Example #1
0
def save_settings(context):    
    scene = context.scene
    config_updates = {}
    
    jar_path = os.path.abspath(efutil.filesystem_path(scene.sunflow_renderconfigure.sunflowPath))
    if os.path.exists(jar_path):
        config_updates['jar_path'] = jar_path
    else:
        sunflowLog("Unable to find path jar_path")
    
    java_path = os.path.abspath(efutil.filesystem_path(scene.sunflow_renderconfigure.javaPath))
    # if os.path.isdir(java_path) and os.path.exists(java_path):
    if os.path.exists(java_path):
        config_updates['java_path'] = java_path
    else:
        sunflowLog("Unable to find path java_path")
        
    
    memoryalloc = scene.sunflow_renderconfigure.memoryAllocated
    config_updates['memoryalloc'] = memoryalloc
    
        
    try:
        for k, v in config_updates.items():
            efutil.write_config_value('sunflow', 'defaults', k, v)
            sunflowLog("writing values")
    except Exception as err:
        sunflowLog('WARNING: Saving sunflow configuration failed, please set your user scripts dir: %s' % err)
Example #2
0
def save_settings(context):
    scene = context.scene
    config_updates = {}

    jar_path = os.path.abspath(
        efutil.filesystem_path(scene.sunflow_renderconfigure.sunflowPath))
    if os.path.exists(jar_path):
        config_updates['jar_path'] = jar_path
    else:
        sunflowLog("Unable to find path jar_path")

    java_path = os.path.abspath(
        efutil.filesystem_path(scene.sunflow_renderconfigure.javaPath))
    # if os.path.isdir(java_path) and os.path.exists(java_path):
    if os.path.exists(java_path):
        config_updates['java_path'] = java_path
    else:
        sunflowLog("Unable to find path java_path")

    memoryalloc = scene.sunflow_renderconfigure.memoryAllocated
    config_updates['memoryalloc'] = memoryalloc

    try:
        for k, v in config_updates.items():
            efutil.write_config_value('sunflow', 'defaults', k, v)
            sunflowLog("writing values")
    except Exception as err:
        sunflowLog(
            'WARNING: Saving sunflow configuration failed, please set your user scripts dir: %s'
            % err)
Example #3
0
def process_filepath_data(scene, obj, file_path, paramset, parameter_name):
	file_basename		= os.path.basename(file_path)
	library_filepath	= obj.library.filepath if (hasattr(obj, 'library') and obj.library) else ''
	file_library_path	= efutil.filesystem_path(bpy.path.abspath(file_path, library_filepath))
	file_relative		= efutil.filesystem_path(file_library_path) if (hasattr(obj, 'library') and obj.library) else efutil.filesystem_path(file_path)
	
	if scene.luxrender_engine.allow_file_embed():
		paramset.add_string(parameter_name, file_basename)
		encoded_data, encoded_size = bencode_file2string_with_size(file_relative)
		paramset.increase_size('%s_data' % parameter_name, encoded_size)
		paramset.add_string('%s_data' % parameter_name, encoded_data.splitlines() )
	else:
		paramset.add_string(parameter_name, file_relative)
Example #4
0
    def get_additional_elements(self, obj):
        d = {}

        for ms in obj.material_slots:
            mat = ms.material
            if mat == None: continue
            ie = mat.indigo_material.indigo_material_emission
            if ie.emission_enabled and ie.emit_ies:
                d['ies_profile'] = {
                    'material_name': [mat.name],
                    'path': [efutil.filesystem_path(ie.emit_ies_path)]
                }

        for ms in obj.material_slots:
            mat = ms.material
            if mat == None: continue
            ie = mat.indigo_material.indigo_material_emission
            if ie.emission_enabled and ie.emission_scale:
                d['emission_scale'] = {
                    'material_name': [mat.name],
                    'measure': [ie.emission_scale_measure],
                    'value': [ie.emission_scale_value * 10**ie.emission_scale_exp]
                }

        if(obj.data != None and obj.data.indigo_mesh.invisible_to_camera):
            d['invisible_to_camera'] = ["true"]

        return d
Example #5
0
def getInstallPath(scene=None):
    # Can use scene.indigo_engine.exe_path as a hint, if available

    if scene != None:
        sip = filesystem_path(scene.indigo_engine.install_path)
        if sip != "" and os.path.exists(sip):
            if os.path.isdir(sip):
                return sip
            else:
                return os.path.dirname(sip)

    if isLinux():
        return ""  # TODO

    if isMac():
        return "/Applications/Indigo Renderer/Indigo.app"  # Assumption

    if isWindows():
        import winreg
        try:
            hKey = winreg.OpenKey(
                winreg.HKEY_CURRENT_USER,
                r"Software\Glare Technologies\Indigo Renderer")
            value = winreg.QueryValueEx(hKey, "InstallDirectory")[0]
        except:
            value = ""
        return value

    return ""
Example #6
0
def get_pbrt_dir():
    return_path = exporter_common.getPreference().pbrt_export_path
    if return_path is '':
        return ''
    if platform.system() == 'Windows':
        return return_path
    return efutil.filesystem_path(return_path) + "/"
Example #7
0
def getInstallPath(scene=None):
    # Can use scene.indigo_engine.exe_path as a hint, if available

    if scene != None:
        sip = efutil.filesystem_path(scene.indigo_engine.install_path)
        if sip != "" and os.path.exists(sip):
            if os.path.isdir(sip):
                return sip
            else:
                return os.path.dirname(sip)

    if isLinux():
        return "" # TODO

    if isMac():
        return "/Applications/Indigo Renderer/Indigo.app" # Assumption

    if isWindows():
        import winreg
        try:
            hKey = winreg.OpenKey (winreg.HKEY_CURRENT_USER, r"Software\Glare Technologies\Indigo Renderer")
            value = winreg.QueryValueEx (hKey, "InstallDirectory")[0]
        except:
            value = ""
        return value

    return ""
Example #8
0
 def check_output_path(self, path):
     efutil.export_path = efutil.filesystem_path(path)
     
     if not os.path.isdir(efutil.export_path):
         parent_dir = os.path.realpath( os.path.join(efutil.export_path, os.path.pardir) )
         if not self.check_write(parent_dir):
             indigo_log('Output path "%s" is not writable' % parent_dir)
             raise Exception('Output path is not writable')
         
         try:
             os.makedirs(efutil.export_path)
         except: 
             indigo_log('Could not create output path %s' % efutil.export_path)
             raise Exception('Could not create output path')
     
     if not self.check_write(efutil.export_path):
         indigo_log('Output path "%s" is not writable' % efutil.export_path)
         raise Exception('Output path is not writable')
     
     igs_filename = '/'.join( (efutil.export_path, self.properties.filename) )
     
     # indigo_log('Writing to %s'%igs_filename)
     
     if efutil.export_path[-1] not in ('/', '\\'):
         efutil.export_path += '/'
     
     try:
         out_file = open(igs_filename, 'w')
         out_file.close()
     except:
         indigo_log('Failed to open output file "%s" for writing: check output path setting' % igs_filename)
         raise Exception('Failed to open output file for writing: check output path setting')
     
     return igs_filename
Example #9
0
 def check_output_path(self, path):
     efutil.export_path = efutil.filesystem_path(path)
     
     if not os.path.isdir(efutil.export_path):
         parent_dir = os.path.realpath( os.path.join(efutil.export_path, os.path.pardir) )
         if not self.check_write(parent_dir):
             indigo_log('Output path "%s" is not writable' % parent_dir)
             raise Exception('Output path is not writable')
         
         try:
             os.makedirs(efutil.export_path)
         except: 
             indigo_log('Could not create output path %s' % efutil.export_path)
             raise Exception('Could not create output path')
     
     if not self.check_write(efutil.export_path):
         indigo_log('Output path "%s" is not writable' % efutil.export_path)
         raise Exception('Output path is not writable')
     
     igs_filename = '/'.join( (efutil.export_path, self.properties.filename) )
     
     # indigo_log('Writing to %s'%igs_filename)
     
     if efutil.export_path[-1] not in ('/', '\\'):
         efutil.export_path += '/'
     
     try:
         out_file = open(igs_filename, 'w')
         out_file.close()
     except:
         indigo_log('Failed to open output file "%s" for writing: check output path setting' % igs_filename)
         raise Exception('Failed to open output file for writing: check output path setting')
     
     return igs_filename
Example #10
0
def get_sort_dir(force_debug=False):
    addon_prefs = bpy.context.user_preferences.addons[common.preference_bl_name].preferences
    debug = bpy.context.scene.debug_prop
    return_path = addon_prefs.install_path
    if debug is True:
        return_path = addon_prefs.install_path_debug
    if force_debug:
        return_path = addon_prefs.install_path_debug
    return efutil.filesystem_path(return_path) + "/"
Example #11
0
def process_filepath_data(scene, obj, file_path, paramset, parameter_name):
    file_basename = os.path.basename(file_path)
    library_filepath = obj.library.filepath if (hasattr(obj, 'library')
                                                and obj.library) else ''
    file_library_path = efutil.filesystem_path(
        bpy.path.abspath(file_path, library_filepath))
    file_relative = efutil.filesystem_path(file_library_path) if (hasattr(
        obj, 'library') and obj.library) else efutil.filesystem_path(file_path)

    if scene.luxrender_engine.allow_file_embed():
        paramset.add_string(parameter_name, file_basename)
        encoded_data, encoded_size = bencode_file2string_with_size(
            file_relative)
        paramset.increase_size('%s_data' % parameter_name, encoded_size)
        paramset.add_string('%s_data' % parameter_name,
                            encoded_data.splitlines())
    else:
        paramset.add_string(parameter_name, file_relative)
Example #12
0
def getServices():
    cube = bpy.context.scene.objects['Cube']
    path = cube.material_slots[0].material.texture_slots[0].texture.image.filepath
    xfac = efutil.filesystem_path(path)
    print("path now>> %s" % xfac)
    abs = os.path.abspath(xfac)
    print("path abs>> %s" % abs)
    rel = efutil.path_relative_to_export(path)
    print("path rel>> %s" % rel)
Example #13
0
def getServices():
    cube = bpy.context.scene.objects['Cube']
    path = cube.material_slots[0].material.texture_slots[
        0].texture.image.filepath
    xfac = efutil.filesystem_path(path)
    print("path now>> %s" % xfac)
    abs = os.path.abspath(xfac)
    print("path abs>> %s" % abs)
    rel = efutil.path_relative_to_export(path)
    print("path rel>> %s" % rel)
Example #14
0
def get_sort_dir(force_debug=False):
    addon_prefs = bpy.context.user_preferences.addons[
        common.preference_bl_name].preferences
    debug = bpy.context.scene.debug_prop
    return_path = addon_prefs.install_path
    if debug is True:
        return_path = addon_prefs.install_path_debug
    if force_debug:
        return_path = addon_prefs.install_path_debug
    return efutil.filesystem_path(return_path) + "/"
Example #15
0
    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
Example #16
0
	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
Example #17
0
 def build_xml_element(self, scene):
     xml = self.Element('tonemapping')
     
     # format needs to be entirely generated at export time
     if self.tonemap_type == 'reinhard':
         xml_format = {
             'reinhard': {
                 'pre_scale': 'reinhard_pre',
                 'post_scale': 'reinhard_post',
                 'burn': 'reinhard_burn',
             }
         }
     elif self.tonemap_type == 'linear':
         xml_format = {
             'linear': {
                 'scale': 'linear_unit',
             }
         }
     elif self.tonemap_type == 'camera':
         if self.camera_response_type == 'preset':
             crf = [self.camera_response_preset]
         elif self.camera_response_file!="" and os.path.exists(efutil.filesystem_path(self.camera_response_file)):
             crf = 'camera_response_file'
         else:
             indigo_log('WARNING: Invalid camera tonemapping, using default dscs315.txt')
             crf = ['data/camera_response_functions/dscs315.txt']
         xml_format = {
             'camera': {
                 'response_function_path': crf,
                 'ev_adjust': 'camera_ev',
                 'film_iso': [scene.camera.data.indigo_camera.iso]
             }
         }
     elif self.tonemap_type == 'filmic':
         xml_format = {
             'filmic': {
                 'scale': 'filmic_scale',
             }
         }
     else:
         xml_format = {}
     
     self.build_subelements(scene, xml_format, xml)
     
     return xml
Example #18
0
 def build_xml_element(self, scene):
     xml = self.Element('tonemapping')
     
     # format needs to be entirely generated at export time
     if self.tonemap_type == 'reinhard':
         xml_format = {
             'reinhard': {
                 'pre_scale': 'reinhard_pre',
                 'post_scale': 'reinhard_post',
                 'burn': 'reinhard_burn',
             }
         }
     elif self.tonemap_type == 'linear':
         xml_format = {
             'linear': {
                 'scale': 'linear_unit',
             }
         }
     elif self.tonemap_type == 'camera':
         if self.camera_response_type == 'preset':
             crf = [self.camera_response_preset]
         elif self.camera_response_file!="" and os.path.exists(efutil.filesystem_path(self.camera_response_file)):
             crf = 'camera_response_file'
         else:
             indigo_log('WARNING: Invalid camera tonemapping, using default dscs315.txt')
             crf = ['data/camera_response_functions/dscs315.txt']
         xml_format = {
             'camera': {
                 'response_function_path': crf,
                 'ev_adjust': 'camera_ev',
                 'film_iso': [scene.camera.data.indigo_camera.iso]
             }
         }
     else:
         xml_format = {}
     
     self.build_subelements(scene, xml_format, xml)
     
     return xml
Example #19
0
	def render(self, scene):
		if self is None or scene is None:
			MtsLog('ERROR: Scene is missing!')
			return
		if scene.mitsuba_engine.binary_path == '':
			MtsLog('ERROR: The binary path is unspecified!')
			return
		
		with self.render_lock:	# just render one thing at a time
			if scene.name == 'preview':
				self.render_preview(scene)
				return
			
			config_updates = {}
			binary_path = os.path.abspath(efutil.filesystem_path(scene.mitsuba_engine.binary_path))
			if os.path.isdir(binary_path) and os.path.exists(binary_path):
				config_updates['binary_path'] = binary_path
			
			try:
				for k, v in config_updates.items():
					efutil.write_config_value('mitsuba', 'defaults', k, v)
			except Exception as err:
				MtsLog('WARNING: Saving Mitsuba configuration failed, please set your user scripts dir: %s' % err)
			
			scene_path = efutil.filesystem_path(scene.render.filepath)
			if os.path.isdir(scene_path):
				output_dir = scene_path
			else:
				output_dir = os.path.dirname(scene_path)		
			
			MtsLog('MtsBlend: Current directory = "%s"' % output_dir)
			output_basename = efutil.scene_filename() + '.%s.%05i' % (scene.name, scene.frame_current)
			
			result = SceneExporter(
				directory = output_dir,
				filename = output_basename,
			).export(scene)
			
			if not result:
				MtsLog('Error while exporting -- check the console for details.')
				return
			
			if scene.mitsuba_engine.export_mode == 'render':
				
				MtsLog("MtsBlend: Launching renderer ..")
				if scene.mitsuba_engine.render_mode == 'gui':
					MtsLaunch(scene.mitsuba_engine.binary_path, output_dir,
						['mtsgui', efutil.export_path])
				elif scene.mitsuba_engine.render_mode == 'cli':
					output_file = efutil.export_path[:-4] + "." + scene.camera.data.mitsuba_film.fileExtension
					mitsuba_process = MtsLaunch(scene.mitsuba_engine.binary_path, output_dir,
						['mitsuba', '-r', str(scene.mitsuba_engine.refresh_interval),
							'-o', output_file, efutil.export_path]
					)
					framebuffer_thread = MtsFilmDisplay()
					framebuffer_thread.set_kick_period(scene.mitsuba_engine.refresh_interval) 
					framebuffer_thread.begin(self, output_file, resolution(scene))
					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()
					
					# If we exit the wait loop (user cancelled) and mitsuba is still running, then send SIGINT
					if mitsuba_process.poll() == None:
						# Use SIGTERM because that's the only one supported on Windows
						mitsuba_process.send_signal(subprocess.signal.SIGTERM)
					
					# Stop updating the render result and load the final image
					framebuffer_thread.stop()
					framebuffer_thread.join()
					
					if mitsuba_process.poll() != None and mitsuba_process.returncode != 0:
						MtsLog("MtsBlend: Rendering failed -- check the console")
					else:
						framebuffer_thread.kick(render_end=True)
					framebuffer_thread.shutdown()
