Skip to content
Snippets Groups Projects
render.py 104 KiB
Newer Older
  • Learn to ignore specific revisions
  •                         traceback.print_exc()
                            print ("***-DONE-***")
                            return False
    
    Campbell Barton's avatar
    Campbell Barton committed
    
    
                            print("Running POV-Ray 3.7 64 bits build with 32 bits Blender,\n" \
                                  "You might want to run Blender 64 bits as well.")
    
                            print("Command line arguments passed: " + str(extra_args))
                            return True
    
    Campbell Barton's avatar
    Campbell Barton committed
    
    
                    else:
                        print("POV-Ray 3.7 32 bits found")
    
                        print("Command line arguments passed: " + str(extra_args))
                        return True
    
            else:
                # DH - added -d option to prevent render window popup which leads to segfault on linux
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                isExists = False
                sysPathList = os.getenv("PATH").split(':')
                sysPathList.append("")
    
                for dirName in sysPathList:
                    if (os.path.exists(os.path.join(dirName, pov_binary))):
                        isExists = True
                        break
    
                if not isExists:
                    print("POV-Ray 3.7: could not found execute '%s' - not if PATH" % pov_binary)
                    import traceback
                    traceback.print_exc()
                    print ("***-DONE-***")
                    return False
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                    self._process = subprocess.Popen([pov_binary, self._temp_file_ini] + extra_args,
                                                     stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    
    
                except OSError:
                    # TODO, report api
                    print("POV-Ray 3.7: could not execute '%s'" % pov_binary)
                    import traceback
                    traceback.print_exc()
                    print ("***-DONE-***")
                    return False
    
                else:
                    print("POV-Ray 3.7 found")
                    print("Command line arguments passed: " + str(extra_args))
                    return True
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        def _cleanup(self):
            for f in (self._temp_file_in, self._temp_file_ini, self._temp_file_out):
    
                for i in range(5):
                    try:
                        os.unlink(f)
                        break
                    except OSError:
                        # Wait a bit before retrying file might be still in use by Blender,
                        # and Windows does not know how to delete a file in use!
                        time.sleep(self.DELAY)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
        def render(self, scene):
    
            import tempfile
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            print("***INITIALIZING***")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    ##WIP output format
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    ##        if r.file_format == 'OPENEXR':
    ##            fformat = 'EXR'
    ##            render.color_mode = 'RGBA'
    ##        else:
    ##            fformat = 'TGA'
    
    ##            r.file_format = 'TARGA'
    
    Maurice Raybaud's avatar
    Maurice Raybaud committed
    ##            r.color_mode = 'RGBA'
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            blendSceneName = bpy.data.filepath.split(os.path.sep)[-1].split(".")[0]
            povSceneName = ""
            povPath = ""
            renderImagePath = ""
    
    
            # has to be called to update the frame on exporting animations
            scene.frame_set(scene.frame_current)
    
                povPath = bpy.path.abspath(scene.pov.scene_path).replace('\\', '/')
    
                if povPath == "":
                    if bpy.path.abspath("//") != "":
                        povPath = bpy.path.abspath("//")
                    else:
                        povPath = tempfile.gettempdir()
                elif povPath.endswith("/"):
                    if povPath == "/":
                        povPath = bpy.path.abspath("//")
                    else:
    
                        povPath = bpy.path.abspath(scene.pov.scene_path)
    
                if not os.path.exists(povPath):
    
                    try:
                        os.makedirs(povPath)
                    except:
                        import traceback
                        traceback.print_exc()
    
                        print("POV-Ray 3.7: Cannot create scenes directory: %r" % povPath)
    
                        self.update_stats("", "POV-Ray 3.7: Cannot create scenes directory %r" % \
                                          povPath)
    
                '''
                # Bug in POV-Ray RC3
    
                renderImagePath = bpy.path.abspath(scene.pov.renderimage_path).replace('\\','/')
    
                if renderImagePath == "":
                    if bpy.path.abspath("//") != "":
                        renderImagePath = bpy.path.abspath("//")
                    else:
                        renderImagePath = tempfile.gettempdir()
                    #print("Path: " + renderImagePath)
                elif path.endswith("/"):
                    if renderImagePath == "/":
                        renderImagePath = bpy.path.abspath("//")
                    else:
    
                        renderImagePath = bpy.path.abspath(scene.pov.renderimage_path)
    
                if not os.path.exists(path):
                    print("POV-Ray 3.7: Cannot find render image directory")
                    self.update_stats("", "POV-Ray 3.7: Cannot find render image directory")
                    time.sleep(2.0)
                    return
                '''
    
                # check name
    
                    if blendSceneName != "":
                        povSceneName = blendSceneName
                    else:
                        povSceneName = "untitled"
                else:
    
                    if os.path.isfile(povSceneName):
                        povSceneName = os.path.basename(povSceneName)
                    povSceneName = povSceneName.split('/')[-1].split('\\')[-1]
                    if not povSceneName:
                        print("POV-Ray 3.7: Invalid scene name")
                        self.update_stats("", "POV-Ray 3.7: Invalid scene name")
                        time.sleep(2.0)
                        return
                    povSceneName = os.path.splitext(povSceneName)[0]
    
                print("Scene name: " + povSceneName)
                print("Export path: " + povPath)
    
                povPath = os.path.join(povPath, povSceneName)
    
                povPath = os.path.realpath(povPath)
    
    
                # for now this has to be the same like the pov output. Bug in POV-Ray RC3.
                # renderImagePath = renderImagePath + "\\" + povSceneName
    
                renderImagePath = povPath  # Bugfix for POV-Ray RC3 bug
    
                # renderImagePath = os.path.realpath(renderImagePath)  # Bugfix for POV-Ray RC3 bug
    
    
                #print("Export path: %s" % povPath)
                #print("Render Image path: %s" % renderImagePath)
    
            # start export
            self.update_stats("", "POV-Ray 3.7: Exporting data from Blender")
            self._export(scene, povPath, renderImagePath)
            self.update_stats("", "POV-Ray 3.7: Parsing File")
    
            if not self._render(scene):
                self.update_stats("", "POV-Ray 3.7: Not found")
                return
    
            r = scene.render
    
    Luca Bonavita's avatar
    Luca Bonavita committed
            # compute resolution
            x = int(r.resolution_x * r.resolution_percentage * 0.01)
            y = int(r.resolution_y * r.resolution_percentage * 0.01)
    
    
            # This makes some tests on the render, returning True if all goes good, and False if
            # it was finished one way or the other.
            # It also pauses the script (time.sleep())
            def _test_wait():
                time.sleep(self.DELAY)
    
                # User interrupts the rendering
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                if self.test_break():
                    try:
    
    Campbell Barton's avatar
    Campbell Barton committed
                        self._process.terminate()
    
    Campbell Barton's avatar
    Campbell Barton committed
                    except OSError:
    
    Luca Bonavita's avatar
    Luca Bonavita committed
                        pass
    
                # POV process is finisehd, one way or the other
    
    Campbell Barton's avatar
    Campbell Barton committed
                if poll_result is not None:
    
                    if poll_result < 0:
                        print("***POV PROCESS FAILED : %s ***" % poll_result)
                        self.update_stats("", "POV-Ray 3.7: Failed")
                    return False
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            # Wait for the file to be created
            # XXX This is no more valid, as 3.7 always creates output file once render is finished!
            parsing = re.compile(br"= \[Parsing\.\.\.\] =")
            rendering = re.compile(br"= \[Rendering\.\.\.\] =")
            percent = re.compile(r"\(([0-9]{1,3})%\)")
            # print("***POV WAITING FOR FILE***")
    
            data = b""
            last_line = ""
            while _test_wait():
                # POV in Windows does not output its stdout/stderr, it displays them in its GUI
                if self._is_windows:
                    self.update_stats("", "POV-Ray 3.7: Rendering File")
                else:
    
    Campbell Barton's avatar
    Campbell Barton committed
                    if not t_data:
                        continue
    
                    # XXX This is working for UNIX, not sure whether it might need adjustments for
                    #     other OSs
                    # First replace is for windows
                    t_data = str(t_data).replace('\\r\\n', '\\n').replace('\\r', '\r')
    
                    lines = t_data.split('\\n')
                    last_line += lines[0]
                    lines[0] = last_line
                    print('\n'.join(lines), end="")
                    last_line = lines[-1]
    
                    if rendering.search(data):
                        _pov_rendering = True
                        match = percent.findall(str(data))
                        if match:
                            self.update_stats("", "POV-Ray 3.7: Rendering File (%s%%)" % match[-1])
                        else:
                            self.update_stats("", "POV-Ray 3.7: Rendering File")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                    elif parsing.search(data):
                        self.update_stats("", "POV-Ray 3.7: Parsing File")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            if os.path.exists(self._temp_file_out):
                # print("***POV FILE OK***")
                #self.update_stats("", "POV-Ray 3.7: Rendering")
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                xmin = int(r.border_min_x * x)
                ymin = int(r.border_min_y * y)
                xmax = int(r.border_max_x * x)
                ymax = int(r.border_max_y * y)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                # print("***POV UPDATING IMAGE***")
                result = self.begin_result(0, 0, x, y)
    
                # XXX, tests for border render.
                #result = self.begin_result(xmin, ymin, xmax - xmin, ymax - ymin)
                #result = self.begin_result(0, 0, xmax - xmin, ymax - ymin)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
                # This assumes the file has been fully written We wait a bit, just in case!
                time.sleep(self.DELAY)
                try:
                    lay.load_from_file(self._temp_file_out)
    
                    # XXX, tests for border render.
                    #lay.load_from_file(self._temp_file_out, xmin, ymin)
    
                except RuntimeError:
                    print("***POV ERROR WHILE READING OUTPUT FILE***")
    
                # Not needed right now, might only be useful if we find a way to use temp raw output of
                # pov 3.7 (in which case it might go under _test_wait()).
    #            def update_image():
    #                # possible the image wont load early on.
    #                try:
    #                    lay.load_from_file(self._temp_file_out)
    
    #                    # XXX, tests for border render.
    #                    #lay.load_from_file(self._temp_file_out, xmin, ymin)
    #                    #lay.load_from_file(self._temp_file_out, xmin, ymin)
    
    #                except RuntimeError:
    #                    pass
    
    #            # Update while POV-Ray renders
    #            while True:
    #                # print("***POV RENDER LOOP***")
    
    #                # test if POV-Ray exists
    #                if self._process.poll() is not None:
    #                    print("***POV PROCESS FINISHED***")
    #                    update_image()
    #                    break
    
    #                # user exit
    #                if self.test_break():
    #                    try:
    #                        self._process.terminate()
    #                        print("***POV PROCESS INTERRUPTED***")
    #                    except OSError:
    #                        pass
    
    #                    break
    
    #                # Would be nice to redirect the output
    #                # stdout_value, stderr_value = self._process.communicate() # locks
    
    #                # check if the file updated
    #                new_size = os.path.getsize(self._temp_file_out)
    
    #                if new_size != prev_size:
    #                    update_image()
    #                    prev_size = new_size
    
    #                time.sleep(self.DELAY)
    
                self.end_result(result)
    
    Luca Bonavita's avatar
    Luca Bonavita committed
    
    
            if scene.pov.tempfiles_enable or scene.pov.deletefiles_enable:
    
                self._cleanup()