jupyter-widgets / pythreejs

A Jupyter - Three.js bridge
https://pythreejs.readthedocs.io
Other
936 stars 185 forks source link

Mouse control gets stuck and objects disappear when using multiple Renderers inside ipywidgets.interact #274

Open t-suzuki opened 5 years ago

t-suzuki commented 5 years ago

Hi, Thank you all for developing this awesome project!

Today I would like to report a peculiar behavior that when many (>=8 for example) Renderer()s are used inside a ipywidgets.interact function, OrbitControls() sometimes get stuck and objects in the scene disappear on some ordinary mouse operations (like L-dragging after R-dragging). However I am not sure this is a bug of pythreejs (maybe a bug of jupyter notebook, ipywidgets or even threejs?)

Please find repro code in the attached notebook (extension changed to .txt according to GitHub limitations). ManyRenderersInsideInteract.ipynb.txt

environment:

vidartf commented 5 years ago

Hi, and thanks for the kind words.

Browsers have a limit for how many concurrent webgl contexts it can have (typically 8 or 16), which is the likely cause for your >= 8. When pythreejs hits that limit, it will start switching out the webgl contexts with images, and re-purpose the contexts whenever it needs to draw. So if you have 8+ renderers each trying to update simultaneously, there is bound to be a performance hit.

That being said, the following things will be symptoms of a bug:

vidartf commented 5 years ago

I'll have a look at this later, but for now: Is there any output in the browser developer console when this happens? The console is typically accessible by pressing the F12 key on your keyboard when in the correct browser tab.

t-suzuki commented 5 years ago

Thanks for pointing out the number of WebGL contexts. It may be the trigger of the problem. However, the glitch only occurs when Renderer()s are used inside ipywidgets.interact but does not occur when directly IPython.display()ed. It suggests that the number of WebGL contexts is probably not the sole cause of the problem.

Also, the behavior happens even if single Renderer() with a very simple scene is updated once at a time and the others are not simultaneously updated. Therefore it does not seem to be a performance issue.

If it starts drawing all other renderers when you only interact with one (are you reusing objects across renderers?)

Sometimes, objects in other renderers disappear when interacting with another renderer. Renderer objects are not reused (calling create_renderer() each time to display a renderer; please find the code in the second cell of attached ipynb).

Developer console: I found some errors when running the problematic cell. It is recorded only once when the last cell is executed and no additional logs at the timing of the glitchy behavior. Error messages do not show up if renderers are directly passed to IPython.display() without ipywidgets.interact(). console

vidartf commented 5 years ago

In general, I would say that using pythreejs with interact is an anti-pattern. That being said, it might be that this is a symptom of an issue with pythreejs, so it might be worth looking into.