Example #20
0
    def render(self, scene):
        if self is None or scene is None:
            MtsLog('ERROR: Scene is missing!')
            return
        if scene.mitsuba_engine.binary_path == '':
            MtsLog('ERROR: The binary path is unspecified!')
            return

        with self.render_lock:  # just render one thing at a time
            if scene.name == 'preview':
                self.render_preview(scene)
                return

            config_updates = {}
            binary_path = os.path.abspath(
                efutil.filesystem_path(scene.mitsuba_engine.binary_path))
            if os.path.isdir(binary_path) and os.path.exists(binary_path):
                config_updates['binary_path'] = binary_path

            try:
                for k, v in config_updates.items():
                    efutil.write_config_value('mitsuba', 'defaults', k, v)
            except Exception as err:
                MtsLog(
                    'WARNING: Saving Mitsuba configuration failed, please set your user scripts dir: %s'
                    % err)

            scene_path = efutil.filesystem_path(scene.render.filepath)
            if os.path.isdir(scene_path):
                output_dir = scene_path
            else:
                output_dir = os.path.dirname(scene_path)

            MtsLog('MtsBlend: Current directory = "%s"' % output_dir)
            output_basename = efutil.scene_filename() + '.%s.%05i' % (
                scene.name, scene.frame_current)

            result = SceneExporter(
                directory=output_dir,
                filename=output_basename,
            ).export(scene)

            if not result:
                MtsLog(
                    'Error while exporting -- check the console for details.')
                return

            if scene.mitsuba_engine.export_mode == 'render':

                MtsLog("MtsBlend: Launching renderer ..")
                if scene.mitsuba_engine.render_mode == 'gui':
                    MtsLaunch(scene.mitsuba_engine.binary_path, output_dir,
                              ['mtsgui', efutil.export_path])
                elif scene.mitsuba_engine.render_mode == 'cli':
                    output_file = efutil.export_path[:
                                                     -4] + "." + scene.camera.data.mitsuba_film.fileExtension
                    mitsuba_process = MtsLaunch(
                        scene.mitsuba_engine.binary_path, output_dir, [
                            'mitsuba', '-r',
                            str(scene.mitsuba_engine.refresh_interval), '-o',
                            output_file, efutil.export_path
                        ])
                    framebuffer_thread = MtsFilmDisplay()
                    framebuffer_thread.set_kick_period(
                        scene.mitsuba_engine.refresh_interval)
                    framebuffer_thread.begin(self, output_file,
                                             resolution(scene))
                    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()

                    # If we exit the wait loop (user cancelled) and mitsuba is still running, then send SIGINT
                    if mitsuba_process.poll() == None:
                        # Use SIGTERM because that's the only one supported on Windows
                        mitsuba_process.send_signal(subprocess.signal.SIGTERM)

                    # Stop updating the render result and load the final image
                    framebuffer_thread.stop()
                    framebuffer_thread.join()

                    if mitsuba_process.poll(
                    ) != None and mitsuba_process.returncode != 0:
                        MtsLog(
                            "MtsBlend: Rendering failed -- check the console")
                    else:
                        framebuffer_thread.kick(render_end=True)
                    framebuffer_thread.shutdown()
Example #21
0
def convert_texture(scene, texture, variant_hint=None):
    # Lux only supports blender's textures in float variant (except for image/ocean, but both of these are exported as imagemap)
    variant = 'float'
    paramset = ParamSet()

    lux_tex_name = 'blender_%s' % texture.type.lower()

    mapping_type = '3D'

    if texture.type not in ('IMAGE', 'OCEAN'):
        paramset.add_float('bright', texture.intensity)
        paramset.add_float('contrast', texture.contrast)

    if texture.type == 'BLEND':
        progression_map = {
            'LINEAR': 'lin',
            'QUADRATIC': 'quad',
            'EASING': 'ease',
            'DIAGONAL': 'diag',
            'SPHERICAL': 'sphere',
            'QUADRATIC_SPHERE': 'halo',
            'RADIAL': 'radial',
        }
        paramset.add_bool('flipxy', texture.use_flip_axis) \
          .add_string('type', progression_map[texture.progression])

    if texture.type == 'CLOUDS':
        paramset.add_string('noisetype', texture.noise_type.lower() ) \
          .add_string('noisebasis', texture.noise_basis.lower() ) \
          .add_float('noisesize', texture.noise_scale) \
          .add_integer('noisedepth', texture.noise_depth)

    if texture.type == 'DISTORTED_NOISE':
        lux_tex_name = 'blender_distortednoise'
        paramset.add_string('type', texture.noise_distortion.lower()) \
          .add_string('noisebasis', texture.noise_basis.lower() ) \
          .add_float('distamount', texture.distortion) \
          .add_float('noisesize', texture.noise_scale) \
          .add_float('nabla', texture.nabla)

    if texture.type == 'MAGIC':
        paramset.add_integer('noisedepth', texture.noise_depth) \
          .add_float('turbulence', texture.turbulence)

    if texture.type == 'MARBLE':
        paramset.add_string('type', texture.marble_type.lower() ) \
          .add_string('noisetype', texture.noise_type.lower() ) \
          .add_string('noisebasis', texture.noise_basis.lower() ) \
          .add_string('noisebasis2', texture.noise_basis_2.lower() ) \
          .add_float('noisesize', texture.noise_scale) \
          .add_float('turbulence', texture.turbulence) \
          .add_integer('noisedepth', texture.noise_depth)

    if texture.type == 'MUSGRAVE':
        paramset.add_string('type', texture.musgrave_type.lower() ) \
          .add_float('h', texture.dimension_max) \
          .add_float('lacu', texture.lacunarity) \
          .add_string('noisebasis', texture.noise_basis.lower() ) \
          .add_float('noisesize', texture.noise_scale) \
          .add_float('octs', texture.octaves)

    # NOISE shows no params ?

    if texture.type == 'STUCCI':
        paramset.add_string('type', texture.stucci_type.lower() ) \
          .add_string('noisetype', texture.noise_type.lower() ) \
          .add_string('noisebasis', texture.noise_basis.lower() ) \
          .add_float('noisesize', texture.noise_scale) \
          .add_float('turbulence', texture.turbulence)

    if texture.type == 'VORONOI':
        distancem_map = {
            'DISTANCE': 'actual_distance',
            'DISTANCE_SQUARED': 'distance_squared',
            'MANHATTAN': 'manhattan',
            'CHEBYCHEV': 'chebychev',
            'MINKOVSKY_HALF': 'minkovsky_half',
            'MINKOVSKY_FOUR': 'minkovsky_four',
            'MINKOVSKY': 'minkovsky'
        }
        paramset.add_string('distmetric', distancem_map[texture.distance_metric]) \
          .add_float('minkovsky_exp', texture.minkovsky_exponent) \
          .add_float('noisesize', texture.noise_scale) \
          .add_float('nabla', texture.nabla) \
          .add_float('w1', texture.weight_1) \
          .add_float('w2', texture.weight_2) \
          .add_float('w3', texture.weight_3) \
          .add_float('w4', texture.weight_4)

    if texture.type == 'WOOD':
        paramset.add_string('noisebasis', texture.noise_basis.lower() ) \
          .add_string('noisebasis2', texture.noise_basis_2.lower() ) \
          .add_float('noisesize', texture.noise_scale) \
          .add_string('noisetype', texture.noise_type.lower() ) \
          .add_float('turbulence', texture.turbulence) \
          .add_string('type', texture.wood_type.lower() )

    # Translate Blender Image/movie into lux tex
    if texture.type == 'IMAGE' and texture.image and texture.image.source in [
            'GENERATED', 'FILE', 'SEQUENCE'
    ]:

        extract_path = os.path.join(efutil.scene_filename(),
                                    bpy.path.clean_name(scene.name),
                                    '%05d' % scene.frame_current)

        if texture.image.source == 'GENERATED':
            tex_image = 'luxblend_baked_image_%s.%s' % (bpy.path.clean_name(
                texture.name), scene.render.image_settings.file_format)
            tex_image = os.path.join(extract_path, tex_image)
            texture.image.save_render(tex_image, scene)

        if texture.image.source == 'FILE':
            if texture.image.packed_file:
                tex_image = 'luxblend_extracted_image_%s.%s' % (
                    bpy.path.clean_name(
                        texture.name), scene.render.image_settings.file_format)
                tex_image = os.path.join(extract_path, tex_image)
                texture.image.save_render(tex_image, scene)
            else:
                if texture.library is not None:
                    f_path = efutil.filesystem_path(
                        bpy.path.abspath(texture.image.filepath,
                                         texture.library.filepath))
                else:
                    f_path = efutil.filesystem_path(texture.image.filepath)
                if not os.path.exists(f_path):
                    raise Exception(
                        'Image referenced in blender texture %s doesn\'t exist: %s'
                        % (texture.name, f_path))
                tex_image = efutil.filesystem_path(f_path)

        if texture.image.source == 'SEQUENCE':
            if texture.image.packed_file:
                tex_image = 'luxblend_extracted_image_%s.%s' % (
                    bpy.path.clean_name(
                        texture.name), scene.render.image_settings.file_format)
                tex_image = os.path.join(extract_path, tex_image)
                texture.image.save_render(tex_image, scene)
            else:
                # sequence params from blender
                sequence = bpy.data.textures[(texture.name).replace(
                    '.001', ''
                )].image_user  # remove tex_preview extension to avoid error
                seqframes = sequence.frame_duration
                seqoffset = sequence.frame_offset
                seqstartframe = sequence.frame_start  # the global frame at which the imagesequence starts
                seqcyclic = sequence.use_cyclic
                currentframe = scene.frame_current

                if texture.library is not None:
                    f_path = efutil.filesystem_path(
                        bpy.path.abspath(texture.image.filepath,
                                         texture.library.filepath))
                else:
                    f_path = efutil.filesystem_path(texture.image.filepath)

                if currentframe < seqstartframe:
                    fnumber = 1 + seqoffset
                else:
                    fnumber = currentframe - (seqstartframe - 1) + seqoffset

                if fnumber > seqframes:
                    if seqcyclic == False:
                        fnumber = seqframes
                    else:
                        fnumber = (currentframe -
                                   (seqstartframe - 1)) % seqframes
                        if fnumber == 0:
                            fnumber = seqframes

                import re

                def get_seq_filename(number, f_path):
                    m = re.findall(r'(\d+)', f_path)
                    if len(m) == 0:
                        return "ERR: Can't find pattern"

                    rightmost_number = m[len(m) - 1]
                    seq_length = len(rightmost_number)

                    nstr = "%i" % number
                    new_seq_number = nstr.zfill(seq_length)

                    return f_path.replace(rightmost_number, new_seq_number)

                f_path = get_seq_filename(fnumber, f_path)

                #				print("-----------------", f_path)

                if not os.path.exists(f_path):
                    raise Exception(
                        'Image referenced in blender texture %s doesn\'t exist: %s'
                        % (texture.name, f_path))
                tex_image = efutil.filesystem_path(f_path)

        lux_tex_name = 'imagemap'
        sampling = texture.luxrender_texture.luxrender_tex_imagesampling
        if variant_hint:
            variant = variant_hint
        else:
            variant = 'color'
        paramset.add_string('filename', tex_image)
        if variant_hint == float:
            paramset.add_string('channel', sampling.channel)
        paramset.add_integer('discardmipmaps', sampling.discardmipmaps)
        paramset.add_float('gain', sampling.gain)
        paramset.add_float('gamma', sampling.gamma)
        paramset.add_float('maxanisotropy', sampling.maxanisotropy)
        paramset.add_string('wrap', sampling.wrap)
        mapping_type = '2D'

    # Similar to image handler, but for Ocean tex
    if texture.type == 'OCEAN':
        if texture.ocean.output == 'FOAM':

            ocean_mods = [
                m for m in texture.ocean.ocean_object.modifiers
                if m.type == 'OCEAN'
            ]
            if len(ocean_mods) == 0:
                print('No ocean modifiers!')
            else:
                ocean_mod = ocean_mods[0]

            if texture.ocean.output == 'FOAM':
                tex_image = efutil.filesystem_path(
                    os.path.join(ocean_mod.filepath,
                                 'foam_%04d.exr' % scene.frame_current))
            #SOON! (until 3D disp support...)
            #elif texture.ocean.output == 'DISPLACEMENT':
            #tex_image = os.path.join(ocean_mod.filepath, 'disp_%04d.exr' % scene.frame_current)

            lux_tex_name = 'imagemap'
            if variant_hint:
                variant = variant_hint
            else:
                variant = 'color'
            paramset.add_string('filename', tex_image)
            paramset.add_float('gamma', 1.0)
            mapping_type = '2D'

        else:
            lux_tex_name = 'constant'

    if mapping_type == '3D':
        paramset.update(
            texture.luxrender_texture.luxrender_tex_transform.get_paramset(
                scene))
    else:
        paramset.update(
            texture.luxrender_texture.luxrender_tex_mapping.get_paramset(
                scene))

    return variant, lux_tex_name, paramset
Example #22
0
def convert_texture(scene, texture, variant_hint=None):
	# Lux only supports blender's textures in float variant (except for image/ocean, but both of these are exported as imagemap)
	variant = 'float'
	paramset = ParamSet()
	
	lux_tex_name = 'blender_%s' % texture.type.lower()
	
	mapping_type = '3D'
	
	if texture.type not in ('IMAGE', 'OCEAN'):
		paramset.add_float('bright', texture.intensity)
		paramset.add_float('contrast', texture.contrast)
	
	if texture.type == 'BLEND':
		progression_map = {
			'LINEAR':			'lin',
			'QUADRATIC':		'quad',
			'EASING':			'ease',
			'DIAGONAL':			'diag',
			'SPHERICAL':		'sphere',
			'QUADRATIC_SPHERE':	'halo',
			'RADIAL':			'radial',
		}
		paramset.add_bool('flipxy', texture.use_flip_axis) \
				.add_string('type', progression_map[texture.progression])
	
	if texture.type == 'CLOUDS':
		paramset.add_string('noisetype', texture.noise_type.lower() ) \
				.add_string('noisebasis', texture.noise_basis.lower() ) \
				.add_float('noisesize', texture.noise_scale) \
				.add_integer('noisedepth', texture.noise_depth)
	
	if texture.type == 'DISTORTED_NOISE':
		lux_tex_name = 'blender_distortednoise'
		paramset.add_string('type', texture.noise_distortion.lower()) \
				.add_string('noisebasis', texture.noise_basis.lower() ) \
				.add_float('distamount', texture.distortion) \
				.add_float('noisesize', texture.noise_scale) \
				.add_float('nabla', texture.nabla)
	
	if texture.type == 'MAGIC':
		paramset.add_integer('noisedepth', texture.noise_depth) \
				.add_float('turbulence', texture.turbulence)
	
	if texture.type == 'MARBLE':
		paramset.add_string('type', texture.marble_type.lower() ) \
				.add_string('noisetype', texture.noise_type.lower() ) \
				.add_string('noisebasis', texture.noise_basis.lower() ) \
				.add_string('noisebasis2', texture.noise_basis_2.lower() ) \
				.add_float('noisesize', texture.noise_scale) \
				.add_float('turbulence', texture.turbulence) \
				.add_integer('noisedepth', texture.noise_depth)
	
	if texture.type == 'MUSGRAVE':
		paramset.add_string('type', texture.musgrave_type.lower() ) \
				.add_float('h', texture.dimension_max) \
				.add_float('lacu', texture.lacunarity) \
				.add_string('noisebasis', texture.noise_basis.lower() ) \
				.add_float('noisesize', texture.noise_scale) \
				.add_float('octs', texture.octaves)
	
	# NOISE shows no params ?
	
	if texture.type == 'STUCCI':
		paramset.add_string('type', texture.stucci_type.lower() ) \
				.add_string('noisetype', texture.noise_type.lower() ) \
				.add_string('noisebasis', texture.noise_basis.lower() ) \
				.add_float('noisesize', texture.noise_scale) \
				.add_float('turbulence', texture.turbulence)
	
	if texture.type == 'VORONOI':
		distancem_map = {
			'DISTANCE': 'actual_distance',
			'DISTANCE_SQUARED': 'distance_squared',
			'MANHATTAN': 'manhattan',
			'CHEBYCHEV': 'chebychev',
			'MINKOVSKY_HALF': 'minkovsky_half',
			'MINKOVSKY_FOUR': 'minkovsky_four',
			'MINKOVSKY': 'minkovsky'
		}
		paramset.add_string('distmetric', distancem_map[texture.distance_metric]) \
				.add_float('minkovsky_exp', texture.minkovsky_exponent) \
				.add_float('noisesize', texture.noise_scale) \
				.add_float('nabla', texture.nabla) \
				.add_float('w1', texture.weight_1) \
				.add_float('w2', texture.weight_2) \
				.add_float('w3', texture.weight_3) \
				.add_float('w4', texture.weight_4)
	
	if texture.type == 'WOOD':
		paramset.add_string('noisebasis', texture.noise_basis.lower() ) \
				.add_string('noisebasis2', texture.noise_basis_2.lower() ) \
				.add_float('noisesize', texture.noise_scale) \
				.add_string('noisetype', texture.noise_type.lower() ) \
				.add_float('turbulence', texture.turbulence) \
				.add_string('type', texture.wood_type.lower() )
	
	# Translate Blender Image/movie into lux tex
	if texture.type == 'IMAGE' and texture.image and texture.image.source in ['GENERATED', 'FILE', 'SEQUENCE']:
		
		extract_path = os.path.join(
			efutil.scene_filename(),
			bpy.path.clean_name(scene.name),
			'%05d' % scene.frame_current
		)
		
		if texture.image.source == 'GENERATED':
			tex_image = 'luxblend_baked_image_%s.%s' % (bpy.path.clean_name(texture.name), scene.render.image_settings.file_format)
			tex_image = os.path.join(extract_path, tex_image)
			texture.image.save_render(tex_image, scene)
		
		if texture.image.source == 'FILE':
			if texture.image.packed_file:
				tex_image = 'luxblend_extracted_image_%s.%s' % (bpy.path.clean_name(texture.name), scene.render.image_settings.file_format)
				tex_image = os.path.join(extract_path, tex_image)
				texture.image.save_render(tex_image, scene)
			else:
				if texture.library is not None:
					f_path = efutil.filesystem_path(bpy.path.abspath( texture.image.filepath, texture.library.filepath))
				else:
					f_path = efutil.filesystem_path(texture.image.filepath)
				if not os.path.exists(f_path):
					raise Exception('Image referenced in blender texture %s doesn\'t exist: %s' % (texture.name, f_path))
				tex_image = efutil.filesystem_path(f_path)

		if texture.image.source == 'SEQUENCE':
			if texture.image.packed_file:
				tex_image = 'luxblend_extracted_image_%s.%s' % (bpy.path.clean_name(texture.name), scene.render.image_settings.file_format)
				tex_image = os.path.join(extract_path, tex_image)
				texture.image.save_render(tex_image, scene)
			else:
				# sequence params from blender
				sequence = bpy.data.textures[(texture.name).replace('.001', '')].image_user # remove tex_preview extension to avoid error
				seqframes = sequence.frame_duration
				seqoffset = sequence.frame_offset
				seqstartframe = sequence.frame_start # the global frame at which the imagesequence starts
				seqcyclic = sequence.use_cyclic
				currentframe = scene.frame_current
				
				if texture.library is not None:
					f_path = efutil.filesystem_path(bpy.path.abspath( texture.image.filepath, texture.library.filepath))
				else:
					f_path = efutil.filesystem_path(texture.image.filepath)

				if currentframe < seqstartframe:
					fnumber = 1 + seqoffset
				else:
					fnumber = currentframe - (seqstartframe-1) + seqoffset

				if fnumber > seqframes:
					if seqcyclic == False:
						fnumber = seqframes
					else:
						fnumber = (currentframe - (seqstartframe-1)) % seqframes
						if fnumber == 0:
							fnumber = seqframes

				import re
				def get_seq_filename(number, f_path):
					m = re.findall(r'(\d+)', f_path)
					if len(m) == 0:
						return "ERR: Can't find pattern"
					
					rightmost_number = m[len(m)-1]
					seq_length = len(rightmost_number)
					
					nstr = "%i" %number
					new_seq_number = nstr.zfill(seq_length)
					
					return f_path.replace(rightmost_number, new_seq_number)

				f_path = get_seq_filename(fnumber, f_path)
				
