In certain specific scenarios, attaching a bounding box gizmo to a mesh causes the mesh’s scale to change. That is, when creating an “editor”-type application, selecting a mesh causes the object to change size every time it’s picked.
The scenario for this to occur is somewhat niche, but not really that uncommon:
Mesh is a child of a parent object that has a non-linear scale (e.g. 1, 2, 1)
Mesh has non-zero rotation (e.g. Math.PI, 0, 0)
Expected behaviour
The bounding box gizmo surrounds the picked mesh and nothing else.
Actual behaviour
The bounding box gizmo correctly surrounds the picked mesh but also changes the scale of it, every time it is picked. Selecting something else does not revert the scale change.
Reproduction
Further notes
I understand non-linear scales are kind of a taboo subject within Babylon. But frankly, there shouldn’t be any reason it can’t work. I’d really like this bug report to not be met with a blanket “non-uniform scaling is not supported” response. I’m looking to at least understand why these technical restraints exist, since other engines don’t seem to have this problem. If there’s some refactoring work that needs to be done, I’m keen to help out. Controlling these properties (scale, rotation, etc.) manually doesn’t seem to cause any issue. It just seems to be the gizmos themselves that have problems.
Initially I thought just as you did, but my research revealed a fundamental mathematical limitation that I think applies to your situation, too.
I don’t think it is generically solvable because Babylon, like other engines, insists on decomposing matrix transformations into Scale, Rotation, and Translation. The fundamental limitation, if I recall correctly, is that a sequence of SRT transforms, as happens in a parent-child relationship, cannot be expressed as a single SRT tranform when the parent S is non-uniform and the child R is not a factor of 90 degrees.
This is from memory, based on what I discovered when I did a deep dive researching the post I linked.
The examples you’ve posted in that other thread don’t seem incorrect to me. It seems like those folks want the child to not inherit the scale of the parent or something? e.g. The child box would remain cubic even though its parent is scaled Y=2, or perhaps they want the scale to apply before the rotation? I don’t really understand what is wrong in the examples they’ve given. The stretching / “shearing” effect is correct in my opinion, you can see it in my playground above.
What isn’t correct is that every time you select the child object it grows bigger. You can continue doing this until it is bigger than the entire viewport. You don’t have to make any rotational / scaling changes, you simply have to attach the bounding box gizmo to it.
As far as any mathematical constraints go, I haven’t personally sat down to work through the maths of it all so it’s possible there are some constraints there. However, there doesn’t seem be any issue in other 3D game engines. I’ve never faced anything like this in Unity, and i’ve just created a scene in Godot seemingly without any issue:
Godot happily lets me scale/rotate both the parent AND the child object. In Babylon, attaching a Rotation gizmo to the child object produces an error, stating that non-uniform scaling is not supported. I’m currently working around this in my editor by attaching the gizmo to a blank Node, and copying the rotation to the selected object using the observable hook - which seems to work fine.
Yes, @HiGreg is right: transformation hierarchy is handled by a matrix (local matrix is transformed by parent matrix). With non uniform scaling (or negative) scaling is present, it’s difficult to extract it from the matrix. It should be possible to do the same in the gizmos if whole transformation hierarchy is evaluated with quaternion/translation/scaling instead of using a matrix.
I’ll take a look asap at size changing each time it’s being picked.
I was thinking about this problem in the abstract and how parenting, if used with the gizmo, would affect transforms. There are a few cases tha might be implemented and I think only one would allow the gizmo to handle non-uniform scaling in ancestors and/or decendants.
Obviously, you have a ton more experience in this code, so if what I write here is not applicable, please ignore.
I think the offending code is the addChild/removeChild on lines 773-776 in boundingBoxGizmo.ts. Within add/remove, there are decompose and compose Matrix functions that probably don’t like scaling in the hierarchy.
I think the only way to handle scaling properly is to set the gizmo as a sibling to the attached mesh (i.e. same parent) and set initial scaling of the gizmo from the attached mesh. Subsequent editing of the gizmo should mirror (copy) the scaling of the gizmo to the attached mesh.
Perhaps the code is already doing that, as I’m having a little difficulty following it. My apologies if this leads you down an incorrect debugging path.
Matrix is skewed and display is not correct.
This is an edge case, even if it’s not that difficult to repro.
Bounding box gizmo only work with orthogonal matrices. I think best is to warn user whern getting that state and at least, not modify the object matrix to not explode its scaling.
If you want to get further when non uniform scaling then it’s your responsability to bake from a sibling transform to another (which makes sense)