← All examples

asset contracts

Axes, handedness and units checker and converter for glTF

Diagnose a glTF that is Z-up, mirrored or in the wrong unit (checked against expected dimensions and triangle winding) and convert it between up axes, handedness, front-face winding and units, transforming nodes, meshes, skins and animations.

What this component contains

  • ATTRIBUTION.md
  • LICENSE
  • README.md
  • asset_report.py
  • axes_units_converter.py
  • component.json
  • fixtures/door.gltf
  • fixtures/door_centimetres.gltf
  • fixtures/door_mirrored.gltf
  • fixtures/door_z_up.gltf
  • gltfio.py
  • pngio.py
  • schema_lite.py
  • test_axes_units_converter.py
  • test_package.py
  • verification/native.json

How it works

Entry points
conversion, convert_document, winding_agreement, check, convert, run, main
Proves
check: the scene box equals the expected dimensions within tolerance, or the report names the axis swap or uniform unit factor that explains it, and at least half of the triangles wind with their stored normals. convert: every node transform, vertex attribute, morph target, inverse bind matrix and animation output is mapped by the same change of basis and unit, so world geometry keeps its shape…
Does not prove
Which way the asset should face (forward is a declaration, not something measured), that cameras and lights still look the right way (their local -Z convention is not corrected), or that quantized data converts (it is refused).
Catches
asset_unreadable, expectation_invalid, up_axis_mismatch, unit_scale_mismatch, dimensions_mismatch, winding_inverted, conversion_unsupported

Recorded checks

blender_and_godot blender 5.2.1 LTS (hash 9e2066aef7ef built 2026-08-25 02:12:34); godot 4.7.2.stable.official.ed1daf0bf

  • checker_matches_contract
  • repaired_fixtures_match_the_door_in_both_engines
  • blender_export_mistakes_are_diagnosed_and_repaired
  • round_trip_matches_in_godot_and_blender

Limits to consider

Conventions are signed axis permutations with a uniform unit factor; arbitrary rotations are not offered. Quantized (integer) positions, normals or animation outputs are refused. Sparse accessors become dense, interleaved data becomes tightly packed, and every buffer is embedded in the output. Cameras and lights keep their node transform change but get no correction rotation. Winding agreement needs stored normals. The diagnosis recognises one axis swap or one uniform unit factor, not combinations.