How to instantiateModelsToScene() for each mesh/geometry in a single .glb file that has multiple objects

Hello fellow seekers!

I was wondering how to manage different shapes (each with their own transformation, material, etc.)
image

from a single Blender (.glb) file with Babylon’s instantiateModelsToScene()

The idea is to import one .glb file containing all the needed shapes, use (and reuse/copy) the ones that are needed. But I can’t seem to get it to work. I am not sure if this is even possible?
I don’t like the idea of having to create a separate .glb file for each shape.

This is the output of the .glb import using: LoadAssetContainerAsync()

Note that there are 7 geometries, and that is correct (first screenshot). But there are 8 meshes, why is that?

Alternatively I’ve played with another import method: ImportMeshAsync() (see below log) and I tried to copy the objects when I needed them with .clone(), but that also failed.

I am not sure which import method to use, probably depends on performance, but I will decide at a later stage. What’s the proper way to manage multiple shapes from a single asset file? Ideally in both methods?

Hi!

This happens because when a GLTF mesh is imported to Babylon, a special __root__ node is added, which contains a transformation to convert between GLTF’s native right handed coordinate system to Babylon’s left handed one. You can check that node if you open the Inspector.

@PatrickRyan will be the best person to answer about managing assets :slight_smile:

@kagedaf232, what @carolhmj mentioned about the __root__ node is why you are seeing 8 meshes. As you can see here, the __root__ node that is added to all glTF imports is of class mesh and will count as such in an asset container.

image

You can certainly use one glTF file to import multiple assets, but there are a few things to keep in mind.

  • As @carolhmj mentioned, __root__ node is there to hold the negative scale needed to flip the handedness of the mesh. The glTF format is right-handed, while by default the Babylon scene is left-handed. You can see in the image above that the correction here is to scale the asset on the Z axis by -1. This will mimic reversing the winding order on the meshes. If you want to remove the meshes from __root__ you will either need to reintroduce the handedness conversion or set your scene to right-handed.
  • When using an asset container, it is important to remember that the whole hierarchy needs to be added to the asset container to retain the parent/child relationships. Adding only a part of a hierarchy will at some point break the parent structure through adding and removing the asset. When importing directly to an asset container, this is done automatically. When doing it manually, you can either manually add the entire hierarchy or you can use the new method addAllAssetsToContainer that @carolhmj did for us once it is merged.
  • If you are using these meshes as base imports to sprinkle around your scene, you will likely need to use instances to keep the number of draw calls manageable. You will want all of the instances to share a material, again to manage draw calls, but remember you have custom buffers to pass information to specific instances. You can use the custom buffers to add variation to your instances as you can see in this Medium article.

Typically when I manage a bunch of assets for a scene, even if importing them from one glTF, I want to either rename the __root__ node or get rid of it all together so the inspector isn’t filled with nodes of the same name. Especially if I have several meshes under one parent. I normally want to break them out of the parent, but you don’t have to do that. You can leave them as a child of the parent mesh and just add them directly to the scene with addToScene. Simply target the specific mesh by name with something like:

container.addToScene(m => m.name === "meshName")

Remember that if you have a left-handed scene and are pulling a mesh without the __root__ node from the asset container, you need to apply a scale to ensure the winding order of the mesh is correct. And you will likely also need to rotate the mesh to get it back to the correct orientation after the negative scale. Or you can choose to set your scene to right-handed to avoid some of these concerns.

I hope this helps, but please feel free to ping back with more questions.

1 Like

Hello @PatrickRyan,

Thank you so much for the tips, I will definitely keep those into consideration.
However, I read and re-read the post but I am not sure it’s addressing my particular problem.

Let me try showcase what I am dealing with.

I have one .glb file containing several different meshes (3D models built in Blender).
In the below screenshot only one is visible, but I have 10 such tokens (all the same size, and all centered at the origin)

I am trying to load them as one file:

BABYLON.SceneLoader.LoadAssetContainerAsync(`./models/`, "number_tokens.glb", this.scene)

but I need to have individual control over each single token, and I need to be able to reprint whichever I need when I need it. For example:

var randomList = [2,3,4,2,2,6,7,8,10];

randomList.map((element) => {
        // Print the according token number.
        tokens[element];
})

I do not think this can be done through instancing… from my understanding instancing is limited to colors, and textures at max. But before talking about rendering optimization I would like to know if there is an organized way to manage similar assets.

I am going to have a lot of models that are similar, yet different enough to not be “instanceable”. And certainly far too many to be able to load them separately.

Something like:

x11 hexagon models (hexes.glb)
x10 number token models (number_tokens.glb)
x32 player pieces models (player_pieces.glb)
x10 world pieces models (world_pieces.glb)

So it would be great if I could have them organized like this:
image

Note that I duplicated the NumberToken 3 on purpose.
There may be times in which I need to duplicate some nodes (maybe here I can use instance for that particular shape), or some times in which I don’t need some of the meshes at all.

I’m fine with stuff being loaded under a parent node “root”, as long as I can make it make sense :slight_smile:
Also, yes my system is right-handed.

