Shared skeleton between GLB import instances incorrectly culls instances

Process to replicate:

  • Import GLB file which has a skeleton
  • Create an Instance (createInstance) of the non-root mesh some distance next to the original mesh
  • Notice that when you scroll away from the original mesh (causing it to out-of-view), and you look at the new instanced mesh, it actually disappears as well

What I found out:

  • Instanced mesh skeleton === original mesh skeleton

My hypothesis:

  • Sharing the skeleton breaks the culling process such that when the original mesh goes off screen, all instanced meshes are made invisible as well

I wasn’t sure how to upload own assets to the playground but I at least wrote this example which I believe should show the bug if you manage to replace the non-skeleton Boombox with some skeleton GLB.

https://www.babylonjs-playground.com/#WGZLGJ#1741

Sorry if I’m unclear, let me know if you have any questions and I’ll try to answer.

EDIT: I guess the intention of this post is to find out whether there’s something I’m doing wrong, whether this is intended behaviour, or whether this is actually a bug - in which case I can make a GitHub issue for it.

I think (And this is only a thought as we have no clear repro) that you need to update the mesh bounding info OR flag the mesh as always active.

The point with skeleton is that the GPU will move the mesh but the CPU has no idea of that and thus it will clip the mesh based on initial info

So you can try this: instance.alwaysSelectAsActiveMesh = true

1 Like

Omg that worked perfectly, you’re the best. I was trying this to fix this for hours.

Is this something that should perhaps be included as a default setting for instancing gltf with skeleton imports? Or maybe warned about somewhere on this page? Use Instances - Babylon.js Documentation

And am I right in saying that the effect of this option will increase CPU utilisation because the bounding information has to be constantly updated?

we are actually cutting the mesh bounding info check with this line. So it could even be faster ;D

For doc maybe we could improve it (as this is somehow mentioned here: Use Bones and Skeletons - Babylon.js Documentation)

1 Like

After reading the docs, it still wasn’t too clear for me and the actual fix is not directly mentioned. To help save time for people that may have the same issue but not know much about the underlying bounding info mechanics, I made this MR: Update How_to_use_Bones_and_Skeletons.md about instancing issue by shasaur · Pull Request #2021 · BabylonJS/Documentation · GitHub

I’m not sure it’s the right fix (with all due respects to @Deltakosh :wink:) because it simply disables the frustum check for your instance, so it makes it always go to the rendering stage.

What happens is that because your meshes come from a glb/gltf file, they have an effective mesh that is the root of the hierarchy and which is not “themselves” (for a regular mesh, effective mesh == mesh). This effective mesh is, among other things, used for the bounding info computation, so both the master mesh and the instanced mesh end up with the same bounding box (which is the right one for the master mesh but not for the instanced mesh).

What you can do is computing the bounding info of the instance with the matrix of the instance and not with the matrix of the effective mesh as it is by default. To do this:

newMesh.getBoundingInfo().update(newMesh.getWorldMatrix(true));

Note that if your instanced mesh has sub meshes, you must call updateBoundingInfo(worldMatrix) on all sub meshes.

https://playground.babylonjs.com/#2LXD5K#2

Note that the instance (the upper head) has the right bounding box: if you comment line 21, you will see that the bounding box of the instance is wrong, it is at the location of the master mesh. That’s why if you move the camera to have the master mesh out of the screen, the instance mesh will disappear too (the bounding box is used for frustum checking).

To conclude, note that you don’t have this problem with a rigged mesh coming from a .babylon (or .obj) file because their effective mesh = themselves.

1 Like

The cost of updating the bounding info update will be important if the mesh is moving on every frame. Furthermore if the skeleton is moving the bones beyond the initial pose, we cannot just update the bounding info with world matrix but we need to scale it (we do have an expensive API for that as mentioned in the Doc link I shared)

If you do not need picking AND if the instance is moving I still think skipping the culling is probably the more efficient fix:)

If the instance is static @Evgeni_Popov is totally right (I think we should do that anyway after instancing a mesh with skeleton that has an effectivemesh)

1 Like

@Shasaur: I jus chatted with @Evgeni_Popov and we will fix the bounding info calculation at engine level. This will fix your issue

1 Like

That’s awesome! I’m amazed to see how well you guys understand this issue and your responsiveness + eagerness to improve the engine! Thanks so much!

PR on its way:

3 Likes