#				print("-----------------", f_path)

				if not os.path.exists(f_path):
					raise Exception('Image referenced in blender texture %s doesn\'t exist: %s' % (texture.name, f_path))
				tex_image = efutil.filesystem_path(f_path)


		lux_tex_name = 'imagemap'
		sampling = texture.luxrender_texture.luxrender_tex_imagesampling
		if variant_hint:
			variant = variant_hint
		else:
			variant = 'color'
		paramset.add_string('filename', tex_image)
		if variant_hint == float:
			paramset.add_string('channel', sampling.channel)
		paramset.add_integer('discardmipmaps', sampling.discardmipmaps)
		paramset.add_float('gain', sampling.gain)
		paramset.add_float('gamma', sampling.gamma)
		paramset.add_float('maxanisotropy', sampling.maxanisotropy)
		paramset.add_string('wrap', sampling.wrap)
		mapping_type = '2D'
	
	# Similar to image handler, but for Ocean tex
	if texture.type == 'OCEAN':
		if texture.ocean.output == 'FOAM':

			ocean_mods = [m for m in texture.ocean.ocean_object.modifiers if m.type == 'OCEAN']
			if len(ocean_mods) == 0:
				print ('No ocean modifiers!')
			else:
				ocean_mod = ocean_mods[0]
			
			if texture.ocean.output == 'FOAM':
				tex_image = efutil.filesystem_path(os.path.join(ocean_mod.filepath, 'foam_%04d.exr' % scene.frame_current)) 
			#SOON! (until 3D disp support...)
			#elif texture.ocean.output == 'DISPLACEMENT':
				#tex_image = os.path.join(ocean_mod.filepath, 'disp_%04d.exr' % scene.frame_current) 
			
			lux_tex_name = 'imagemap'
			if variant_hint:
				variant = variant_hint
			else:
				variant = 'color'
			paramset.add_string('filename', tex_image)
			paramset.add_float('gamma', 1.0)
			mapping_type = '2D'
			
		else:
			lux_tex_name = 'constant'
		
	if mapping_type == '3D':
		paramset.update( texture.luxrender_texture.luxrender_tex_transform.get_paramset(scene) )
	else:
		paramset.update( texture.luxrender_texture.luxrender_tex_mapping.get_paramset(scene) )
	
	return variant, lux_tex_name, paramset
Example #23
0
def convert_texture(scene, texture, variant_hint=None):
	# Lux only supports blender's textures in float variant (except for image/ocean (both of these are exported as imagemap)
	variant = 'float'
	paramset = ParamSet()
	
	lux_tex_name = 'blender_%s' % texture.type.lower()
	
	mapping_type = '3D'
	
	if texture.type not in ('IMAGE', 'OCEAN'):
		paramset.add_float('bright', texture.intensity)
		paramset.add_float('contrast', texture.contrast)
	
	if texture.type == 'BLEND':
		progression_map = {
			'LINEAR':			'lin',
			'QUADRATIC':		'quad',
			'EASING':			'ease',
			'DIAGONAL':			'diag',
			'SPHERICAL':		'sphere',
			'QUADRATIC_SPHERE':	'halo',
			'RADIAL':			'radial',
		}
		paramset.add_bool('flipxy', texture.use_flip_axis) \
				.add_string('type', progression_map[texture.progression])
	
	if texture.type == 'CLOUDS':
		paramset.add_string('noisetype', texture.noise_type.lower() ) \
				.add_string('noisebasis', texture.noise_basis.lower() ) \
				.add_float('noisesize', texture.noise_scale) \
				.add_integer('noisedepth', texture.noise_depth)
	
	if texture.type == 'DISTORTED_NOISE':
		lux_tex_name = 'blender_distortednoise'
		paramset.add_string('type', texture.noise_distortion.lower()) \
				.add_string('noisebasis', texture.noise_basis.lower() ) \
				.add_float('distamount', texture.distortion) \
				.add_float('noisesize', texture.noise_scale) \
				.add_float('nabla', texture.nabla)
	
	if texture.type == 'MAGIC':
		paramset.add_integer('noisedepth', texture.noise_depth) \
				.add_float('turbulence', texture.turbulence)
	
	if texture.type == 'MARBLE':
		paramset.add_string('type', texture.marble_type.lower() ) \
				.add_string('noisetype', texture.noise_type.lower() ) \
				.add_string('noisebasis', texture.noise_basis.lower() ) \
				.add_string('noisebasis2', texture.noise_basis_2.lower() ) \
				.add_float('noisesize', texture.noise_scale) \
				.add_float('turbulence', texture.turbulence) \
				.add_integer('noisedepth', texture.noise_depth)
	
	if texture.type == 'MUSGRAVE':
		paramset.add_string('type', texture.musgrave_type.lower() ) \
				.add_float('h', texture.dimension_max) \
				.add_float('lacu', texture.lacunarity) \
				.add_string('noisebasis', texture.noise_basis.lower() ) \
				.add_float('noisesize', texture.noise_scale) \
				.add_float('octs', texture.octaves)
	
	# NOISE shows no params ?
	
	if texture.type == 'STUCCI':
		paramset.add_string('type', texture.stucci_type.lower() ) \
				.add_string('noisetype', texture.noise_type.lower() ) \
				.add_string('noisebasis', texture.noise_basis.lower() ) \
				.add_float('noisesize', texture.noise_scale) \
				.add_float('turbulence', texture.turbulence)
	
	if texture.type == 'VORONOI':
		distancem_map = {
			'DISTANCE': 'actual_distance',
			'DISTANCE_SQUARED': 'distance_squared',
			'MANHATTAN': 'manhattan',
			'CHEBYCHEV': 'chebychev',
			'MINKOVSKY_HALF': 'minkovsky_half',
			'MINKOVSKY_FOUR': 'minkovsky_four',
			'MINKOVSKY': 'minkovsky'
		}
		paramset.add_string('distmetric', distancem_map[texture.distance_metric]) \
				.add_float('minkovsky_exp', texture.minkovsky_exponent) \
				.add_float('noisesize', texture.noise_scale) \
				.add_float('nabla', texture.nabla) \
				.add_float('w1', texture.weight_1) \
				.add_float('w2', texture.weight_2) \
				.add_float('w3', texture.weight_3) \
				.add_float('w4', texture.weight_4)
	
	if texture.type == 'WOOD':
		paramset.add_string('noisebasis', texture.noise_basis.lower() ) \
				.add_string('noisebasis2', texture.noise_basis_2.lower() ) \
				.add_float('noisesize', texture.noise_scale) \
				.add_string('noisetype', texture.noise_type.lower() ) \
				.add_float('turbulence', texture.turbulence) \
				.add_string('type', texture.wood_type.lower() )
	
	# Translate Blender Image/movie into lux tex
	if texture.type == 'IMAGE' and texture.image and texture.image.source in ['GENERATED', 'FILE']:
		
		extract_path = os.path.join(
			efutil.scene_filename(),
			bpy.path.clean_name(scene.name),
			'%05d' % scene.frame_current
		)
		
		if texture.image.source == 'GENERATED':
			tex_image = 'luxblend_baked_image_%s.%s' % (bpy.path.clean_name(texture.name), scene.render.image_settings.file_format)
			tex_image = os.path.join(extract_path, tex_image)
			texture.image.save_render(tex_image, scene)
		
		if texture.image.source == 'FILE':
			if texture.image.packed_file:
				tex_image = 'luxblend_extracted_image_%s.%s' % (bpy.path.clean_name(texture.name), scene.render.image_settings.file_format)
				tex_image = os.path.join(extract_path, tex_image)
				texture.image.save_render(tex_image, scene)
			else:
				if texture.library is not None:
					f_path = efutil.filesystem_path(bpy.path.abspath( texture.image.filepath, texture.library.filepath))
				else:
					f_path = efutil.filesystem_path(texture.image.filepath)
				if not os.path.exists(f_path):
					raise Exception('Image referenced in blender texture %s doesn\'t exist: %s' % (texture.name, f_path))
				tex_image = efutil.filesystem_path(f_path)
		
		lux_tex_name = 'imagemap'
		if variant_hint:
			variant = variant_hint
		else:
			variant = 'color'
		paramset.add_string('filename', tex_image)
		paramset.add_float('gamma', 2.2)
		mapping_type = '2D'
	
	# Similar to image handler, but for Ocean tex
	if texture.type == 'OCEAN':
		if texture.ocean.output == 'FOAM':

			ocean_mods = [m for m in texture.ocean.ocean_object.modifiers if m.type == 'OCEAN']
			if len(ocean_mods) == 0:
				print ('No ocean modifiers!')
			else:
				ocean_mod = ocean_mods[0]
			
			if texture.ocean.output == 'FOAM':
				tex_image = efutil.filesystem_path(os.path.join(ocean_mod.filepath, 'foam_%04d.exr' % scene.frame_current)) 
			#SOON! (until 3D disp support...)
			#elif texture.ocean.output == 'DISPLACEMENT':
				#tex_image = os.path.join(ocean_mod.filepath, 'disp_%04d.exr' % scene.frame_current) 
			
			lux_tex_name = 'imagemap'
			if variant_hint:
				variant = variant_hint
			else:
				variant = 'color'
			paramset.add_string('filename', tex_image)
			paramset.add_float('gamma', 1.0)
			mapping_type = '2D'
			
		else:
			lux_tex_name = 'constant'
		
	if mapping_type == '3D':
		paramset.update( texture.luxrender_texture.luxrender_tex_transform.get_paramset(scene) )
	else:
		paramset.update( texture.luxrender_texture.luxrender_tex_mapping.get_paramset(scene) )
	
	return variant, lux_tex_name, paramset