Thank you!

@kagedaf232, give me a little time to put together an example. I have some time in my schedule tomorrow to work on it.

@kagedaf232, here is a very simple example of loading one glTF with multiple meshes in it to an asset container and then pulling them out to be used as needed. There are two examples here, one where the asset is pulled directly from the container and another where a mesh in the container is instanced into the scene. You can see that you have full control over position and parent structures of both examples. Hope this helps give you some ideas but feel free to ping back with questions.

2 Likes

Thank you @PatrickRyan, I’m definitely getting close to my goal.

Now the further complication is that each imported object in the .glb file is actually created by many meshes.

image

In your example you have multiplied the Icosahedron at wish, which is exactly what I need to do with Ore, except ore is a combination of underlying Meshes. But it looks like I cannot do that:


I admit that I am both new to Babylon and Blender modeling. I may miss some basic knowledge on how to handle models created by many meshes in Blender, export them, and handle them in an organized way on Babylon.

My assumption was that I can create any however complicated model in Blender, export it as a packaged object and handle it as I wish for my application.

So for example if I have an Object A built by meshes 1,2,3,4
A = {1,2,3,4}
I thought I could handle everything in Babylon (instancing, displaying, hiding, etc.) by just playing with A.

And if I had a .glb fle containing
A = {1,2,3,4}
B = {1,4,5,6}
C = {1,2,4,6,7}
I could still take that into Babylon and handle A,B,C separately without worrying about having to go deep into the parts that construct them.

So perhaps, I have to do a step back and ask how to export multi-mesh objects in a single .glb file


so they can all be handled in Babylon one at a time as unified object without

I explored the possibility of joining the meshes into one directly in Blender, but that seems to get complicated with models with many many meshes…

Let me know,
maybe I’m not even asking the right questions :slight_smile:

@kagedaf232, when designing your assets for real time rendering, you definitely want to combine meshes as much as possible because every mesh equals another draw call in real-time rendering. This can have a large impact on performance if you have a scene with a lot of meshes in it. The place where you would normally want to split meshes, however, is where you need material breaks.

For example, if you have on part of an asset that needs transparency (say leaves on a tree) and another that does not (say the trunk and branches of the tree) you would want this asset to be made of two meshes. One for all the leaves and one for all the branches and trunk. This is because you need a material that supports alpha blending for the leaves, which is more expensive to render, but you don’t want to incur that extra cost (or the problem of sorting the mesh) with the trunk and branches. In this case, two meshes and two materials is reasonable for this asset.

What you are describing, however, is a set of base meshes that can be combined in different ways to make three different assets. There are two ways to approach this problem depending on what you need.

  1. You combine the meshes for each asset A, B, and C in Blender so that asset A is one mesh (assuming you don’t need to split materials), asset B is one mesh, and asset C is one mesh. Then you don’t need to worry about the individual parts of the mesh and reduce your draw calls. The down side here is that if asset A, B, and C have common base meshes, you are literally storing multiple copies of the base mesh in one file, making the file larger and incurring more cost in download and in memory.

  2. You just save the submeshes 1-7 in the glTF file and don’t worry about combining them into a single asset. You then instantiate from your asset container the parts that you need for each asset as you create them. You would make an abstract mesh for a parent that is named A, then you instantiate base mesh 1, 2, 3, and 4 from your container and make them all children of A. Same with B, but you instantiate 1, 4, 5, and 6 instead. You can then use the parent to move them around as needed.

However, it sounds like you may be trying to create your three assets in Blender by instancing the shared base meshes and then trying to use each asset as it’s own thing in the container. I have no idea if this would work because of the nested instances coming from Blender.

You mentioned that joining the meshes in blender was complicated due to the number of meshes, but I will counter that Blender is the exact place to do that. Ask yourself why you are keeping the meshes separate? It looks like your meshes are flat colored and do not use transparency from your screen capture. Are you UVing your meshes into an atlas so that you can pass the correct color in texture or are you using a different material with color factors for each base mesh to get the color you want? If you are doing the second, that is more of a pre-render workflow not a real-time workflow. You want to minimize the number of meshes and materials you use in real time as much as possible.

1 Like

Thanks @PatrickRyan,
that makes sense.

In your playground, at line 31 you create a meshes object
image
In which it seems like you extract the contents of the asset manager to keep them organized?

1) But there is not really a need for that, since you can extract and instantiate them directly?


In my asset container, I realize that sometimes my Blender meshes are stored as Meshes and sometimes as TransformNodes (I suspect there may be more ways to have assets stored in the container)
image

image
From my understanding this depends on how the model is built in Blender?

2) Should I have a standard way to have models organized in the container?


3) If not, and that just depends on how the model is built, how do I target the model that I need without knowing if it’s stored as Mesh or as TransformNodes (or as else)
Currently I load them like this, but I feel this is not right, especially if the way models are loaded in the container is prone to change:


4) If I have to target them all by name (as you have done in your PG), do I have to work on a certain naming convention in Blender?
Or are there any restrictions/nuances?


