Coordinate Systems
SAGE uses BabylonJS as its rendering engine, which operates in a left-handed coordinate system. Most 3D content is authored in right-handed tools (Blender, glTF standard). This page explains how SAGE handles the conversion transparently.
How BabylonJS Handles glTF Imports
When BabylonJS imports a .glb or .gltf file into a left-handed scene, it creates a hidden __root__ transform node at the top of the imported hierarchy. This node has scaling = (-1, 1, 1), which mirrors the X axis to convert from right-handed to left-handed coordinates.
You generally don't need to think about __root__. It's an implementation detail of BabylonJS's loader. All nodes in the imported scene become children of __root__, so their local coordinates are in the mirrored (right-handed) space, while their world-space positions are correct left-handed values.
How SAGE Handles Spawn Points
Spawn points are nodes in your scene file tagged with a spawn custom property. They live inside the scene's __root__ hierarchy. When SAGE reads spawn points, it extracts world-space (absolute) position and rotation. Scaling uses the spawn point's own local value since it represents artist intent, not the coordinate conversion.
Entity nodes are created at the scene root — outside __root__. Since they have no parent, local equals world, so the absolute values apply directly. This ensures entities appear exactly where the spawn point is, facing the correct direction.
How Entity Meshes Work
When an entity has a GLB mesh, SAGE imports it and the loader creates its own __root__ node for that import. This is parented under the entity node at the scene root:
scene root
├── __root__ (scene GLB — handedness conversion)
│ ├── level geometry
│ ├── lights
│ └── spawn points
│
├── entity-1 (world-space position from spawn point)
│ └── __root__ (entity GLB — handedness conversion)
│ └── meshes
│
├── entity-2 (primitive — no GLB, no __root__)
│ └── box meshEach GLB import gets exactly one __root__ handedness conversion. Primitive meshes (box, sphere, capsule, cylinder) don't need conversion since they're created natively in BabylonJS's left-handed space.
The rightHanded Option
If your scene file was exported for a right-handed coordinate system, you can set rightHanded: true in your level config:
scene:
path: models/level.glb
rightHanded: trueThis sets scene.useRightHandedSystem = true, which tells BabylonJS to interpret all coordinates as right-handed. When enabled, the glTF loader does not create __root__ — no conversion is needed since both the scene and the format are right-handed.
Troubleshooting
Entity appears at mirrored X position: The spawn point's position is being read in local space instead of world space. This is a SAGE bug — spawn points should always use getAbsolutePosition(). Check that you're using an up-to-date version.
Entity mesh appears mirrored or inside-out: The entity's GLB __root__ may be missing or stripped. Each GLB import needs its own __root__ for correct handedness conversion.
Entity mesh appears correct but at the wrong rotation: Same root cause as the position issue. Rotations under a mirrored parent behave differently — SAGE extracts absoluteRotationQuaternion to handle this correctly.