Example #24
0
	def api_output(self):
		'''
		Calculate type and parameters for LuxRender Film statement
		
		Returns		tuple(2) (string, list) 
		'''
		scene = LuxManager.CurrentScene
		
		xr, yr = self.resolution(scene)
		
		params = ParamSet()
		
		if scene.render.use_border: #Border rendering handler, this gets a bit tricky. Blender ALWAYS expects to get back a cropped image, it will handle the padding itself if the user asked for it.
			if scene.render.use_crop_to_border: #user asked to crop, so always crop
				(x1,x2,y1,y2) = [
					scene.render.border_min_x, scene.render.border_max_x,
					scene.render.border_min_y, scene.render.border_max_y
				]
				# Set resolution
				# This is a new method of "rounding" the cropped image to match blenders expected rectangle_size
				# I tested this with several cases which failed with the former rounding, pls check - Jens
				params.add_integer('xresolution', int((xr*x2)-(xr*x1)+1))
				params.add_integer('yresolution', int((yr*y2)-(yr*y1)+1))
			
			if not scene.render.use_crop_to_border: #user asked for padded-to-full-frame output, there are a few cases where Lux needs to do this itself since the rendered image will not be returned to Blender
				if scene.luxrender_engine.render == False or (scene.luxrender_engine.export_type == 'EXT' and scene.luxrender_engine.binary_name == 'luxrender' and scene.luxrender_engine.monitor_external == False): #If run-renderer (scene.luxrender_engine.render) is disabled or we are in un-monitored external mode, we do not return the image to Blender and Lux must pad the image itself
					cropwindow = [
						scene.render.border_min_x, scene.render.border_max_x,
						1-scene.render.border_min_y, 1-scene.render.border_max_y
					] #Subtract scene.render.border Y values from 1 to translate between Blender and Lux conventions
					params.add_float('cropwindow', cropwindow)
					params.add_integer('xresolution', xr) #Don't forget to set full frame resolution
					params.add_integer('yresolution', yr)

					
				else: #we are returning the image to blender which will pad for us, so have LuxRender send back a cropped frame anyway
					(x1,x2,y1,y2) = [
						scene.render.border_min_x, scene.render.border_max_x,
						scene.render.border_min_y, scene.render.border_max_y
					]
					# Set resolution
					# This is a new method of "rounding" the cropped image to match blenders expected rectangle_size
					# I tested this with several cases which failed with the former rounding, pls check - Jens
					params.add_integer('xresolution', int((xr*x2)-(xr*x1)+1))
					params.add_integer('yresolution', int((yr*y2)-(yr*y1)+1))

		else:
			# Set resolution
			params.add_integer('xresolution', xr)
			params.add_integer('yresolution', yr)
		
		
		# ColourSpace
		if self.luxrender_colorspace.preset:
			cs_object = getattr(colorspace_presets, self.luxrender_colorspace.preset_name)
		else:
			cs_object = self.luxrender_colorspace
			
		params.add_float('gamma', self.get_gamma())
		params.add_float('colorspace_white',	[cs_object.cs_whiteX,	cs_object.cs_whiteY])
		params.add_float('colorspace_red',		[cs_object.cs_redX,		cs_object.cs_redY])
		params.add_float('colorspace_green',	[cs_object.cs_greenX,	cs_object.cs_greenY])
		params.add_float('colorspace_blue',		[cs_object.cs_blueX,	cs_object.cs_blueY])
		
		# Camera Response Function
		if LUXRENDER_VERSION >= '0.8' and self.luxrender_colorspace.use_crf == 'file':
			if scene.camera.library is not None:
				local_crf_filepath = bpy.path.abspath(self.luxrender_colorspace.crf_file, scene.camera.library.filepath)
			else:
				local_crf_filepath = self.luxrender_colorspace.crf_file
			local_crf_filepath = efutil.filesystem_path( local_crf_filepath )
			if scene.luxrender_engine.allow_file_embed():
				from ..util import bencode_file2string
				params.add_string('cameraresponse', os.path.basename(local_crf_filepath))
				encoded_data = bencode_file2string(local_crf_filepath)
				params.add_string('cameraresponse_data', encoded_data.splitlines() )
			else:
				params.add_string('cameraresponse', local_crf_filepath)
		if LUXRENDER_VERSION >= '0.8' and self.luxrender_colorspace.use_crf == 'preset':
			params.add_string('cameraresponse', self.luxrender_colorspace.crf_preset)
		
		# Output types
		params.add_string('filename', get_output_filename(scene))
		params.add_bool('write_resume_flm', self.write_flm)
		params.add_bool('restart_resume_flm', self.restart_flm)
		params.add_bool('write_flm_direct', self.write_flm_direct)
		
		if self.output_alpha:
			output_channels = 'RGBA'
			params.add_bool('premultiplyalpha', self.premultiply_alpha)
		else:
			output_channels = 'RGB'
								
		if scene.luxrender_engine.export_type == 'INT' and scene.luxrender_engine.integratedimaging:
			# Set up params to enable z buffer
			# we use the colorspace gamma, else autolinear gives wrong estimation, gamma 1.0 per pixel is recalculated in pylux after
			# Also, this requires tonemapped EXR output
			params.add_string('write_exr_channels', 'RGBA')
			params.add_bool('write_exr_halftype', False)
			params.add_bool('write_exr_applyimaging', True)
			params.add_bool('premultiplyalpha', True if self.output_alpha else False) # Blender 2.66 always expects premultiplyalpha
			params.add_bool('write_exr_ZBuf', True)
			params.add_string('write_exr_zbuf_normalizationtype', 'Camera Start/End clip')
		else:
			# Otherwise let the user decide on tonemapped EXR and other EXR settings
			params.add_bool('write_exr_halftype', self.write_exr_halftype)
			params.add_bool('write_exr_applyimaging', self.write_exr_applyimaging)
			params.add_bool('write_exr_ZBuf', self.write_zbuf)
			params.add_string('write_exr_compressiontype', self.write_exr_compressiontype)
			params.add_string('write_exr_zbuf_normalizationtype', self.zbuf_normalization)
			params.add_bool('write_exr', self.write_exr)
			params.add_string('write_exr_channels', output_channels)
		
		params.add_bool('write_png', self.write_png)
		params.add_string('write_png_channels', output_channels)
		if self.write_png:
			params.add_bool('write_png_16bit', self.write_png_16bit)
		params.add_bool('write_tga', self.write_tga)
		params.add_string('write_tga_channels', output_channels)
		if self.write_tga:
			params.add_bool('write_tga_ZBuf', self.write_zbuf)
			params.add_string('write_tga_zbuf_normalizationtype', self.zbuf_normalization)
		
		params.add_string('ldr_clamp_method', self.ldr_clamp_method)
		
		if scene.luxrender_engine.export_type == 'EXT':
			params.add_integer('displayinterval', self.displayinterval)
			params.add_integer('writeinterval', self.writeinterval)
			params.add_integer('flmwriteinterval', self.flmwriteinterval)
		else:
			params.add_integer('writeinterval', self.internal_updateinterval)
		
		# Halt conditions
		if scene.luxrender_halt.haltspp > 0:
			params.add_integer('haltspp', scene.luxrender_halt.haltspp)
		
		if scene.luxrender_halt.halttime > 0:
			params.add_integer('halttime', scene.luxrender_halt.halttime)

		if scene.luxrender_halt.haltthreshold > 0:
			params.add_float('haltthreshold', 1 - ( scene.luxrender_halt.haltthreshold / 100.00 ))
		
		# Convergence Test
		if scene.luxrender_halt.convergencestep != 32:
			params.add_float('convergencestep', scene.luxrender_halt.convergencestep)
		
		# Filename for User Sampling Map
		if scene.luxrender_sampler.usersamplingmap_filename != '':
			if scene.luxrender_sampler.usersamplingmap_filename.endswith('.exr'):
				params.add_string('usersamplingmap_filename', scene.luxrender_sampler.usersamplingmap_filename)
			else:
				params.add_string('usersamplingmap_filename', scene.luxrender_sampler.usersamplingmap_filename + '.exr')
				
		if self.outlierrejection_k > 0 and scene.luxrender_rendermode.renderer != 'sppm':
			params.add_integer('outlierrejection_k', self.outlierrejection_k)
			
		params.add_integer('tilecount', self.tilecount)
		
		# update the film settings with tonemapper settings
		params.update( self.luxrender_tonemapping.get_paramset() )
		
		return ('fleximage', params)
Example #25
0
def make_path_real(path):
    xfac = efutil.filesystem_path(path)
    return os.path.abspath(xfac)
Example #26
0
 def valid_proxy(self):
     proxy_path = filesystem_path(self.mesh_path)
     return self.mesh_proxy and os.path.exists(proxy_path)
Example #27
0
def make_path_real(path):
    xfac = efutil.filesystem_path(path)
    return os.path.abspath(xfac)
Example #28
0
def get_sort_dir():
    return_path = exporter_common.getPreference().install_path
    if platform.system() == 'Windows':
        return return_path
    return efutil.filesystem_path(return_path) + "/"
Example #29
0
 def build_xml_element(self, scene, matrix_list):
     xml = self.Element('camera')
     
     xml_format = {
         'aperture_radius': [aperture_radius(scene, self)],
         'sensor_width': [scene.camera.data.sensor_width / 1000.0],
         'lens_sensor_dist': [lens_sensor_dist(scene, self)],
         'aspect_ratio': [aspect_ratio(scene, self)],
         'exposure_duration': 'exposure',
     }
     
     if self.whitebalance == 'Custom':
         xml_format['white_point'] = {
             'chromaticity_coordinates': {
                 'x': [self.whitebalanceX],
                 'y': [self.whitebalanceY],
             }
         }
     else:
         xml_format['white_balance'] = 'whitebalance',
     
     ws = get_worldscale(scene)
     
     if(scene.camera.data.type == 'ORTHO'):
         xml_format['camera_type'] = ['orthographic']
         xml_format['sensor_width'] = [scene.camera.data.ortho_scale * ws] # Blender seems to use 'ortho_scale' for the sensor width.
     
     mat = matrix_list[0][1].transposed()
     
     xml_format['pos']        = [ i*ws for i in mat[3][0:3]]
     xml_format['forwards']    = [-i*ws for i in mat[2][0:3]]
     xml_format['up']        = [ i*ws for i in mat[1][0:3]]
     
     if len(matrix_list) > 1:
         # Remove pos, conflicts with keyframes.
         del(xml_format['pos'])
     
         keyframes = exportutil.matrixListToKeyframes(scene, scene.camera, matrix_list)
             
         xml_format['keyframe'] = tuple(keyframes)
     
     if self.autofocus:
         xml_format['autofocus'] = '' # is empty element
         xml_format['focus_distance'] = [10.0]  # any non-zero value will do
     else:
         if scene.camera.data.dof_object is not None:
             xml_format['focus_distance'] = [((scene.camera.location - scene.camera.data.dof_object.location).length*ws)]
         elif scene.camera.data.dof_distance > 0:
             xml_format['focus_distance'] = [scene.camera.data.dof_distance*ws]
         else: #autofocus
             xml_format['autofocus'] = '' # is empty element
             xml_format['focus_distance'] = [10.0]  # any non-zero value will do
     
     if self.ad:
         xml_format.update({
             'aperture_shape': {}
         })
         if self.ad_obstacle != '':
             ad_obstacle = efutil.filesystem_path(self.ad_obstacle)
             if os.path.exists(ad_obstacle):
                 xml_format.update({
                     'obstacle_map': {
                         'path': [efutil.path_relative_to_export(ad_obstacle)]
                     }
                 })
             else:
                 indigo_log('WARNING: Camera Obstacle Map specified, but image path is not valid')
         
         if self.ad_type == 'image':
             ad_image = efutil.filesystem_path(self.ad_image)
             if os.path.exists(ad_image):
                 xml_format['aperture_shape'].update({
                     'image': {
                         'path': [efutil.path_relative_to_export(ad_image)]
                     }
                 })
             else:
                 indigo_log('WARNING: Camera Aperture Diffraction type "Image" selected, but image path is not valid')
         
         elif self.ad_type == 'generated':
             xml_format['aperture_shape'].update({
                 'generated': {
                     'num_blades': [self.ad_blades],
                     'start_angle': [self.ad_angle],
                     'blade_offset': [self.ad_offset],
                     'blade_curvature_radius': [self.ad_curvature]
                 }
             })
         elif self.ad_type == 'circular':
             xml_format['aperture_shape'][self.ad_type] = {}
     
     aspect = aspect_ratio(scene, self)
     if scene.camera.data.shift_x != 0:
         sx = scene.camera.data.shift_x * 0.001*scene.camera.data.sensor_width
         if aspect < 1.0:
             sx /= aspect
         xml_format['lens_shift_right_distance'] = [sx]
         
     if scene.camera.data.shift_y != 0:
         sy = scene.camera.data.shift_y * 0.001*scene.camera.data.sensor_width
         if aspect < 1.0:
             sy /= aspect
         xml_format['lens_shift_up_distance'] = [sy]
     
     self.build_subelements(scene, xml_format, xml)
     
     return xml
Example #30
0
    def render(self, context):
        '''
        Render the scene file, or in our case, export the frame(s)
        and launch an Indigo process.
        '''

        with RENDERENGINE_indigo.render_lock:  # Just render one thing at a time.
            self.renderer = None
            self.message_thread = None
            self.stats_thread = None
            self.framebuffer_thread = None
            self.render_update_timer = None
            self.rendering = False

            # force scene update to current rendering frame
            # Not sure why - Yves
            #context.frame_set(context.frame_current)

            #------------------------------------------------------------------------------
            # Export the Scene

            # Get the frame path.
            frame_path = efutil.filesystem_path(context.render.frame_path())

            # Get the filename for the frame sans extension.
            image_out_path = os.path.splitext(frame_path)[0]

            # Generate the name for the scene file(s).
            if context.indigo_engine.use_output_path == True:
                # Get the output path from the frame path.
                output_path = os.path.dirname(frame_path)

                # Generate the output filename
                output_filename = '%s.%s.%05i.igs' % (
                    efutil.scene_filename(), bpy.path.clean_name(
                        context.name), context.frame_current)
            else:
                # Get export path from the indigo_engine.
                export_path = efutil.filesystem_path(
                    context.indigo_engine.export_path)

                # Get the directory name from the output path.
                output_path = os.path.dirname(export_path)

                # Get the filename from the output path and remove the extension.
                output_filename = os.path.splitext(
                    os.path.basename(export_path))[0]

                # Count contiguous # chars and replace them with the frame number.
                # If the hash count is 0 and we are exporting an animation, append the frame numbers.
                hash_count = util.count_contiguous('#', output_filename)
                if hash_count != 0:
                    output_filename = output_filename.replace(
                        '#' * hash_count,
                        ('%%0%0ii' % hash_count) % context.frame_current)
                elif self.is_animation:
                    output_filename = output_filename + (
                        '%%0%0ii' % 4) % context.frame_current

                # Add .igs extension.
                output_filename += '.igs'

            # The full path of the exported scene file.
            exported_file = '/'.join([output_path, output_filename])

            # Create output_path if it does not exist.
            if not os.path.exists(output_path):
                os.makedirs(output_path)

            # If an animation is rendered, write an indigo queue file (.igq).
            if self.is_animation:
                igq_filename = '%s/%s.%s.igq' % (
                    output_path, efutil.scene_filename(),
                    bpy.path.clean_name(context.name))

                if context.frame_current == context.frame_start:
                    # Start a new igq file.
                    igq_file = open(igq_filename, 'w')
                    igq_file.write(
                        '<?xml version="1.0" encoding="utf-8" standalone="no" ?>\n'
                    )
                    igq_file.write('<render_queue>\n')
                else:
                    # Append to existing igq.
                    igq_file = open(igq_filename, 'a')

                rnd = random.Random()
                rnd.seed(context.frame_current)

                # Write igq item.
                igq_file.write('\t<item>\n')
                igq_file.write('\t\t<scene_path>%s</scene_path>\n' %
                               exported_file)
                igq_file.write('\t\t<halt_time>%d</halt_time>\n' %
                               context.indigo_engine.halttime)
                igq_file.write('\t\t<halt_spp>%d</halt_spp>\n' %
                               context.indigo_engine.haltspp)
                igq_file.write('\t\t<output_path>%s</output_path>\n' %
                               image_out_path)
                igq_file.write('\t\t<seed>%s</seed>\n' %
                               rnd.randint(1, 1000000))
                igq_file.write('\t</item>\n')

                # If this is the last frame, write the closing tag.
                if context.frame_current == context.frame_end:
                    igq_file.write('</render_queue>\n')

                igq_file.close()

                # Calculate the progress by frame with frame range (fr) and frame offset (fo).
                fr = context.frame_end - context.frame_start
                fo = context.frame_current - context.frame_start
                self.update_progress(fo / fr)

            scene_writer = indigo.operators._Impl_OT_indigo(
                directory=output_path,
                filename=output_filename).set_report(self.report)

            # Write the scene file.
            export_result = scene_writer.execute(context)

            # Return if the export didn't finish.
            if not 'FINISHED' in export_result:
                return

            #------------------------------------------------------------------------------
            # Update indigo defaults config file .
            config_updates = {
                'auto_start': context.indigo_engine.auto_start,
                'console_output': context.indigo_engine.console_output
            }

            if context.indigo_engine.use_console:
                indigo_path = getConsolePath(context)
            else:
                indigo_path = getGuiPath(context)

            if os.path.exists(indigo_path):
                config_updates['install_path'] = getInstallPath(context)

            try:
                for k, v in config_updates.items():
                    efutil.write_config_value('indigo', 'defaults', k, v)
            except Exception as err:
                indigo_log('Saving indigo config failed: %s' % err,
                           message_type='ERROR')

            # Make sure that the Indigo we are going to launch is at least as
            # new as the exporter version.
            version_ok = True
            if not context.indigo_engine.skip_version_check:
                iv = getVersion(context)
                for i in range(3):
                    version_ok &= iv[i] >= bl_info['version'][i]

            #------------------------------------------------------------------------------
            # Conditionally Spawn Indigo.
            if context.indigo_engine.auto_start:

                exe_path = efutil.filesystem_path(indigo_path)

                if not os.path.exists(exe_path):
                    print("Failed to find indigo at '" + str(exe_path) + "'")
                    msg = "Failed to find indigo at '" + str(exe_path) + "'."
                    msg + "\n  "
                    msg += "Please make sure you have Indigo installed, and that the path to indigo in the 'Indigo Render Engine Settings' is set correctly."
                    self.report({'ERROR'}, msg)

                #if not version_ok:
                #indigo_log("Unsupported version v%s; Cannot start Indigo with this scene" % ('.'.join(['%s'%i for i in iv])), message_type='ERROR')
                #return

                # if it's an animation, don't execute until final frame
                if self.is_animation and context.frame_current != context.frame_end:
                    return

                # if animation and final frame, launch queue instead of single frame
                if self.is_animation and context.frame_current == context.frame_end:
                    exported_file = igq_filename
                    indigo_args = [exe_path, exported_file]
                else:
                    indigo_args = [
                        exe_path, exported_file, '-o', image_out_path + '.png'
                    ]

                # Set master or working master command line args.
                if context.indigo_engine.network_mode == 'master':
                    indigo_args.extend(['-n', 'm'])
                elif context.indigo_engine.network_mode == 'working_master':
                    indigo_args.extend(['-n', 'wm'])

                # Set port arg if network rendering is enabled.
                if context.indigo_engine.network_mode in [
                        'master', 'working_master'
                ]:
                    indigo_args.extend(
                        ['-p', '%i' % context.indigo_engine.network_port])

                # Set hostname and port arg.
                if context.indigo_engine.network_mode == 'manual':
                    indigo_args.extend([
                        '-h',
                        '%s:%i' % (context.indigo_engine.network_host,
                                   context.indigo_engine.network_port)
                    ])

                # indigo_log("Starting indigo: %s" % indigo_args)

                # If we're starting a console or should wait for the process, listen to the output.
                if context.indigo_engine.use_console or context.indigo_engine.wait_for_process:
                    f_stdout = subprocess.PIPE
                else:
                    f_stdout = None

                # Launch the Indigo process.
                indigo_proc = subprocess.Popen(indigo_args, stdout=f_stdout)
                indigo_pid = indigo_proc.pid
                indigo_log('Started Indigo process, PID: %i' % indigo_pid)

                # Wait for the render to finish if we use the console or should wait for the process.
                if context.indigo_engine.use_console or context.indigo_engine.wait_for_process:
                    while indigo_proc.poll() == None:
                        indigo_proc.communicate()
                        time.sleep(2)

                    indigo_proc.wait()
                    if not indigo_proc.stdout.closed:
                        indigo_proc.communicate()
                    if indigo_proc.returncode == -1:
                        sys.exit(-1)

            else:
                indigo_log("Scene was exported to %s" % exported_file)

            #------------------------------------------------------------------------------
            # Finished
            return