5) How do I create a Mesh at runtime, but do not render it until I make an instance of it?
I tried several things, including creating it and then disposing of it in the end - with the result that it also deletes its instances:


Eventually I came up with disabling it, but I don’t like that it still appears in the debug tools, this creates confusion and means that the original mesh actually exists:
image


6) If I create an AbstractMesh like you suggested, how do I add children (subMeshes) to it?


Is the above right, or is there a dedicated method to create subMeshes?


 

Sorry for the many questions,
I spent a lot of time on doc pages, videos, and stackOverflow… but I find I learn much better this way.

Shortly - yes, if you want to find your mesh by name, you have to work on a certain naming convention.
Regarding nuances - it should be comfortable and understandable for you and your designer team (if any).

setEnabled(false) is correct method here. I don’t see any confusion here, because if the original mesh doesn’t actually exist you will not have neither this mesh nor its instances at all. Inspector shows that you have this mesh and shows that it is not enabled (and is not rendered).
If you have several “instances prototype” meshes like this you may collect them under one Transform node, just for orderliness.
Another way to avoid confusion is to close Inspector (I am joking, of course :)).

@kagedaf232, I will say that I have a general template that I use for examples and demos to save on writing the same boilerplate over and over. Especially when responding on the forum, I want to save as much time as possible, so I just grab the template to make a sample to share. This is why there is a meshes object in the code and why I use it. It’s just familiarity with the template that can get me to a working solution as fast as possible. You will certainly find things in my code that are not optimal as I am a tech artist, not an engineer. I work with amazing engineers, but I do not have their level of expertise in writing optimized code. I do, however, come from a game art and design background so being able to talk about and demonstrate methods of creating and managing assets is my strong suit. To answer your questions directly:

  1. Yes, the way your asset is stored in engine comes directly from the digital content creation (DCC) tool and how the asset was created. Elements that are a transform only (like an Empty in Blender) in the DCC are loaded and stored as transforms in engine and will be held in the asset container as such. Mesh elements (those with a triangle list) are stored as meshes. How you organize your file in a DCC tool will determine how the asset appears in the engine.

  2. With any asset pipeline, you will need to strategize about what your scene needs now and in the future. The reason is that your asset pipeline may need to evolve with the needs of your scene. Also, coming up with an organization structure in the scene itself will help you understand your code when you come back to it six months later as well as help anyone else coming behind you to understand the code. This could be applied to the asset container where you organize assets under a common parent and add all to the container, or it could be just added meshes in isolation from one another if your scene does a lot of assembly at runtime. You could also manage multiple asset containers if you like. It really depends on how your mental model for your scene works and what organization can help you understand your assets and code.

  3. The way your assets are loaded into an asset container should never “change.” It sounds like you are saying that your assets have components that sometimes appear as a mesh and other times appear as a mesh. This should be impossible as a mesh component will always have a triangle list and a transform will not. This is all driven by your DCC tool, however, so it is possible to create a similar hierarchy and naming structure that has transforms in one case and meshes in another, so changes like this could happen if the asset changes. However, it may be that you are saying that in your file you have a complex hierarchy and you are getting a mix of transforms and meshes. This would point to the structure having empties or other transforms being used for organization or animation so you end up with a mix of transforms and meshes in the same asset. This would be normal. This is also a reason to do something like instantiate by name rather than by type. However, if you have a very consistent hierarchy in your assets and know which if your elements are transforms and which are meshes, you can instantiate by type like this. Instantiating by type could also be a check against your art pipeline to ensure your assets are created the same way since if the asset loads with the elements created as the wrong type, you could easily see the formatting error of the asset.

  4. Totally agree with @labris on this one.

  5. Again, agree with @labris here. Though if you are concerned about having a lot of extra nodes in your scene explorer, you have a couple of options. A simple one would be to create an AbstractMesh that you set as the parent of all of your assets that are not enabled but waiting for instantiate. This would clean up the scene explorer as you will only see the abstract mesh and not all of the other assets unless you unfurl the hierarchy. The other way would be to use an asset container. If your asset is in the asset container, it will not be in the scene explorer. In that way you can instantiate from the asset container, or you could add a particular asset to the scene to to something with it (clone for example) and then return the original asset back to the asset container in the same frame. This would keep only enabled meshes in your scene explorer.

  6. To add meshes to an AbstractMesh you can simply set the parent of the mesh to the abstract mesh like myMesh.parent = myAbstractMesh or by adding the mesh as a child using myAbstractMesh.addChild(myMesh). The code in your example would add a submeshes array to your AbstractMesh object, but the engine does not know what to do with that array. Using the parent accessor which will be inherited from the Node class will tell the engine that whatever transform is applied to the parent will also affect the child. Using a parent hierarchy also gives you access to methods like getChildren, getChildMeshes, and getChildTransformNodes to help manage the hierarchy.

I hope this helps to clear things up. Thanks @labris for the assist here! Ping back if you have more questions or concerns.

1 Like