diff --git a/terminalplotter.py b/terminalplotter.py index bc2afe5..625775b 100644 --- a/terminalplotter.py +++ b/terminalplotter.py @@ -11,6 +11,7 @@ import pyvista as pv import kitty +import numpy as np class TerminalPlotter(pv.Plotter): def __init__(self, width, height, **kwargs): @@ -21,11 +22,9 @@ class TerminalPlotter(pv.Plotter): # setup vtk rendering chain self.w2i_filter = vtk.vtkWindowToImageFilter() self.w2i_filter.SetInputBufferTypeToRGBA() - self.w2i_filter.ReadFrontBufferOff() + #self.w2i_filter.ReadFrontBufferOff() + self.w2i_filter.ReadFrontBufferOn() self.w2i_filter.SetInput(self.ren_win) - self.writer = vtk.vtkPNGWriter() - self.writer.WriteToMemoryOn() - self.writer.SetInputConnection(self.w2i_filter.GetOutputPort()) # enable transparency self.set_background([0.0, 0.0, 0.0]) self.ren_win.SetAlphaBitPlanes(1) @@ -80,14 +79,25 @@ class TerminalPlotter(pv.Plotter): termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) async def _render_loop(self): + import time while self._running: + start = time.perf_counter() # keep renedring the scene self.ren_win.Render() # Update the filter to grab the current buffer self.w2i_filter.Modified() self.w2i_filter.Update() - self.writer.Write() - await kitty.draw_to_terminal(self.writer.GetResult()) + vtk_image = self.w2i_filter.GetOutput() + width, height, _ = vtk_image.GetDimensions() + vtk_array = vtk_image.GetPointData().GetScalars() + np_image = numpy_support.vtk_to_numpy(vtk_array).reshape(height, width, 4) + np_image = np_image[::-1] # Flip vertically + np_image = np.ascontiguousarray(np_image) # Ensure memory layout is C-contiguous + print("Render & copy:", time.perf_counter() - start) + + #await kitty.draw_to_terminal(np_image, width, height, compress=True) + await kitty.draw_to_terminal(np_image, width, height, use_shm=True) + print("Draw:", time.perf_counter() - start) kitty.set_position(self.start_y, self.start_x) self.camera.Azimuth(1) @@ -99,4 +109,14 @@ class TerminalPlotter(pv.Plotter): asyncio.create_task(self._render_loop()), ] await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED) - self._running = False + self._running = False + +async def main(): + plotter = TerminalPlotter(1000, 1000) + mesh = pv.Sphere() + plotter.add_mesh(mesh) + await plotter.run() + +if __name__ == '__main__': + import cProfile + cProfile.run("asyncio.run(main())", "profile")