Example #31
0
	def exportLamp(self, scene, lamp, idx):
		ltype = lamp.data.type
		name = translate_id(lamp.name)
		mult = lamp.data.mitsuba_lamp.intensity
		if lamp.data.mitsuba_lamp.inside_medium:
			self.exportMedium(scene.mitsuba_media.media[lamp.data.mitsuba_lamp.lamp_medium])
		if ltype == 'POINT':
			self.openElement('luminaire', { 'type' : 'point', 'id' : '%s-light' % name })
			self.exportWorldTrafo(lamp.matrix_world)
			self.parameter('rgb', 'intensity', {'value' : 
				"%f %f %f" % (lamp.data.color.r*mult, lamp.data.color.g*mult,
					lamp.data.color.b*mult)})
			self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
			if lamp.data.mitsuba_lamp.inside_medium:
				self.element('ref', {'id' : lamp.data.mitsuba_lamp.lamp_medium})
			self.closeElement()
		elif ltype == 'AREA':
			self.element('remove', { 'id' : '%s-light' % name})
			self.openElement('shape', { 'type' : 'obj'} )
			(size_x, size_y) = (lamp.data.size, lamp.data.size)
			if lamp.data.shape == 'RECTANGLE':
				size_y = lamp.data.size_y
			mult = mult / (2 * size_x * size_y)
			filename = "area_luminaire_%d.obj" % idx
			try:
				os.mkdir(self.meshes_dir)
			except OSError:
				pass
			self.parameter('string', 'filename', { 'value' : 'meshes/%s' % filename})
			self.exportWorldTrafo(lamp.matrix_world)

			self.openElement('luminaire', { 'id' : '%s-arealight' % name, 'type' : 'area'})
			if lamp.data.mitsuba_lamp.inside_medium:
				self.element('ref', {'id' : lamp.data.mitsuba_lamp.lamp_medium})
			self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
					% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
			self.closeElement()
			self.openElement('bsdf', { 'type' : 'lambertian'})
			self.parameter('spectrum', 'reflectance', {'value' : '0'})
			self.closeElement()
			self.closeElement()
			path = os.path.join(self.meshes_dir, filename)
			objFile = open(path, 'w')
			objFile.write('v %f %f 0\n' % (-size_x/2, -size_y/2))
			objFile.write('v %f %f 0\n' % ( size_x/2, -size_y/2))
			objFile.write('v %f %f 0\n' % ( size_x/2,  size_y/2))
			objFile.write('v %f %f 0\n' % (-size_x/2,  size_y/2))
			objFile.write('f 4 3 2 1\n')
			objFile.close()
		elif ltype == 'SUN':
			self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'directional'})
			scale = mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1]))
			self.exportWorldTrafo(lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
			self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
					% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
			self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
			self.closeElement()
		elif ltype == 'SPOT':
			self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'spot'})
			self.exportWorldTrafo(lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
			self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
					% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
			self.parameter('float', 'cutoffAngle', {'value' : '%f' %  (lamp.data.spot_size * 180 / (math.pi * 2))})
			self.parameter('float', 'beamWidth', {'value' : '%f' % (lamp.data.spot_blend * lamp.data.spot_size * 180 / (math.pi * 2))})
			self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
			if lamp.data.mitsuba_lamp.inside_medium:
				self.element('ref', {'id' : lamp.data.mitsuba_lamp.lamp_medium})
			self.closeElement()
		elif ltype == 'HEMI':
			if lamp.data.mitsuba_lamp.envmap_type == 'constant':
				self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'constant'})
				self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
				self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
						% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
				self.closeElement()
			elif lamp.data.mitsuba_lamp.envmap_type == 'envmap':
				self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'envmap'})
				self.parameter('string', 'filename', {'value' : efutil.filesystem_path(lamp.data.mitsuba_lamp.envmap_file)})
				self.exportWorldTrafo(lamp.matrix_world)
				self.parameter('float', 'intensityScale', {'value' : '%f' % lamp.data.mitsuba_lamp.intensity})
				self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
				self.closeElement()
