0

My goal:

Write a class that plots something after creating a window and using vao.render(mode=moderngl.PATCHES) only when an update() method is called, in order to update a dynamic VBO. imshow by matplotlib is just toooo slow.

The issue:

Based on these Github issues #114, #216 and this example, I created a custom window setup that does not have a run() method. Instead, a vertex array object (VAO), which is an instance attribute of the class, is rendered once when the class is initialized. Then an update(inputs) method is used to change a dynamic vertex buffer object (VBO), also an instance attribute, by using self.vbo.write(inputs) and the VAO is re-rendered, followed by a swap_buffers() call.

BUT I cannot resize/move/close the window when other python codes are running.

The question:

Is there a simple way to "fix" this issue?


What I've done thus far

Taking matplotlib.pyplot.show() as inspiration, though ultimately adulterating the idea, I created a dictionary as a class attribute.

For every new object created from my class, a distinct int is added as a key to this dictionary with the corresponding value being an alias of the object itself.

Then I created a static method that render()s all open objects of this class indefinitely, until the last one is closed.

The issue with this is that it is a bit unresponsive...

Below there is a sample of the idea I programmed:

# to illustrate the main packages I actually use, they are written here
import numpy as np
import moderngl
import moderngl_window
from moderngl_window.conf import settings


class myViewerClass:

    # A dict as a mutable class attribute to keep track
    # of all instances of this class
    _manager_dict = {}

    def __init__(self):  # there can be more inputs here

        # more code here

        # Edit: I initialize the windows here using settings
        # close, resize, key, mouse click events, among others
        # are all implemented here
        self.wnd = moderngl_window.create_window_from_settings()

        # if no instances of this class exists yet
        if not myViewerClass._manager_dict:
            # assign a key of 0 to the first instance of this class
            self._num = 0
        else:
            # else, assign a distinct integer greater than the maximum
            # one found in the dict's keys
            self._num = max(myViewerClass._manager_dict.keys())+1
        # save an alias of the generated object in the dict
        myViewerClass._manager_dict[self._num] = self

    @staticmethod
    def show_all():
        # run while there are still open windows
        # this works because the dictionary evaluates to True
        # while it is not empty
        while myViewerClass._manager_dict:
            for window in myViewerClass._manager_dict.values():
                window.wnd.clear()  # this is from moderngl_window
                window.render()  # this is an instance method that is
                                 # implemented in this class using
                                 # OpenGL (ModernGL)
                window.wnd.swap_buffers()  # also from moderngl_window
                if window.wnd.is_closing():
                    # delete this object's entry in the class dict
                    del myViewerClass._manager_dict[window._num]
                    # close the window
                    window.wnd.destroy()
                    break  # this is necessary because the dict's
                           # length has changed, which issues an
                           # error in the `for` loop


Edit 1: The above code does work. For either a single or multiple objects. But the myViewerClass.show_all() method seems a bit laggy. After manipulating one window (e.g. resizing it), the others start flickering. The flickering stops after clicking on them.

And after clicking on the close button of a certain window, if there are more than one windows open, it freezes instead of closing, while the other windows continue functioning. Suppose I had originally 3 windows open and close two of them, they freeze, but the third one continues working. All of the windows close simultaneously only after closing the third one as well.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Breno
  • 748
  • 8
  • 18
  • I have never coded OpenGL in python, but have you`"registered window events"` correctly, according to the link you put above : `# register event methods, self.wnd.resize_func = self.resize, self.wnd.close_func = self.close` – Dstarred Jul 30 '21 at 07:27
  • Yes! These events are configured using `settings`. I've added an edit to the code snippet. Plus, I gave a better explanation on how the issue manifests itself. Perhaps the issue has changed? "How to have multiple windows simultaneously active with no lag"? – Breno Jul 30 '21 at 12:18

0 Answers0