Performance implications after disable instances

Hi,

I found out that we can disable instances by settings the createInstances to false on the SceneLoader object.
Can somebody help me with understanding the performance implications due to this?
Because if models are created without instances then the size really increases quiet a bit (of course depending on how many times the mesh repeats). So, I would like to have instances in the model to keep the file size small and disable instances by setting the flag on the SceneLoader in babylon.js, but just wondering if this a good approach or are there performance implications.

Regards,
Nithin

Instances should not impact the size much as the buffer can still be shared without instances.

The main drawback of not using them is that you will have 1 draw call per “clone” whereas with instances you have 1 draw call for all the “instances” so if we speak 1-10 elements, all good but if you are in the 10-100 instances would be a must.

Hi @sebavan,

Thank you for the reply.

So, it’s better to disable instances from a performance perspective, right?

Regards,
Nithin

So nope, it’s better to keep instances enabled cause 1 draw call total is faster than 1 draw call per element.

Ah ok…i understand.

My main problem is when one instance is clicked with a mouse i want to hightlight that mesh but it ends up highlighting all the instances. Is there a way then to highlight only the selected mesh when instances are enabled?

This is a tricky one. Usually in this case, I would keep 1 alone and the rest as instances. On click the instance would be disabled and the alone one would be positionned like the instance so that the effect is totally similar. the disable the alone and reenable the instance when you do not need the highlight anymore.

1 Like

Initially I thought we could calculate the bounding box of each instance and write logic to isolate by left, right, top, down and depth co-ordinates.

but that sounds deranged keeping just 1 clone as a highlight helper is way better lol

on that note, but here’s a semi-example just based on depth for funsies.

1 Like

@sebavan thanks for the solution direction and I think I understand it but not sure how to implement in my situation as I do not create the meshes in babylonjs. Let me explain.

I get a model (glb) with lot of meshes and there are several groups of instances e.g. bunch of fans, bunch of lamps and other items. Lets say there are 5 fans, I want each of them to be individually selectable and also want to highlight the selected one. What happens now is when I click on the first fan then all of them are highlighted but when I click the rest of the fans nothing is selected and I get this error in the console:

highlightLayer.ts:718 Uncaught TypeError: Cannot read properties of undefined (reading ‘add’)
at t.addMesh (highlightLayer.ts:718:64)
at highlightMesh (app.js:511:24)
at HTMLCanvasElement. (app.js:486:13)

Probably because it is an instance. So, it looks like in the model, fans 2,3,4 & 5 are instances and 1 not and its the same story with other items as well.

Since I do not have control over the model, I am not sure how to implement the solution you suggest. Could you please guide me further?

I don’t know if I understood correctly. But I think it’s because you use :
scene.freezeActiveMeshes();

If you remove freezeActiveMesh, it works as I think you want.

1 Like

I know, the implementation is incomplete, we need to restrict by left, right up and down too.

I did freezeActiveMeshes to make them act like instances, i.e. be drawn in 1 draw call.

if I don’t do that they all take separate draw calls : )

Since in my case I am not creating the meshes or making instances, I am still wondering how I should pursue @sebavan solution direction.

I was expecting something like a flag that can be set on the mesh to temporarily not make it behave like an instance and switch it back. My apologies if it does not make any sense from an design standpoint.

Does this work for you?

//pseudo code
const masterMesh = scene.getMesh();
const highlightMesh = masterMesh.clone("m2"); //or use master mesh if possible
const children = [masterMesh.createInstance("c1"), ... ];
let activeChild = null;

(...)

onClick(child) {
 if(activeChild) {
   activeChild.setEnabled(true);
 }
 highlightMesh.position.copyFrom(child.position);
 highlightMesh.rotation.copyFrom(child.rotation);
 child.setEnabled(false);
 activeChild = child;
}
2 Likes

@Joe_Kerr something like this is also what I was thinking but the problem I have is I do not know where in the mesh hierarchy is the master mesh for the instance that was clicked (because I do not create any mesh or mesh instances in babylonjs, its all in the glb file i receive).

Is there a way to get to the master mesh for a instance?

Sorry if I am not being clear :frowning:

I am not sure I understand. If an instance was clicked, then you can access the original or source mesh like this. But at this point you do not need that, do you?

You also refer to glb and mesh hierarchy. So do you mean when you import the glb and you have a file structure like

__root__
  someNode
    someMesh
  ...a million other nodes

you want to get the actual mesh to be cloned/instantiated from within that hierarchy? If yes, the way I do it is to just iterate the hierarchy and compare the mesh.name. I have standardised names set up in Blender like “$VisionNode” or “$BodyCollider”.
Or if you know there is just a single mesh, you can also root.getChildMeshes()[0]

Otherwise, can you make some basic playground showcasing yuor problem?

1 Like

@Joe_Kerr, yes exactly, a hierarchy with million other nodes and the nodes already have both original mesh and the instances. So, I am not creating any mesh or instance in babylonjs, just loading the glb file.

I also tried the option to not have instances in glb during the creation but then the size of the file increases quite a lot.

I have tried loader.createInstance = flase; after loading the model, that works also but i have concerns on performance.

Like you suggest, I could iterate the hierarchy, compare mesh name and manage to get to the original mesh, but feels like a complicated way to just highlight a mesh on click. I will give it a try though.

Meanwhile, if there is any other way that i coud try, that is simpler please do let me know.