Example #32
0
	def exportLamp(self, scene, lamp):
		ltype = lamp.data.type
		name = lamp.name
		mult = lamp.data.mitsuba_lamp.intensity
		if lamp.data.mitsuba_lamp.inside_medium:
			self.exportMedium(scene.mitsuba_media.media[lamp.data.mitsuba_lamp.lamp_medium])
		if ltype == 'POINT':
			self.openElement('shape', { 'type' : 'sphere'})
			self.exportPoint(lamp.location)
			self.parameter('float', 'radius', {'value' : lamp.data.mitsuba_lamp.radius})
			self.openElement('emitter', { 'id' : '%s-light' % name, 'type' : 'area'})
			self.parameter('rgb', 'radiance', { 'value' : "%f %f %f"
					% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
			self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
			if lamp.data.mitsuba_lamp.inside_medium:
				self.element('ref', {'id' : lamp.data.mitsuba_lamp.lamp_medium})
			self.closeElement()
			self.closeElement()
		elif ltype == 'AREA':
			self.openElement('shape', { 'type' : 'rectangle'} )
			self.parameter('boolean', 'flipNormals', {'value' : 'true'})
			(size_x, size_y) = (lamp.data.size/2.0, lamp.data.size/2.0)
			if lamp.data.shape == 'RECTANGLE':
				size_y = lamp.data.size_y/2.0
			self.openElement('transform', {'name' : 'toWorld'})
			loc, rot, sca = lamp.matrix_world.decompose()
			mat_loc = mathutils.Matrix.Translation(loc)
			mat_rot = rot.to_matrix().to_4x4()
			mat_sca = mathutils.Matrix((
				(sca[0]*size_x,0,0,0),
				(0,sca[1]*size_y,0,0),
				(0,0,sca[2],0),
				(0,0,0,1),
			))
			self.exportMatrix(mat_loc * mat_rot * mat_sca)
			self.closeElement()
			self.openElement('emitter', { 'id' : '%s-arealight' % name, 'type' : 'area'})
			self.parameter('rgb', 'radiance', { 'value' : "%f %f %f"
					% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
			self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
			if lamp.data.mitsuba_lamp.inside_medium:
				self.element('ref', {'id' : lamp.data.mitsuba_lamp.lamp_medium})
			self.closeElement()
			self.openElement('bsdf', { 'type' : 'diffuse'})
			self.parameter('spectrum', 'reflectance', {'value' : '0'})
			self.closeElement()
			self.closeElement()
		elif ltype == 'SUN':
			# sun is considered hemi light by Mitsuba
			if self.hemi_lights >= 1:
				# Mitsuba supports only one hemi light
				return False
			self.hemi_lights += 1
			invmatrix = lamp.matrix_world
			skyType = lamp.data.mitsuba_lamp.mitsuba_lamp_sun.sunsky_type
			LampParams = getattr(lamp.data.mitsuba_lamp, 'mitsuba_lamp_sun' ).get_paramset(lamp)
			if skyType == 'sunsky':
				self.openElement('emitter', { 'id' : '%s-light' % name, 'type' : 'sunsky'})
			elif skyType == 'sun':
				self.openElement('emitter', { 'id' : '%s-light' % name, 'type' : 'sun'})
			elif skyType == 'sky':
				self.openElement('emitter', { 'id' : '%s-light' % name, 'type' : 'sky'})
				#self.parameter('boolean', 'extend', {'value' : '%s' % str(lamp.data.mitsuba_lamp.mitsuba_lamp_sun.extend).lower()})
			LampParams.export(self)
			self.openElement('transform', {'name' : 'toWorld'})
			#rotate around x to make z UP. Default Y - UP
			self.element('rotate', {'x' : '1', 'angle' : '90'})
			self.closeElement()
			#self.exportWorldTrafo()
			#self.parameter('float', 'turbidity', {'value' : '%f' % (lamp.data.mitsuba_lamp.mitsuba_lamp_sun.turbidity)})
			#ot_mat = mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1]))	#to make Z up rotate 90 around X
			#rotatedSun = invmatrix * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([1, 0, 0])) * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1]))
			self.parameter('vector', 'sunDirection', {'x':'%f' % invmatrix[0][2], 'y':'%f' % invmatrix[1][2], 'z':'%f' % invmatrix[2][2]})
			self.closeElement()
			
		elif ltype == 'SPOT':
			self.openElement('emitter', { 'id' : '%s-light' % name, 'type' : 'spot'})
			self.exportWorldTrafo(lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
			self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
					% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
			self.parameter('float', 'cutoffAngle', {'value' : '%f' % (lamp.data.spot_size * 180 / (math.pi * 2))})
			self.parameter('float', 'beamWidth', {'value' : '%f' % ((1-lamp.data.spot_blend) * lamp.data.spot_size * 180 / (math.pi * 2))})
			self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
			if lamp.data.mitsuba_lamp.inside_medium:
				self.element('ref', {'id' : lamp.data.mitsuba_lamp.lamp_medium})
			self.closeElement()
		elif ltype == 'HEMI':
			if self.hemi_lights >= 1:
				# Mitsuba supports only one hemi light
				return False
			self.hemi_lights += 1
			if lamp.data.mitsuba_lamp.envmap_type == 'constant':
				self.openElement('emitter', { 'id' : '%s-light' % name, 'type' : 'constant'})
				self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
				self.parameter('rgb', 'radiance', { 'value' : "%f %f %f"
						% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
				self.closeElement()
			elif lamp.data.mitsuba_lamp.envmap_type == 'envmap':
				self.openElement('emitter', { 'id' : '%s-light' % name, 'type' : 'envmap'})
				self.parameter('string', 'filename', {'value' : efutil.filesystem_path(lamp.data.mitsuba_lamp.envmap_file)})
				self.exportWorldTrafo(lamp.matrix_world * mathutils.Matrix.Rotation(radians(90.0), 4, 'X'))
				self.parameter('float', 'scale', {'value' : '%f' % lamp.data.mitsuba_lamp.intensity})
				self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
				self.closeElement()
Example #33
0
def realpath(path):
    return os.path.realpath(efutil.filesystem_path(path))
Example #34
0
	def api_output(self):
		'''
		Calculate type and parameters for LuxRender Film statement
		
		Returns		tuple(2) (string, list) 
		'''
		scene = LuxManager.CurrentScene
		
		xr, yr = self.resolution(scene)
		
		params = ParamSet()
		
		if scene.render.use_border:
			(x1,x2,y1,y2) = [
				scene.render.border_min_x, scene.render.border_max_x,
				scene.render.border_min_y, scene.render.border_max_y
			]
			# Set resolution
			params.add_integer('xresolution', round(xr*x2, 0)-round(xr*x1, 0))
			params.add_integer('yresolution', round(yr*y2, 0)-round(yr*y1, 0))
		else:
			# Set resolution
			params.add_integer('xresolution', xr)
			params.add_integer('yresolution', yr)
		
#		if scene.render.use_border:
#			cropwindow = [
#				scene.render.border_min_x, scene.render.border_max_x,
#				scene.render.border_min_y, scene.render.border_max_y
#			]
#			params.add_float('cropwindow', cropwindow)
		
		# ColourSpace
		if self.luxrender_colorspace.preset:
			cs_object = getattr(colorspace_presets, self.luxrender_colorspace.preset_name)
		else:
			cs_object = self.luxrender_colorspace
			
		params.add_float('gamma', self.get_gamma())
		params.add_float('colorspace_white',	[cs_object.cs_whiteX,	cs_object.cs_whiteY])
		params.add_float('colorspace_red',		[cs_object.cs_redX,		cs_object.cs_redY])
		params.add_float('colorspace_green',	[cs_object.cs_greenX,	cs_object.cs_greenY])
		params.add_float('colorspace_blue',		[cs_object.cs_blueX,	cs_object.cs_blueY])
		
		# Camera Response Function
		if LUXRENDER_VERSION >= '0.8' and self.luxrender_colorspace.use_crf == 'file':
			if scene.camera.library is not None:
				local_crf_filepath = bpy.path.abspath(self.luxrender_colorspace.crf_file, scene.camera.library.filepath)
			else:
				local_crf_filepath = self.luxrender_colorspace.crf_file
			local_crf_filepath = efutil.filesystem_path( local_crf_filepath )
			if scene.luxrender_engine.allow_file_embed():
				from ..util import bencode_file2string
				params.add_string('cameraresponse', os.path.basename(local_crf_filepath))
				encoded_data = bencode_file2string(local_crf_filepath)
				params.add_string('cameraresponse_data', encoded_data.splitlines() )
			else:
				params.add_string('cameraresponse', local_crf_filepath)
		if LUXRENDER_VERSION >= '0.8' and self.luxrender_colorspace.use_crf == 'preset':
			params.add_string('cameraresponse', self.luxrender_colorspace.crf_preset)
		
		# Output types
		params.add_string('filename', get_output_filename(scene))
		params.add_bool('write_resume_flm', self.write_flm)
		params.add_bool('restart_resume_flm', self.restart_flm)
		params.add_bool('write_flm_direct', self.write_flm_direct)
		
		if self.output_alpha:
			output_channels = 'RGBA'
			params.add_bool('premultiplyalpha', self.premultiply_alpha)
		else:
			output_channels = 'RGB'
								
		if scene.luxrender_engine.export_type == 'INT' and self.integratedimaging:
			# Set up params to enable z buffer and set gamma=1.0
			# Also, this requires tonemapped EXR output
			params.add_string('write_exr_channels', 'RGBA')
			params.add_bool('write_exr_halftype', False)
			params.add_bool('write_exr_applyimaging', True)
			params.add_bool('premultiplyalpha', True) #Apparently, this should always be true with EXR
			params.add_bool('write_exr_ZBuf', True)
			params.add_string('write_exr_zbuf_normalizationtype', 'Camera Start/End clip')
			if scene.render.use_color_management:
				params.add_float('gamma', 1.0) # Linear workflow !
			# else leave as pre-corrected gamma
		else:
			# Otherwise let the user decide on tonemapped EXR and other EXR settings
			params.add_bool('write_exr_halftype', self.write_exr_halftype)
			params.add_bool('write_exr_applyimaging', self.write_exr_applyimaging)
			params.add_bool('write_exr_ZBuf', self.write_zbuf)
			params.add_string('write_exr_compressiontype', self.write_exr_compressiontype)
			params.add_string('write_exr_zbuf_normalizationtype', self.zbuf_normalization)
			params.add_bool('write_exr', self.write_exr)
			if self.write_exr: params.add_string('write_exr_channels', output_channels)
		
		params.add_bool('write_png', self.write_png)
		if self.write_png:
			params.add_string('write_png_channels', output_channels)
			params.add_bool('write_png_16bit', self.write_png_16bit)
		params.add_bool('write_tga', self.write_tga)
		if self.write_tga:
			params.add_string('write_tga_channels', output_channels)
			params.add_string('write_tga_Zbuf', self.write_zbuf)
			params.add_string('write_tga_zbuf_normalizationtype', self.zbuf_normalization)
		
		params.add_string('ldr_clamp_method', self.ldr_clamp_method)
		
		if scene.luxrender_engine.export_type == 'EXT':
			params.add_integer('displayinterval', self.displayinterval)
			params.add_integer('writeinterval', self.writeinterval)
			params.add_integer('flmwriteinterval', self.flmwriteinterval)
		else:
			params.add_integer('writeinterval', self.internal_updateinterval)
		
		# Halt conditions
		if scene.luxrender_halt.haltspp > 0:
			params.add_integer('haltspp', scene.luxrender_halt.haltspp)
		
		if scene.luxrender_halt.halttime > 0:
			params.add_integer('halttime', scene.luxrender_halt.halttime)
		
		if self.outlierrejection_k > 0 and scene.luxrender_rendermode.renderer != 'sppm':
			params.add_integer('outlierrejection_k', self.outlierrejection_k)
			
		params.add_integer('tilecount', self.tilecount)
		
		# update the film settings with tonemapper settings
		params.update( self.luxrender_tonemapping.get_paramset() )
		
		return ('fleximage', params)
Example #35
0
  def render(self, scene):
      
      if self is None or scene is None:
          sunflowLog('ERROR: Scene is missing!')
          return
      
      scene.render.use_placeholder = False
      
      with self.render_lock:  # just render one thing at a time
          
          if scene.name == 'preview':
              self.render_preview(scene)
              return
 
          scene_path = efutil.filesystem_path(scene.render.filepath)
          if os.path.isdir(scene_path):
              output_dir = scene_path
          else:
              output_dir = os.path.dirname(scene_path)        
          
          output_dir = os.path.abspath(os.path.join(output_dir , efutil.scene_filename()))            
          if not os.path.exists(output_dir):
              os.mkdir(output_dir)
          #----------- sunflowLog('Sunflow: Current directory = "%s"' % output_dir)
          
          #--------------------------------------- if DEBUG: pydevd.settrace()
          
          if not getExporter (output_dir, scene.name, scene.frame_current):
              return 
          
          if self.is_animation:
              return
          
          arguments = self.getCommandLineArgs(scene)
          
          
          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', '')
          image_name = "%s.%03d.%s" % (scene.name , scene.frame_current, arguments['format'])
          
          if scene.sunflow_performance.useRandom:
              image_name = self.check_randomname(output_dir, image_name)
          
          sunflow_file = "%s.%03d.sc" % (scene.name , scene.frame_current)
          image_file = os.path.abspath(os.path.join(output_dir , image_name))
          sc_file_path = os.path.abspath(os.path.join(output_dir , sunflow_file))
          
          cmd_line = [ javapath , memory , '-server' , '-jar' , jarpath ]
          final_line = ['-o', image_file , sc_file_path]     
          
          extra = []
          for key in arguments:
              if key == 'format':
                  continue
              if arguments[key] != '':
                  values = arguments[key].split()
                  extra.extend(values)
          
          if arguments['format'] != 'png':
              extra.append('-nogui')
          
          cmd_line.extend(extra)
          cmd_line.extend(final_line)
          
      
          sunflow_process = subprocess.Popen(cmd_line)
          refresh_interval = 5
          
          framebuffer_thread = sunflowFilmDisplay()
          framebuffer_thread.set_kick_period(refresh_interval) 
          framebuffer_thread.begin(self, image_file, 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()
Example #36
0
    def exportMeshElement(self, obj):
        if OBJECT_ANALYSIS: indigo_log('exportMeshElement: %s' % obj)

        if obj.type in self.supported_mesh_types:
        
            start_time = time.time()
            
            # If this object has already been exported, then don't export it again. 
            exported_mesh = self.ExportedMeshes.get(obj)
            if exported_mesh != None:
                self.total_mesh_export_time += time.time() - start_time
                return exported_mesh
        
            # Create mesh with applied modifiers
            mesh = obj.to_mesh(self.scene, True, 'RENDER')

            # Compute a hash over the mesh data (vertex positions, material names etc..)
            mesh_hash = self.meshHash(obj, mesh)

            # Form a mesh name like "4618cbf0bc13316135d676fffe0a74fc9b0577909246477354da9254"
            # The name cannot contain the objects name, as the name itself is always unique.
            exported_mesh_name = bpy.path.clean_name(mesh_hash)

            # If this mesh has already been exported, then don't export it again
            exported_mesh = self.MeshesOnDisk.get(exported_mesh_name)
            if exported_mesh != None:
                # Important! If an object is matched to a mesh on disk, add to ExportedMeshes.
                # Otherwise the mesh checksum will be computed over and over again.
                self.ExportedMeshes[obj] = exported_mesh
                bpy.data.meshes.remove(mesh)
                self.total_mesh_export_time += time.time() - start_time
                return exported_mesh

            # Make full mesh path.
            mesh_filename = exported_mesh_name + '.igmesh'
            full_mesh_path = efutil.filesystem_path( '/'.join([self.mesh_dir, mesh_filename]) )
            
            #indigo_log('full_mesh_path: %s'%full_mesh_path)

            # pass the full mesh path to write to filesystem if the object is not a proxy
            if hasattr(obj.data, 'indigo_mesh') and not obj.data.indigo_mesh.valid_proxy():
                if os.path.exists(full_mesh_path) and self.skip_existing_meshes:
                    # if skipping mesh write, parse faces to gather used mats
                    used_mat_indices = set()
                    num_smooth = 0
                    for face in mesh.tessfaces:
                        used_mat_indices.add(face.material_index)
                        if face.use_smooth:
                            num_smooth += 1

                    use_shading_normals = num_smooth > 0
                else:
                    # else let the igmesh_writer do its thing
                    (used_mat_indices, use_shading_normals) = igmesh_writer.factory(self.scene, obj, full_mesh_path, mesh, debug=OBJECT_ANALYSIS)
                    self.mesh_uses_shading_normals[full_mesh_path] = use_shading_normals
            else:
                # Assume igmesh has same number of mats as the proxy object
                used_mat_indices = range(len(obj.material_slots))

            # Remove mesh.
            bpy.data.meshes.remove(mesh)
            
            # Export materials used by this mesh
            if len(obj.material_slots) > 0:
                for mi in used_mat_indices:
                    mat = obj.material_slots[mi].material
                    if mat == None or mat.name in self.ExportedMaterials: continue
                    mat_xmls = mat.indigo_material.factory(obj, mat, self.scene)
                    self.ExportedMaterials[mat.name] = mat_xmls

            # .. put the relative path in the mesh element
            filename = '/'.join([self.rel_mesh_dir, mesh_filename])

            #print('MESH FILENAME %s' % filename)

            shading_normals = True
            if full_mesh_path in self.mesh_uses_shading_normals:
                shading_normals = self.mesh_uses_shading_normals[full_mesh_path]

            xml = obj.data.indigo_mesh.build_xml_element(obj, filename, shading_normals, exported_name=exported_mesh_name)

            mesh_definition = (exported_mesh_name, xml)

            self.MeshesOnDisk[exported_mesh_name] = mesh_definition
            self.ExportedMeshes[obj] = mesh_definition
            
            total = time.time() - start_time
            self.total_mesh_export_time += total
            if self.verbose: indigo_log('Mesh Export took: %f s' % total)

            return mesh_definition
Example #37
0
    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()
Example #38
0
    def get_process_args(self, scene, start_rendering):
        config_updates = {'auto_start': start_rendering}

        addon_prefs = LuxRenderAddon.get_prefs()
        luxrender_path = efutil.filesystem_path(addon_prefs.install_path)

        print('luxrender_path: ', luxrender_path)

        if luxrender_path == '':
            return ['']

        if luxrender_path[-1] != '/':
            luxrender_path += '/'

        if sys.platform == 'darwin':
            luxrender_path += 'LuxRender.app/Contents/MacOS/%s' % scene.luxrender_engine.binary_name  # Get binary from OSX bundle
            if not os.path.exists(luxrender_path):
                LuxLog('LuxRender not found at path: %s' % luxrender_path,
                       ', trying default LuxRender location')
                luxrender_path = '/Applications/LuxRender/LuxRender.app/Contents/MacOS/%s' % scene.luxrender_engine.binary_name  # try fallback to default installation path

        elif sys.platform == 'win32':
            luxrender_path += '%s.exe' % scene.luxrender_engine.binary_name
        else:
            luxrender_path += scene.luxrender_engine.binary_name

        if not os.path.exists(luxrender_path):
            raise Exception('LuxRender not found at path: %s' % luxrender_path)

        cmd_args = [luxrender_path]

        # set log verbosity
        if scene.luxrender_engine.log_verbosity != 'default':
            cmd_args.append('--' + scene.luxrender_engine.log_verbosity)

        if scene.luxrender_engine.binary_name == 'luxrender':
            # Copy the GUI log to the console
            cmd_args.append('--logconsole')

        # Set number of threads for external processes
        if not scene.luxrender_engine.threads_auto:
            cmd_args.append('--threads=%i' % scene.luxrender_engine.threads)

        #Set fixed seeds, if enabled
        if scene.luxrender_engine.fixed_seed:
            cmd_args.append('--fixedseed')

        if scene.luxrender_networking.use_network_servers and scene.luxrender_networking.servers != '':
            for server in scene.luxrender_networking.servers.split(','):
                cmd_args.append('--useserver')
                cmd_args.append(server.strip())

            cmd_args.append('--serverinterval')
            cmd_args.append('%i' % scene.luxrender_networking.serverinterval)

            config_updates['servers'] = scene.luxrender_networking.servers
            config_updates[
                'serverinterval'] = '%i' % scene.luxrender_networking.serverinterval

        config_updates[
            'use_network_servers'] = scene.luxrender_networking.use_network_servers

        # Save changed config items and then launch Lux

        try:
            for k, v in config_updates.items():
                efutil.write_config_value('luxrender', 'defaults', k, v)
        except Exception as err:
            LuxLog(
                'WARNING: Saving LuxRender config failed, please set your user scripts dir: %s'
                % err)

        return cmd_args
Example #39
0
    def render(self, scene):

        if self is None or scene is None:
            sunflowLog('ERROR: Scene is missing!')
            return

        scene.render.use_placeholder = False

        with self.render_lock:  # just render one thing at a time

            if scene.name == 'preview':
                self.render_preview(scene)
                return

            scene_path = efutil.filesystem_path(scene.render.filepath)
            if os.path.isdir(scene_path):
                output_dir = scene_path
            else:
                output_dir = os.path.dirname(scene_path)

            output_dir = os.path.abspath(
                os.path.join(output_dir, efutil.scene_filename()))
            if not os.path.exists(output_dir):
                os.mkdir(output_dir)
            #----------- sunflowLog('Sunflow: Current directory = "%s"' % output_dir)

            #--------------------------------------- if DEBUG: pydevd.settrace()

            if not getExporter(output_dir, scene.name, scene.frame_current):
                return

            if self.is_animation:
                return

            arguments = self.getCommandLineArgs(scene)

            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', '')
            image_name = "%s.%03d.%s" % (scene.name, scene.frame_current,
                                         arguments['format'])

            if scene.sunflow_performance.useRandom:
                image_name = self.check_randomname(output_dir, image_name)

            sunflow_file = "%s.%03d.sc" % (scene.name, scene.frame_current)
            image_file = os.path.abspath(os.path.join(output_dir, image_name))
            sc_file_path = os.path.abspath(
                os.path.join(output_dir, sunflow_file))

            cmd_line = [javapath, memory, '-server', '-jar', jarpath]
            final_line = ['-o', image_file, sc_file_path]

            extra = []
            for key in arguments:
                if key == 'format':
                    continue
                if arguments[key] != '':
                    values = arguments[key].split()
                    extra.extend(values)

            if arguments['format'] != 'png':
                extra.append('-nogui')

            cmd_line.extend(extra)
            cmd_line.extend(final_line)

            sunflow_process = subprocess.Popen(cmd_line)
            refresh_interval = 5

            framebuffer_thread = sunflowFilmDisplay()
            framebuffer_thread.set_kick_period(refresh_interval)
            framebuffer_thread.begin(self, image_file, 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()
Example #40
0
   def exportLamp(self, scene, lamp, idx):
      ltype = lamp.data.type
      name = translate_id(lamp.name)
      mult = lamp.data.mitsuba_lamp.intensity
      if lamp.data.mitsuba_lamp.inside_medium:
         self.exportMedium(scene.mitsuba_media.media[lamp.data.mitsuba_lamp.lamp_medium])
      if ltype == 'POINT':
         self.element('remove', { 'id' : '%s-light' % name})
         self.openElement('shape', { 'type' : 'sphere'})
         self.exportPoint(lamp.location)
         self.parameter('float', 'radius', {'value' : lamp.data.mitsuba_lamp.radius})
         self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'area'})
         if lamp.data.mitsuba_lamp.inside_medium:
            self.element('ref', {'id' : lamp.data.mitsuba_lamp.lamp_medium})
         self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
         self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
               % (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
         self.closeElement()
         self.closeElement()
      elif ltype == 'AREA':
         self.element('remove', { 'id' : '%s-light' % name})
         self.openElement('shape', { 'type' : 'obj'} )
         (size_x, size_y) = (lamp.data.size, lamp.data.size)
         if lamp.data.shape == 'RECTANGLE':
            size_y = lamp.data.size_y
         #mult = mult / (2 * size_x * size_y) #I like more absolute intensity that int/area
         #mult = mult / (size_x * size_y)
         filename = "area_luminaire_%d.obj" % idx
         try:
            os.mkdir(self.meshes_dir)
         except OSError:
            pass
         self.parameter('string', 'filename', { 'value' : 'meshes/%s' % filename})
         self.exportWorldTrafo(lamp.matrix_world)

         self.openElement('luminaire', { 'id' : '%s-arealight' % name, 'type' : 'area'})
         if lamp.data.mitsuba_lamp.inside_medium:
            self.element('ref', {'id' : lamp.data.mitsuba_lamp.lamp_medium})
         self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
               % (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
         self.closeElement()
         self.openElement('bsdf', { 'type' : 'diffuse'})
         self.parameter('spectrum', 'reflectance', {'value' : '0'})
         self.closeElement()
         self.closeElement()
         path = os.path.join(self.meshes_dir, filename)
         objFile = open(path, 'w')
         objFile.write('v %f %f 0\n' % (-size_x/2, -size_y/2))
         objFile.write('v %f %f 0\n' % ( size_x/2, -size_y/2))
         objFile.write('v %f %f 0\n' % ( size_x/2,  size_y/2))
         objFile.write('v %f %f 0\n' % (-size_x/2,  size_y/2))
         objFile.write('f 4 3 2 1\n')
         objFile.close()
      elif ltype == 'SUN':
         invmatrix = lamp.matrix_world
         skyType = lamp.data.mitsuba_lamp.mitsuba_lamp_sun.sunsky_type
         if skyType == 'sunsky':
            self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'sunsky'})
            self.parameter('boolean', 'extend', {'value' : '%s' % str(lamp.data.mitsuba_lamp.mitsuba_lamp_sun.extend).lower()})
         elif skyType == 'sun':
            self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'sun'})
         elif skyType == 'sky':
            self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'sky'})
            self.parameter('boolean', 'extend', {'value' : '%s' % str(lamp.data.mitsuba_lamp.mitsuba_lamp_sun.extend).lower()})
         self.openElement('transform', {'name' : 'toWorld'})
         #fixes 'up' orientation of sky to blender world.
         self.element('matrix', {'value' : '1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000'})
         self.closeElement()
         #self.exportWorldTrafo()
         self.parameter('float', 'turbidity', {'value' : '%f' % (lamp.data.mitsuba_lamp.mitsuba_lamp_sun.turbidity)})
         self.parameter('vector', 'sunDirection', {'x':'%f' % invmatrix[0][2], 'y':'%f' % invmatrix[1][2], 'z':'%f' % invmatrix[2][2]})
         self.closeElement()
         #self.parameter('vector', 'sunDirection', {'x':'%f' % invmatrix[0][2], 'y':'%f' % invmatrix[1][2], 'z':'%f' % invmatrix[2][2]})

      elif ltype == 'SPOT':
         self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'spot'})
         self.exportWorldTrafo(lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
         self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
               % (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
         self.parameter('float', 'cutoffAngle', {'value' : '%f' %  (lamp.data.spot_size * 180 / (math.pi * 2))})
         self.parameter('float', 'beamWidth', {'value' : '%f' % ((1-lamp.data.spot_blend) * lamp.data.spot_size * 180 / (math.pi * 2))})
         self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
         if lamp.data.mitsuba_lamp.inside_medium:
            self.element('ref', {'id' : lamp.data.mitsuba_lamp.lamp_medium})
         self.closeElement()
      elif ltype == 'HEMI':
         if lamp.data.mitsuba_lamp.envmap_type == 'constant':
            self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'constant'})
            self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
            self.parameter('rgb', 'intensity', { 'value' : "%f %f %f"
                  % (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)})
            self.closeElement()
         elif lamp.data.mitsuba_lamp.envmap_type == 'envmap':
            self.openElement('luminaire', { 'id' : '%s-light' % name, 'type' : 'envmap'})
            self.parameter('string', 'filename', {'value' : efutil.filesystem_path(lamp.data.mitsuba_lamp.envmap_file)})
            self.exportWorldTrafo(lamp.matrix_world)
            self.parameter('float', 'intensityScale', {'value' : '%f' % lamp.data.mitsuba_lamp.intensity})
            self.parameter('float', 'samplingWeight', {'value' : '%f' % lamp.data.mitsuba_lamp.samplingWeight})
            self.closeElement()
Example #41
0
	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()
Example #42
0
 def valid_proxy(self):
     proxy_path = filesystem_path(self.mesh_path)
     return self.mesh_proxy and os.path.exists(proxy_path)
Example #43
0
	def get_process_args(self, scene, start_rendering):
		config_updates = {
			'auto_start': start_rendering
		}
		
		addon_prefs = LuxRenderAddon.get_prefs()
		luxrender_path = efutil.filesystem_path( addon_prefs.install_path )
		
		print('luxrender_path: ', luxrender_path)
		
		if luxrender_path == '':
			return ['']
		
		if luxrender_path[-1] != '/':
			luxrender_path += '/'
		
		if sys.platform == 'darwin':
			luxrender_path += 'LuxRender.app/Contents/MacOS/%s' % scene.luxrender_engine.binary_name # Get binary from OSX bundle
			if not os.path.exists(luxrender_path):
				LuxLog('LuxRender not found at path: %s' % luxrender_path, ', trying default LuxRender location')
				luxrender_path = '/Applications/LuxRender/LuxRender.app/Contents/MacOS/%s' % scene.luxrender_engine.binary_name # try fallback to default installation path

		elif sys.platform == 'win32':
			luxrender_path += '%s.exe' % scene.luxrender_engine.binary_name
		else:
			luxrender_path += scene.luxrender_engine.binary_name
		
		if not os.path.exists(luxrender_path):
			raise Exception('LuxRender not found at path: %s' % luxrender_path)
		
		cmd_args = [luxrender_path]
		
		# set log verbosity
		if scene.luxrender_engine.log_verbosity != 'default':
			cmd_args.append('--' + scene.luxrender_engine.log_verbosity)
		
		if scene.luxrender_engine.binary_name == 'luxrender':
			# Copy the GUI log to the console
			cmd_args.append('--logconsole')
		
		# Set number of threads for external processes
		if not scene.luxrender_engine.threads_auto:
			cmd_args.append('--threads=%i' % scene.luxrender_engine.threads)
			
		#Set fixed seeds, if enabled
		if scene.luxrender_engine.fixed_seed:
			cmd_args.append('--fixedseed')
		
		if scene.luxrender_networking.use_network_servers and scene.luxrender_networking.servers != '':
			for server in scene.luxrender_networking.servers.split(','):
				cmd_args.append('--useserver')
				cmd_args.append(server.strip())
			
			cmd_args.append('--serverinterval')
			cmd_args.append('%i' % scene.luxrender_networking.serverinterval)
			
			config_updates['servers'] = scene.luxrender_networking.servers
			config_updates['serverinterval'] = '%i' % scene.luxrender_networking.serverinterval
		
		config_updates['use_network_servers'] = scene.luxrender_networking.use_network_servers
		
		# Save changed config items and then launch Lux
		
		try:
			for k, v in config_updates.items():
				efutil.write_config_value('luxrender', 'defaults', k, v)
		except Exception as err:
			LuxLog('WARNING: Saving LuxRender config failed, please set your user scripts dir: %s' % err)
		
		return cmd_args
Example #44
0
	def api_output(self):
		'''
		Calculate type and parameters for LuxRender Film statement
		
		Returns		tuple(2) (string, list) 
		'''
		scene = LuxManager.CurrentScene
		
		xr, yr = self.resolution(scene)
		
		params = ParamSet()
		
		if scene.render.use_border: #Border rendering handler, this gets a bit tricky. Blender ALWAYS expects to get back a cropped image, it will handle the padding itself if the user asked for it.
			if scene.render.use_crop_to_border: #user asked to crop, so always crop
				(x1,x2,y1,y2) = [
					scene.render.border_min_x, scene.render.border_max_x,
					scene.render.border_min_y, scene.render.border_max_y
				]
				# Set resolution
				# This is a new method of "rounding" the cropped image to match blenders expected rectangle_size
				# I tested this with several cases which failed with the former rounding, pls check - Jens
				params.add_integer('xresolution', int((xr*x2)-(xr*x1)+1))
				params.add_integer('yresolution', int((yr*y2)-(yr*y1)+1))
			
			if not scene.render.use_crop_to_border: #user asked for padded-to-full-frame output, there are a few cases where Lux needs to do this itself since the rendered image will not be returned to Blender
				if scene.luxrender_engine.render == False or (scene.luxrender_engine.export_type == 'EXT' and scene.luxrender_engine.binary_name == 'luxrender' and scene.luxrender_engine.monitor_external == False): #If run-renderer (scene.luxrender_engine.render) is disabled or we are in un-monitored external mode, we do not return the image to Blender and Lux must pad the image itself
					cropwindow = [
						scene.render.border_min_x, scene.render.border_max_x,
						1-scene.render.border_min_y, 1-scene.render.border_max_y
					] #Subtract scene.render.border Y values from 1 to translate between Blender and Lux conventions
					params.add_float('cropwindow', cropwindow)
					params.add_integer('xresolution', xr) #Don't forget to set full frame resolution
					params.add_integer('yresolution', yr)

					
				else: #we are returning the image to blender which will pad for us, so have LuxRender send back a cropped frame anyway
					(x1,x2,y1,y2) = [
						scene.render.border_min_x, scene.render.border_max_x,
						scene.render.border_min_y, scene.render.border_max_y
					]
					# Set resolution
					# This is a new method of "rounding" the cropped image to match blenders expected rectangle_size
					# I tested this with several cases which failed with the former rounding, pls check - Jens
					params.add_integer('xresolution', int((xr*x2)-(xr*x1)+1))
					params.add_integer('yresolution', int((yr*y2)-(yr*y1)+1))

		else:
			# Set resolution
			params.add_integer('xresolution', xr)
			params.add_integer('yresolution', yr)
		
		
		# ColourSpace
		if self.luxrender_colorspace.preset:
			cs_object = getattr(colorspace_presets, self.luxrender_colorspace.preset_name)
		else:
			cs_object = self.luxrender_colorspace
			
		params.add_float('gamma', self.get_gamma())
		params.add_float('colorspace_white',	[cs_object.cs_whiteX,	cs_object.cs_whiteY])
		params.add_float('colorspace_red',		[cs_object.cs_redX,		cs_object.cs_redY])
		params.add_float('colorspace_green',	[cs_object.cs_greenX,	cs_object.cs_greenY])
		params.add_float('colorspace_blue',		[cs_object.cs_blueX,	cs_object.cs_blueY])
		
		# Camera Response Function
		if self.luxrender_colorspace.use_crf == 'file'and self.luxrender_colorspace.crf_file != '':
			if scene.camera.library is not None:
				local_crf_filepath = bpy.path.abspath(self.luxrender_colorspace.crf_file, scene.camera.library.filepath)
			else:
				local_crf_filepath = self.luxrender_colorspace.crf_file
			local_crf_filepath = efutil.filesystem_path( local_crf_filepath )
			if scene.luxrender_engine.allow_file_embed():
				from ..util import bencode_file2string
				params.add_string('cameraresponse', os.path.basename(local_crf_filepath))
				encoded_data = bencode_file2string(local_crf_filepath)
				params.add_string('cameraresponse_data', encoded_data.splitlines() )
			else:
				params.add_string('cameraresponse', local_crf_filepath)
		if self.luxrender_colorspace.use_crf == 'preset':
			params.add_string('cameraresponse', self.luxrender_colorspace.crf_preset)
		
		# Output types
		params.add_string('filename', get_output_filename(scene))
		params.add_bool('write_resume_flm', self.write_flm)
		params.add_bool('restart_resume_flm', self.restart_flm)
		params.add_bool('write_flm_direct', self.write_flm_direct)
		
		if self.output_alpha:
			output_channels = 'RGBA'
			params.add_bool('premultiplyalpha', True)
		else:
			output_channels = 'RGB'
								
		if scene.luxrender_engine.export_type == 'INT' and scene.luxrender_engine.integratedimaging:
			# Set up params to enable z buffer
			# we use the colorspace gamma, else autolinear gives wrong estimation, gamma 1.0 per pixel is recalculated in pylux after
			# Also, this requires tonemapped EXR output
			params.add_string('write_exr_channels', 'RGBA')
			params.add_bool('write_exr_halftype', False)
			params.add_bool('write_exr_applyimaging', True)
			params.add_bool('premultiplyalpha', True if self.output_alpha else False) # Blender 2.66 always expects premultiplyalpha
			params.add_bool('write_exr_ZBuf', True)
			params.add_string('write_exr_zbuf_normalizationtype', 'Camera Start/End clip')
		else:
			# Otherwise let the user decide on tonemapped EXR and other EXR settings
			params.add_bool('write_exr_halftype', self.write_exr_halftype)
			params.add_bool('write_exr_applyimaging', self.write_exr_applyimaging)
			params.add_bool('write_exr_ZBuf', self.write_zbuf)
			params.add_string('write_exr_compressiontype', self.write_exr_compressiontype)
			params.add_string('write_exr_zbuf_normalizationtype', self.zbuf_normalization)
			params.add_bool('write_exr', self.write_exr)
			params.add_string('write_exr_channels', output_channels)
		
		params.add_bool('write_png', self.write_png)
		params.add_string('write_png_channels', output_channels)
		if self.write_png:
			params.add_bool('write_png_16bit', self.write_png_16bit)
		params.add_bool('write_tga', self.write_tga)
		params.add_string('write_tga_channels', output_channels)
		if self.write_tga:
			params.add_bool('write_tga_ZBuf', self.write_zbuf)
			params.add_string('write_tga_zbuf_normalizationtype', self.zbuf_normalization)
		
		params.add_string('ldr_clamp_method', self.ldr_clamp_method)
		
		if scene.luxrender_engine.export_type == 'EXT':
			params.add_integer('displayinterval', self.displayinterval)
			params.add_integer('writeinterval', self.writeinterval)
			params.add_integer('flmwriteinterval', self.flmwriteinterval)
		else:
			params.add_integer('writeinterval', self.internal_updateinterval)
		
		# Halt conditions
		if scene.luxrender_halt.haltspp > 0:
			params.add_integer('haltspp', scene.luxrender_halt.haltspp)
		
		if scene.luxrender_halt.halttime > 0:
			params.add_integer('halttime', scene.luxrender_halt.halttime)

		if scene.luxrender_halt.haltthreshold > 0:
			params.add_float('haltthreshold', 1 / 10.0**scene.luxrender_halt.haltthreshold)
		
		# Convergence Test
		if scene.luxrender_halt.convergencestep != 32:
			params.add_float('convergencestep', scene.luxrender_halt.convergencestep)
		
		# Filename for User Sampling Map
		if scene.luxrender_sampler.usersamplingmap_filename != '':
			if scene.luxrender_sampler.usersamplingmap_filename.endswith('.exr'):
				params.add_string('usersamplingmap_filename', scene.luxrender_sampler.usersamplingmap_filename)
			else:
				params.add_string('usersamplingmap_filename', scene.luxrender_sampler.usersamplingmap_filename + '.exr')
				
		if self.outlierrejection_k > 0 and scene.luxrender_rendermode.renderer != 'sppm':
			params.add_integer('outlierrejection_k', self.outlierrejection_k)
			
		params.add_integer('tilecount', self.tilecount)
		
		# update the film settings with tonemapper settings
		params.update( self.luxrender_tonemapping.get_paramset() )
		
		return ('fleximage', params)
Example #45
0
def get_real_path(path):
    return os.path.realpath(efutil.filesystem_path(path))
Example #46
0
    def render(self, context):
        '''
        Render the scene file, or in our case, export the frame(s)
        and launch an Indigo process.
        '''

        with RENDERENGINE_indigo.render_lock:    # Just render one thing at a time.
            self.renderer            = None
            self.message_thread      = None
            self.stats_thread        = None
            self.framebuffer_thread  = None
            self.render_update_timer = None
            self.rendering           = False

            # force scene update to current rendering frame
            # Not sure why - Yves
            #context.frame_set(context.frame_current)

            #------------------------------------------------------------------------------
            # Export the Scene

            # Get the frame path.
            frame_path = efutil.filesystem_path(context.render.frame_path())

            # Get the filename for the frame sans extension.
            image_out_path = os.path.splitext(frame_path)[0]

            # Generate the name for the scene file(s).
            if context.indigo_engine.use_output_path == True:
                # Get the output path from the frame path.
                output_path = os.path.dirname(frame_path)

                # Generate the output filename
                output_filename = '%s.%s.%05i.igs' % (efutil.scene_filename(), bpy.path.clean_name(context.name), context.frame_current)
            else:
                # Get export path from the indigo_engine.
                export_path = efutil.filesystem_path(context.indigo_engine.export_path)

                # Get the directory name from the output path.
                output_path = os.path.dirname(export_path)

                # Get the filename from the output path and remove the extension.
                output_filename = os.path.splitext(os.path.basename(export_path))[0]

                # Count contiguous # chars and replace them with the frame number.
                # If the hash count is 0 and we are exporting an animation, append the frame numbers.
                hash_count = util.count_contiguous('#', output_filename)
                if hash_count != 0:
                    output_filename = output_filename.replace('#'*hash_count, ('%%0%0ii'%hash_count)%context.frame_current)
                elif self.is_animation:
                    output_filename = output_filename + ('%%0%0ii'%4)%context.frame_current

                # Add .igs extension.
                output_filename += '.igs'


            # The full path of the exported scene file.
            exported_file = '/'.join([
                output_path,
                output_filename
            ])

            # Create output_path if it does not exist.
            if not os.path.exists(output_path):
                os.makedirs(output_path)

            # If an animation is rendered, write an indigo queue file (.igq).
            if self.is_animation:
                igq_filename = '%s/%s.%s.igq'%(output_path, efutil.scene_filename(), bpy.path.clean_name(context.name))

                if context.frame_current == context.frame_start:
                    # Start a new igq file.
                    igq_file = open(igq_filename, 'w')
                    igq_file.write('<?xml version="1.0" encoding="utf-8" standalone="no" ?>\n')
                    igq_file.write('<render_queue>\n')
                else:
                    # Append to existing igq.
                    igq_file = open(igq_filename, 'a')
                    
                rnd = random.Random()
                rnd.seed(context.frame_current)

                # Write igq item.
                igq_file.write('\t<item>\n')
                igq_file.write('\t\t<scene_path>%s</scene_path>\n' % exported_file)
                igq_file.write('\t\t<halt_time>%d</halt_time>\n' % context.indigo_engine.halttime)
                igq_file.write('\t\t<halt_spp>%d</halt_spp>\n' % context.indigo_engine.haltspp)
                igq_file.write('\t\t<output_path>%s</output_path>\n' % image_out_path)
                igq_file.write('\t\t<seed>%s</seed>\n' % rnd.randint(1, 1000000))
                igq_file.write('\t</item>\n')

                # If this is the last frame, write the closing tag.
                if context.frame_current == context.frame_end:
                    igq_file.write('</render_queue>\n')

                igq_file.close()

                # Calculate the progress by frame with frame range (fr) and frame offset (fo).
                fr = context.frame_end - context.frame_start
                fo = context.frame_current - context.frame_start
                self.update_progress(fo/fr)

            scene_writer = indigo.operators._Impl_OT_indigo(
                directory = output_path,
                filename = output_filename
            ).set_report(self.report)

            # Write the scene file.
            export_result = scene_writer.execute(context)

            # Return if the export didn't finish.
            if not 'FINISHED' in export_result:
                return

            #------------------------------------------------------------------------------
            # Update indigo defaults config file .
            config_updates = {
                'auto_start': context.indigo_engine.auto_start,
                'console_output': context.indigo_engine.console_output
            }

            if context.indigo_engine.use_console:
                indigo_path = getConsolePath(context)
            else:
                indigo_path = getGuiPath(context)

            if os.path.exists(indigo_path):
                config_updates['install_path'] = getInstallPath(context)

            try:
                for k,v in config_updates.items():
                    efutil.write_config_value('indigo', 'defaults', k, v)
            except Exception as err:
                indigo_log('Saving indigo config failed: %s' % err, message_type='ERROR')

            # Make sure that the Indigo we are going to launch is at least as
            # new as the exporter version.
            version_ok = True
            if not context.indigo_engine.skip_version_check:
                iv = getVersion(context)
                for i in range(3):
                    version_ok &= iv[i]>=bl_info['version'][i]

            #------------------------------------------------------------------------------
            # Conditionally Spawn Indigo.
            if context.indigo_engine.auto_start:

                exe_path = efutil.filesystem_path( indigo_path )

                if not os.path.exists(exe_path):
                    print("Failed to find indigo at '" + str(exe_path) + "'")
                    msg = "Failed to find indigo at '" + str(exe_path) + "'."
                    msg + "\n  "
                    msg += "Please make sure you have Indigo installed, and that the path to indigo in the 'Indigo Render Engine Settings' is set correctly."
                    self.report({'ERROR'}, msg)

                #if not version_ok:
                    #indigo_log("Unsupported version v%s; Cannot start Indigo with this scene" % ('.'.join(['%s'%i for i in iv])), message_type='ERROR')
                    #return

                # if it's an animation, don't execute until final frame
                if self.is_animation and context.frame_current != context.frame_end:
                    return

                # if animation and final frame, launch queue instead of single frame
                if self.is_animation and context.frame_current == context.frame_end:
                    exported_file = igq_filename
                    indigo_args = [
                        exe_path,
                        exported_file
                    ]
                else:
                    indigo_args = [
                        exe_path,
                        exported_file,
                        '-o',
                        image_out_path + '.png'
                    ]

                # Set master or working master command line args.
                if context.indigo_engine.network_mode == 'master':
                    indigo_args.extend(['-n', 'm'])
                elif context.indigo_engine.network_mode == 'working_master':
                    indigo_args.extend(['-n', 'wm'])

                # Set port arg if network rendering is enabled.
                if context.indigo_engine.network_mode in ['master', 'working_master']:
                    indigo_args.extend([
                        '-p',
                        '%i' % context.indigo_engine.network_port
                    ])

                # Set hostname and port arg.
                if context.indigo_engine.network_mode == 'manual':
                    indigo_args.extend([
                        '-h',
                        '%s:%i' % (context.indigo_engine.network_host, context.indigo_engine.network_port)
                ])

                # indigo_log("Starting indigo: %s" % indigo_args)

                # If we're starting a console or should wait for the process, listen to the output.
                if context.indigo_engine.use_console or context.indigo_engine.wait_for_process:
                    f_stdout = subprocess.PIPE
                else:
                    f_stdout = None

                # Launch the Indigo process.
                indigo_proc = subprocess.Popen(indigo_args, stdout=f_stdout)
                indigo_pid = indigo_proc.pid
                indigo_log('Started Indigo process, PID: %i' % indigo_pid)

                # Wait for the render to finish if we use the console or should wait for the process.
                if context.indigo_engine.use_console or context.indigo_engine.wait_for_process:
                    while indigo_proc.poll() == None:
                        indigo_proc.communicate()
                        time.sleep(2)

                    indigo_proc.wait()
                    if not indigo_proc.stdout.closed:
                        indigo_proc.communicate()
                    if indigo_proc.returncode == -1:
                        sys.exit(-1)

            else:
                indigo_log("Scene was exported to %s" % exported_file)

            #------------------------------------------------------------------------------
            # Finished
            return
Example #47
0
def get_intermediate_dir(force_debug=False):
    global intermediate_dir
    return_path = intermediate_dir
    if force_debug is True:
        return_path = get_sort_dir()
    return efutil.filesystem_path(return_path) + "/"
Example #48
0
def get_sort_dir():
    preferences = bpy.context.user_preferences.addons['sortblend'].preferences
    return_path = preferences.install_path
    if platform.system() == 'Windows':
        return return_path
    return efutil.filesystem_path(return_path) + "/"
Example #49
0
    def exportLamp(self, scene, lamp):
        ltype = lamp.data.type
        name = lamp.name
        mult = lamp.data.mitsuba_lamp.intensity
        if lamp.data.mitsuba_lamp.inside_medium:
            self.exportMedium(
                scene.mitsuba_media.media[lamp.data.mitsuba_lamp.lamp_medium])
        if ltype == 'POINT':
            self.openElement('shape', {'type': 'sphere'})
            self.exportPoint(lamp.location)
            self.parameter('float', 'radius',
                           {'value': lamp.data.mitsuba_lamp.radius})
            self.openElement('emitter', {
                'id': '%s-light' % name,
                'type': 'area'
            })
            self.parameter(
                'rgb', 'radiance', {
                    'value':
                    "%f %f %f" % (lamp.data.color.r * mult, lamp.data.color.g *
                                  mult, lamp.data.color.b * mult)
                })
            self.parameter(
                'float', 'samplingWeight',
                {'value': '%f' % lamp.data.mitsuba_lamp.samplingWeight})
            if lamp.data.mitsuba_lamp.inside_medium:
                self.element('ref', {'id': lamp.data.mitsuba_lamp.lamp_medium})
            self.closeElement()
            self.closeElement()
        elif ltype == 'AREA':
            self.openElement('shape', {'type': 'rectangle'})
            self.parameter('boolean', 'flipNormals', {'value': 'true'})
            (size_x, size_y) = (lamp.data.size / 2.0, lamp.data.size / 2.0)
            if lamp.data.shape == 'RECTANGLE':
                size_y = lamp.data.size_y / 2.0
            self.openElement('transform', {'name': 'toWorld'})
            loc, rot, sca = lamp.matrix_world.decompose()
            mat_loc = mathutils.Matrix.Translation(loc)
            mat_rot = rot.to_matrix().to_4x4()
            mat_sca = mathutils.Matrix((
                (sca[0] * size_x, 0, 0, 0),
                (0, sca[1] * size_y, 0, 0),
                (0, 0, sca[2], 0),
                (0, 0, 0, 1),
            ))
            self.exportMatrix(mat_loc * mat_rot * mat_sca)
            self.closeElement()
            self.openElement('emitter', {
                'id': '%s-arealight' % name,
                'type': 'area'
            })
            self.parameter(
                'rgb', 'radiance', {
                    'value':
                    "%f %f %f" % (lamp.data.color.r * mult, lamp.data.color.g *
                                  mult, lamp.data.color.b * mult)
                })
            self.parameter(
                'float', 'samplingWeight',
                {'value': '%f' % lamp.data.mitsuba_lamp.samplingWeight})
            if lamp.data.mitsuba_lamp.inside_medium:
                self.element('ref', {'id': lamp.data.mitsuba_lamp.lamp_medium})
            self.closeElement()
            self.openElement('bsdf', {'type': 'diffuse'})
            self.parameter('spectrum', 'reflectance', {'value': '0'})
            self.closeElement()
            self.closeElement()
        elif ltype == 'SUN':
            # sun is considered hemi light by Mitsuba
            if self.hemi_lights >= 1:
                # Mitsuba supports only one hemi light
                return False
            self.hemi_lights += 1
            invmatrix = lamp.matrix_world
            skyType = lamp.data.mitsuba_lamp.mitsuba_lamp_sun.sunsky_type
            LampParams = getattr(lamp.data.mitsuba_lamp,
                                 'mitsuba_lamp_sun').get_paramset(lamp)
            if skyType == 'sunsky':
                self.openElement('emitter', {
                    'id': '%s-light' % name,
                    'type': 'sunsky'
                })
            elif skyType == 'sun':
                self.openElement('emitter', {
                    'id': '%s-light' % name,
                    'type': 'sun'
                })
            elif skyType == 'sky':
                self.openElement('emitter', {
                    'id': '%s-light' % name,
                    'type': 'sky'
                })
                #self.parameter('boolean', 'extend', {'value' : '%s' % str(lamp.data.mitsuba_lamp.mitsuba_lamp_sun.extend).lower()})
            LampParams.export(self)
            self.openElement('transform', {'name': 'toWorld'})
            #rotate around x to make z UP. Default Y - UP
            self.element('rotate', {'x': '1', 'angle': '90'})
            self.closeElement()
            #self.exportWorldTrafo()
            #self.parameter('float', 'turbidity', {'value' : '%f' % (lamp.data.mitsuba_lamp.mitsuba_lamp_sun.turbidity)})
            #ot_mat = mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1]))	#to make Z up rotate 90 around X
            #rotatedSun = invmatrix * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([1, 0, 0])) * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1]))
            self.parameter(
                'vector', 'sunDirection', {
                    'x': '%f' % invmatrix[0][2],
                    'y': '%f' % invmatrix[1][2],
                    'z': '%f' % invmatrix[2][2]
                })
            self.closeElement()

        elif ltype == 'SPOT':
            self.openElement('emitter', {
                'id': '%s-light' % name,
                'type': 'spot'
            })
            self.exportWorldTrafo(
                lamp.matrix_world *
                mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
            self.parameter(
                'rgb', 'intensity', {
                    'value':
                    "%f %f %f" % (lamp.data.color.r * mult, lamp.data.color.g *
                                  mult, lamp.data.color.b * mult)
                })
            self.parameter(
                'float', 'cutoffAngle',
                {'value': '%f' % (lamp.data.spot_size * 180 / (math.pi * 2))})
            self.parameter(
                'float', 'beamWidth', {
                    'value':
                    '%f' %
                    ((1 - lamp.data.spot_blend) * lamp.data.spot_size * 180 /
                     (math.pi * 2))
                })
            self.parameter(
                'float', 'samplingWeight',
                {'value': '%f' % lamp.data.mitsuba_lamp.samplingWeight})
            if lamp.data.mitsuba_lamp.inside_medium:
                self.element('ref', {'id': lamp.data.mitsuba_lamp.lamp_medium})
            self.closeElement()
        elif ltype == 'HEMI':
            if self.hemi_lights >= 1:
                # Mitsuba supports only one hemi light
                return False
            self.hemi_lights += 1
            if lamp.data.mitsuba_lamp.envmap_type == 'constant':
                self.openElement('emitter', {
                    'id': '%s-light' % name,
                    'type': 'constant'
                })
                self.parameter(
                    'float', 'samplingWeight',
                    {'value': '%f' % lamp.data.mitsuba_lamp.samplingWeight})
                self.parameter(
                    'rgb', 'radiance', {
                        'value':
                        "%f %f %f" %
                        (lamp.data.color.r * mult, lamp.data.color.g * mult,
                         lamp.data.color.b * mult)
                    })
                self.closeElement()
            elif lamp.data.mitsuba_lamp.envmap_type == 'envmap':
                self.openElement('emitter', {
                    'id': '%s-light' % name,
                    'type': 'envmap'
                })
                self.parameter(
                    'string', 'filename', {
                        'value':
                        efutil.filesystem_path(
                            lamp.data.mitsuba_lamp.envmap_file)
                    })
                self.exportWorldTrafo(
                    lamp.matrix_world *
                    mathutils.Matrix.Rotation(radians(90.0), 4, 'X'))
                self.parameter(
                    'float', 'scale',
                    {'value': '%f' % lamp.data.mitsuba_lamp.intensity})
                self.parameter(
                    'float', 'samplingWeight',
                    {'value': '%f' % lamp.data.mitsuba_lamp.samplingWeight})
                self.closeElement()
Example #50
0
    def exportLamp(self, scene, lamp, idx):
        ltype = lamp.data.type
        name = translate_id(lamp.name)
        mult = lamp.data.mitsuba_lamp.intensity
        if lamp.data.mitsuba_lamp.inside_medium:
            self.exportMedium(
                scene.mitsuba_media.media[lamp.data.mitsuba_lamp.lamp_medium])
        if ltype == 'POINT':
            self.openElement('luminaire', {
                'type': 'point',
                'id': '%s-light' % name
            })
            self.exportWorldTrafo(lamp.matrix_world)
            self.parameter(
                'rgb', 'intensity', {
                    'value':
                    "%f %f %f" % (lamp.data.color.r * mult, lamp.data.color.g *
                                  mult, lamp.data.color.b * mult)
                })
            self.parameter(
                'float', 'samplingWeight',
                {'value': '%f' % lamp.data.mitsuba_lamp.samplingWeight})
            if lamp.data.mitsuba_lamp.inside_medium:
                self.element('ref', {'id': lamp.data.mitsuba_lamp.lamp_medium})
            self.closeElement()
        elif ltype == 'AREA':
            self.element('remove', {'id': '%s-light' % name})
            self.openElement('shape', {'type': 'obj'})
            (size_x, size_y) = (lamp.data.size, lamp.data.size)
            if lamp.data.shape == 'RECTANGLE':
                size_y = lamp.data.size_y
            mult = mult / (2 * size_x * size_y)
            filename = "area_luminaire_%d.obj" % idx
            try:
                os.mkdir(self.meshes_dir)
            except OSError:
                pass
            self.parameter('string', 'filename',
                           {'value': 'meshes/%s' % filename})
            self.exportWorldTrafo(lamp.matrix_world)

            self.openElement('luminaire', {
                'id': '%s-arealight' % name,
                'type': 'area'
            })
            if lamp.data.mitsuba_lamp.inside_medium:
                self.element('ref', {'id': lamp.data.mitsuba_lamp.lamp_medium})
            self.parameter(
                'rgb', 'intensity', {
                    'value':
                    "%f %f %f" % (lamp.data.color.r * mult, lamp.data.color.g *
                                  mult, lamp.data.color.b * mult)
                })
            self.closeElement()
            self.openElement('bsdf', {'type': 'lambertian'})
            self.parameter('spectrum', 'reflectance', {'value': '0'})
            self.closeElement()
            self.closeElement()
            path = os.path.join(self.meshes_dir, filename)
            objFile = open(path, 'w')
            objFile.write('v %f %f 0\n' % (-size_x / 2, -size_y / 2))
            objFile.write('v %f %f 0\n' % (size_x / 2, -size_y / 2))
            objFile.write('v %f %f 0\n' % (size_x / 2, size_y / 2))
            objFile.write('v %f %f 0\n' % (-size_x / 2, size_y / 2))
            objFile.write('f 4 3 2 1\n')
            objFile.close()
        elif ltype == 'SUN':
            self.openElement('luminaire', {
                'id': '%s-light' % name,
                'type': 'directional'
            })
            scale = mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1]))
            self.exportWorldTrafo(
                lamp.matrix_world *
                mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
            self.parameter(
                'rgb', 'intensity', {
                    'value':
                    "%f %f %f" % (lamp.data.color.r * mult, lamp.data.color.g *
                                  mult, lamp.data.color.b * mult)
                })
            self.parameter(
                'float', 'samplingWeight',
                {'value': '%f' % lamp.data.mitsuba_lamp.samplingWeight})
            self.closeElement()
        elif ltype == 'SPOT':
            self.openElement('luminaire', {
                'id': '%s-light' % name,
                'type': 'spot'
            })
            self.exportWorldTrafo(
                lamp.matrix_world *
                mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
            self.parameter(
                'rgb', 'intensity', {
                    'value':
                    "%f %f %f" % (lamp.data.color.r * mult, lamp.data.color.g *
                                  mult, lamp.data.color.b * mult)
                })
            self.parameter(
                'float', 'cutoffAngle',
                {'value': '%f' % (lamp.data.spot_size * 180 / (math.pi * 2))})
            self.parameter(
                'float', 'beamWidth', {
                    'value':
                    '%f' % (lamp.data.spot_blend * lamp.data.spot_size * 180 /
                            (math.pi * 2))
                })
            self.parameter(
                'float', 'samplingWeight',
                {'value': '%f' % lamp.data.mitsuba_lamp.samplingWeight})
            if lamp.data.mitsuba_lamp.inside_medium:
                self.element('ref', {'id': lamp.data.mitsuba_lamp.lamp_medium})
            self.closeElement()
        elif ltype == 'HEMI':
            if lamp.data.mitsuba_lamp.envmap_type == 'constant':
                self.openElement('luminaire', {
                    'id': '%s-light' % name,
                    'type': 'constant'
                })
                self.parameter(
                    'float', 'samplingWeight',
                    {'value': '%f' % lamp.data.mitsuba_lamp.samplingWeight})
                self.parameter(
                    'rgb', 'intensity', {
                        'value':
                        "%f %f %f" %
                        (lamp.data.color.r * mult, lamp.data.color.g * mult,
                         lamp.data.color.b * mult)
                    })
                self.closeElement()
            elif lamp.data.mitsuba_lamp.envmap_type == 'envmap':
                self.openElement('luminaire', {
                    'id': '%s-light' % name,
                    'type': 'envmap'
                })
                self.parameter(
                    'string', 'filename', {
                        'value':
                        efutil.filesystem_path(
                            lamp.data.mitsuba_lamp.envmap_file)
                    })
                self.exportWorldTrafo(lamp.matrix_world)
                self.parameter(
                    'float', 'intensityScale',
                    {'value': '%f' % lamp.data.mitsuba_lamp.intensity})
                self.parameter(
                    'float', 'samplingWeight',
                    {'value': '%f' % lamp.data.mitsuba_lamp.samplingWeight})
                self.closeElement()