glTF models appear mirrored after switching our app from RHS → LHS (seeking root cause + best-practice fix)

Context

  • We’ve run our app in a right-handed scene for years.

  • We’re migrating to left-handed (Babylon’s native) for long-term stability (a past update flipped the Z axis when we were RHS and broke our input system). I am very aware that I can just flip controls around and make this work but that’s not what we want as keeps our code with these constant flips and patches.

  • Our app assembles GLTF/GLB product models at runtime and also creates plane meshes for 2D textures (labels, cards, etc.).

Symptoms

After switching to LHS, some assets render mirrored:

  • Text on models reads backwards; some 3D models look mirrored.
  • We later discovered even the ones that looked okay just happened to be symmetric models that looked similar even when flipped.

What I tested (hacks I don’t want to ship):

  1. material.sideOrientation = BABYLON.Mesh.BACKSIDE

    • Appears to fix visibility, but lighting/shading is wrong when rotating → normals/tangents not corrected.
  2. mesh.scaling.z *= -1 (also tried other axes)

    • Visually correct and lighting looks better, but this is a per-mesh runtime inversion that can fight parent transforms/skins and feels brittle. I am very uncomfortable adding this to production code even if it looks like it works.
  3. Flipping normals in DCC (e.g., Blender) [didn’t really test this but makes sense]

    • Addresses individual models, but is not practical for a large library and mixed pipelines.
  4. Swapping SceneLoader usage from BABYLON.SceneLoader.ImportMesh to BABYLON.ImportMesh

    • No change;

Observations about Sandbox vs our app

  1. In the Babylon Sandbox, the same models look correct.
  2. Reading Sandbox code, it looks like after a load the Sandbox replaces its scene with the scene produced by the loader (and for glTF that means a right-handed scene). It then rotates the camera by π for glTF/OBJ so you see the model “front.”
  3. Our app, however, keeps its own LHS scene and appends imported content into it (and we also merge meshes for performance).

For an app that wants to run LHS (default system) globally but loads glTF (RHS by spec), what’s the recommended, stable approach?

cc @bghgary

You should be able to use glTF (RHS) assets out-of-the-box in a a LHS Babylon scene, but it sounds like this isn’t working correctly in your case, which we’d love the chance to fix. Could you share a repro of the issue in a PG so we can diagnose? :slight_smile:

Also, just to confirm here:

a past update flipped the Z axis when we were RHS and broke our input system

Are you referring to this breaking change?

yes and thanks @alexchuber that’s the breaking change that got us thinking about changing the coordinate system but the reasons were far beyond just that one twist, let me work on a simple repo to replicate this.

2 Likes

This should not be the case. The sandbox does load a new scene for the glTF, but it should be in left-handed system (which is the default). We can check by typing this statement in the browser debug console:

BABYLON.Engine.LastCreatedScene.useRightHandedSystem

Which should return false.

This will be useful. We will need this to investigate further.