What is the most optimal way to select meshes from the scene?

Just to give a bit of background…

In my sci-fi strategy game project, I am using BabylonJS in tandem with React+Redux. It is done via super thin, integration layer. Putting implementation details aside, main consideration is providing relevant pieces of mesh related data to (and sharing it between) different components.

I find Redux store (because of its nature) to be less than ideal for storing mesh references. Only use it for storing game entity data including ids. IDs are then assigned to related meshes upon their instantiation. IDs along with entity types are then fed to to all interested components.

So… I have all relevant data (id, tags, names, etc.) needed to select meshes from the scene. From mesh API docs I can see there are multiple methods allowing to do so:

So far I am accessing meshes by getMeshByID without any performance issues but find myself puzzled by following:

  1. what is the most optimal way to select meshes from the scene and how do those methods affect overall application performance assuming I will run them multiple times every frame.

  2. Is there really a need for both id and unique id? Shouldn’t id already be unique?

Any comments would be highly appreciated.

I’ll begin to answer from the point #2.
Here is the small example - https://playground.babylonjs.com/#1KUJ0A#441

As you see, both spheres have the same ID and the same name. It happens quite often in 3D modelling, so in order to distinguish meshes Babylon.js assigns to each mesh auto-generated unique ID. Please note that every time you start the script you may have different unique IDs. Some examples - Playground search page | Babylon.js Documentation
But having the same IDs is not always bad since it gives you the opportunity to choose all meshes with the same IDs with scene.getMeshesByID (you’ll get the array of meshes).
There could be also other cases, for example cloned meshes with the same name and different IDs.

So the first 3 functions you’ve mentioned will give you needed mesh.
scene.getMeshesByID will give the list of meshes with this ID
scene.getMeshesByTags will give you all meshes with the given tag (assuming that this tag was assigned earlier).

As for performance, all these functions are very fast ones.

P.S. Here is good example of using getMeshByUniqueID function - https://playground.babylonjs.com/#BLXMHV#3

3 Likes

If you really do a lot of getMeshByXXX() calls in a frame, you can speed things up by maintaining a map (id => mesh) on your side. The lookups in this map will be done in constant time, whereas the getMeshByXXX() methods operates in linear time because they loop through all the meshes of the scene to find the one(s) you want.

3 Likes

Re question 2:
Thanks @labris.
It makes perfect sense. I wasn’t aware non-unique IDs are common in 3D modelling. Thank you for clarifying.

Ok… now onto question 1

I keep considering pretty much what @Evgeni_Popov described.

In the nutshell that would be done with a dictionary of meshes that then can be injected into components via context provider. Maintaining meshes in { [entityId: string]: Mesh } type is very straightforward, considered my entity ids are guaranteed to actually be unique.

To protect dictionary mutation, accessing meshes would be done via getMeshById but then I am pretty much duplicating mesh selector method BabylonJS comes with. And that doesn’t feel right. Hence the question about performance.

@labris says:

As for performance, all these functions are very fast ones.

So far I haven’t experience any noticeable performance issues, which is a good sign. Will keep an eye on that but so far looks like I don’t really need it.

Thanks for helping out with that guys!

However, there is additional argument for managing meshes externally.

This morning I realised every time React reloads canvas-part of the page, I have to reload all the objects and textures. That’s a bit awkward. I am looking at Asset Manager docs but it seems that it is coupled with a scene. Perhaps I am missing something but it doesn’t feel right.

Is there a way to force Asset Manager to store loaded textures and models after scene is disposed and re-use them it in another scene (or even canvas)? What comes to mind is “asset canvas” responsible solely for loading files. Are there any recommendations for dealing with above?

FYI.
It begs separate question about sharing assets between different scenes. Let me know if you should take it out of this thread please.

As always any comments are welcome.

I think AssetContainer is what you need: you can change the scene it operates on through the scene property.

1 Like

I have given up asset container for multiple scenes. It really does my head in. :confounded: Tried to put together in playground but every time I switch the scene using scene setter playground hangs.

I have found old thread in html5gamedev forum talking about serialising objects from one scene and loading them onto the other, but that’s seems an overkill.

Will try to revisit it tomorrow again.
Perhaps we could explanation with a playground example of how to do it in documentation.

Any more tips to get me ready for round 2 would be appreciated. :tired_face:

Sorry, I’m not the best one for that, I have never used asset containers / managers!

No worries @Evgeni_Popov . Thanks for help earlier!
Will post solution here once I figured out how to deal with it.
But it also deserves an update (rewrite). Will report it in feature request section. :smiley:

Here is the basic example of switching between multiple scenes with the help of Asset Container - https://playground.babylonjs.com/#JA1ND3#48 (use “z” to switch between scenes)
Version with no VR and camera control attached - https://playground.babylonjs.com/#JA1ND3#322

4 Likes

Ohhhhh… I get it. So instead of multiple scenes, and moving assets between scenes I can just have single scene with multiple asset containers showing / hiding objects.

Interesting… :thinking: I guess it does make sense.
I could probably do with single camera too, switching mode to orthographic only when needed.

Thanks a lot @labris.

I just read through this thread and wow, there I am again trying to transfer assets from one scene to another, then realizing that the better problem to solve is keeping one scene, but instead loading in different containers.

Now I don’t know if that’s objectively better and babylon js gets more performance from supporting this way instead of the other (being able to move assets inter-scene), but I what I do know is that’s what the framework supports.

Then with this react reloading problem, I too experienced just this. What I did was google how to get react-app dev server to stop with the hot-reloads. I arrived on using this npm command in my package.json :
"start": "react-scripts start FAST_REFRESH=false",

It seems to work on mac dev environments, but not always for windows. What you can do though while testing things in the browser in between making changes in your source files is try to make edits that can at least compile, if you do that than it seems that even windows will still keep your page loaded without losing rendering context.

1 Like