Skip to content

Up-Axis Mismatch

Severity: ⚠️ Warning
Fixable: ⚠️ Contextual (warn-only in Preflight)
Prevalence: 🔥 High

In RealityKit, Z-up assets can appear upright when loaded directly, but rotated 90 deg when referenced inside a Y-up scene (for example, Reality Composer Pro). Hydra shows literal orientation unless it is compensated. This mismatch is easy to miss in previews.

Root Cause: The Root-Level Orientation Rule

Section titled “Root Cause: The Root-Level Orientation Rule”

RealityKit applies orientation correction only at the root load boundary:

  1. Reads upAxis metadata from the root file being loaded.
  2. If the root file is Z-up, applies a -90 deg X rotation to the entire load.
  3. Does not recurse into referenced sub-assets; it trusts their authored transforms.
Loading ContextRoot AxisCorrection AppliedObserved Result
Direct preview (root is asset)Z-upYesStanding (auto-rotated)
Y-up scene references Z-up assetY-upNoLying down
Z-up scene references Z-up assetZ-upYes (whole scene)Standing
  • RealityKit previews load the asset as the root, so Z-up assets can look correct even when they will not in a Y-up composition.
  • Preflight’s Hydra view applies a Z-up compensation rotation, so it may also appear correct.
  • Result: both previews can look fine while the asset still fails in real production scenes.

Preflight detects Z-up metadata and warns, but does not apply an automatic fix. The decision is intentional:

  • A metadata-only change can make direct previews worse (it disables RealityKit’s auto-rotation).
  • Geometry conversion can fix composition but is destructive and path-sensitive.
  • Preflight cannot infer the target usage (root load vs composed scene), so no single fix is always correct.

See docs/UpAxis_Handling.md for the full analysis and open questions.

Author the geometry as Y-up in the DCC and export with Y-up orientation. This is the most predictable and least risky option.

Set the scene up-axis or rotate the model at the reference point. This keeps the source asset intact but requires consistency across scenes.

Changing only the upAxis token does not rotate geometry. It may help in some pipelines, but can make direct RealityKit loads appear wrong.

A geometry conversion can rotate the scene to Y-up and update metadata, but it may:

  • Re-parent root prims under a new wrapper prim
  • Change defaultPrim
  • Break reference paths or downstream overrides

This is intentionally disabled as an automatic fix in Preflight.

File: PreflightUSDInterop/USDClient+Live.swift
Function: performValidation()

if metadataUpAxis == "Z" {
detectedUpAxis = "Z-up"
results.append(
.warning(
"Up-Axis Mismatch",
details: "Stage metadata is Z-up. RealityKit may auto-rotate when loading the file directly, but composed Y-up scenes will not. Preflight warns only because a safe automatic fix is context-dependent.",
fix: nil
))
}
DateChange
2026-01-20Option B: warn-only, removed automatic fix guidance
2024-12-18Full documentation with evidence and automatic fix
2024-12-18Stub created