I’m loading gltf models which set the root x-scale to -1. I believe that’s to correct the handedness of the model vs the engine. If I parent that root to a new transform node, the matrix propagation ends up clearing out the -1, resulting in inverted mesh textures.
I’m not sure if it’s actually bug, or I’m just using it wrong. Thanks!
This is a Babylon Lite setParent() bug/limitation.
The problem occurs because setParent() tries to preserve the world transform by calculating a new local matrix and decomposing it back into position, rotation, and scale.
However, mat4Decompose() explicitly does not preserve mirrored matrices:
Negative determinant matrices are not specially handled; the returned scale is always non-negative.
It calculates each scale component with Math.hypot(), so -1 becomes 1.
That explains why newRoot = false works and why using setParent() causes the model to become mirrored.
Workaround: When the new parent has an identity transform, establish the relationship directly instead of using setParent()
Set up the relationship before adding the hierarchy to the scene.
When reparenting from an existing parent, also keep the children arrays synchronized:
const previousParent = gltfRoot.parent;
if (previousParent && "children" in previousParent) {
const children = previousParent.children;
const index = children.indexOf(gltfRoot);
if (index !== -1) {
children.splice(index, 1);
}
}
gltfRoot.parent = newRoot;
if (!newRoot.children.includes(gltfRoot)) {
newRoot.children.push(gltfRoot);
}
The engine-side fix should preserve the sign of the matrix determinant during decomposition – either inside mat4Decompose() or through a signed decomposition used specifically by setParent(). Since setParent() promises to preserve the complete world transform, losing the reflection violates that contract.
cc @Deltakosh