LOD as billboard multiplies root scale with billboarded LOD object

I’m not a coder on this project, but an environment artist. With our current setup, I have no issues using ordinary non-billboard LODS that are scaled independently of the root. That is to say, if LOD0 (root) is scaled by 3.0, and so are LOD1, LOD2, LOD3, etc. Everything is fine. They all follow the root scale. HOWEVER, if I set one of those to billboard, suddenly the billboard object will be 3 times as large as all the others when LOD is enabled, despite them all being set to the same scale. Sure, I can set the billboarded LOD to 1.0 and it will work, but when you are making hundreds to instances, etc in blender, trying to come back and clean that up later can be an undertaking and appear incorrectly in blender. I would usually expect the billboarding to behave identically to the non-billboards as far as scale goes. The coder and I spent a long time trying to figure out why this is but they are not treating billboarding any differently, so we are thinking perhaps it’s a babylon bug. Thoughts? I linked to the LOD portion of our repo. Perhaps there is some insight. Inspector says we are on v6.4.1

link to repo

Are you able to setup a small repro in the Playground?

It’s probably a bug, but we would need a simple repro to be sure!

1 Like

I’ll see if I can get them do that and report back shortly.

I’m attempting to create a repro here but cannot get the model to even show, any ideas? Babylon.js Playground

You can use scene.createDefaultCamera to automatically create a camera that will encompass the whole scene:

Thanks! I got the repro working, you can comment out billboard to see the original size, but you’ll notice how billboarding LOD3 causes the scaling issue to happen. https://playground.babylonjs.com/#B4H112#2

Thanks for the repro.

When billboard is enabled for a LOD, the effective parent is calculated as being the master mesh of the LOD (that is, the mesh on which you set the LODs), meaning that when the world matrix of the LOD is computed and the parent matrix is multiplied with the mesh matrix, you end up with combining the master mesh matrix with the LOD matrix. In your case, because they both have a scale of 3, you get a scale of 9 in the end.

I don’t know why we had to do it like this, cc @Deltakosh in case he remembers (as he actually wrote the code), but I don’t think we will be able to change it anyway. So, in your case, it’s probably easier to keep the scaling on the master mesh and set a scale of 1 on the billboarded LOD mesh.

I wrote it this way as the LOD are not supposed to provide their own matrix. Or at least just an offset from the master mesh. The idea is that user will only move/animate the main mesh and LODs are only for rendering purposes

1 Like

Thanks for the explanation. I’m curious though, why would it handle scaling differently on billboarded LODs than regular non-billboarded LODs?

This doesn’t seem to be demonstrating the issue. Rather I’m not seeing any LOD switching here to compare to.

I think that’s because a billboarded mesh has a special world matrix, so we needed to multiply it with the source mesh world matrix to get the right matrix, something we don’t have to do if the mesh is not a billboard: we can simply use the source mesh matrix.

Thanks.

Correct!

In this case, can there not be a property or something we can set to undo that effect? Seems like an unintended side effect.

The TransformNode.computeWorldMatrix is already a big function and sometimes a bottleneck, so we can’t add new flags if they aren’t absolutely necessary. In your case, you can either overload the function, or add an observer to the observable TransformNode.onAfterWorldMatrixUpdateObservable, which is called at the end of computeWorldMatrix, and calculate another matrix.

1 Like