I’m using BabylonJS in a Vue application, and I need to dispose everything when unmounting the component.
I have a scene open with many meshes, most of which instances (>25k). Calling dispose() on this scene (or on the engine) takes approximately 40 seconds, which is absolutely unusable for my application, since the whole page freezes until this call is done.
When unmounting the component I dispose everything (scene, engine) and set all references to null. Mounting the component again creates a completely new scene and engine.
How should I go about this issue? Do I really need to call dispose()?
Other than that, hide all meshes and dispose them in chunks in the background? If hiding is too slow as well, set canvas to hidden? Then dispose engine/scene.
Thanks! Using the options helped a bit, while using blockfreeActiveMeshesAndRenderingGroups really improved the performance by reducing dispose time from 40 seconds down to 15.
However, 15 seconds is still kind of annoying for UX, so I could try hiding and disposing them in the background. But how can I do things “in the background”? In JS I can’t really do that, in any case it would be executed at some point and when it does it would freeze the UI.
I thought maybe because my 25k meshes are much bigger than the 15k in the playground. Those add up to 2.5M vertices, while in my case it’s 72M vertices. I tried using 150k spheres in the playground which resulted in about 35M vertices, and disposing still took only about 300ms.
In my case, everything takes up about 300 MB in memory, while the playground with 25k spheres is about 260MB. So again, that’s still not the issue.
About Vue, I do have a ref on the root TransformNode, one on the Scene, and one on the Engine. I just realised that I could probably use a shallowRef. I’ll try that and get back here.
why would you do that … you dont even need shallowref , you need to use markRaw if they are declared in a store , inside a component you can just use var and it wont be tracked
I’m not using a store, It’s a self-contained component. I’m using the Vue.js 3 composition API and I just used ref because I’m obsessed by immutability and liked having all consts, even though refs are definitely mutable in the end…
I’ll use lets, or probably still shallowRefs because I might need to watch them in the future.
I dont think this is a good idea , vue framework might offer all fancy things like reactivity and watching , but its not always the best choice to do so , and even they say so in their documentation.
You should probably think of using other code constructs , event listeners or observables etc to handle functionaliy when things need to update based on change , not watching props inside the 3d engine using vue, besides if its declared shallow ref then changes within the engine wont trigger updates in a deeeper watched property
My component has a single prop that is a “spec”, a plain object, describing how a simulation should look. The component passes this spec to a class that reads it and creates a static simulation based on this spec, and this simulation is rendered inside the BabylonJS scene.
The only thing that I watch for the moment is this prop. When it changes, I dispose the current simulation meshes, create the new one, and render it inside the scene again.
I don’t need to watch anything that is managed by BabylonJS for the moment. I guess I could really just use three lets.