Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

glTF and generic runtime profile

Use this page when glTF/GLB is consumed by a custom runtime or when no frozen engine tuple matches the actual consumer. This is intentionally not a sixth V1 engine profile. Leave [engine] absent and use AnimSmith's engine-neutral measurements, checks, transforms, and evidence.

What the format guarantees

The glTF 2.0 specification defines a right-handed, Y-up coordinate system and metres for linear distances. Animation sampler input is time in seconds and must be finite, non-negative, and strictly increasing; channels target node translation, rotation, scale, or morph weights. Names are optional and not guaranteed unique. The runtime still chooses scene selection, asset addressability, graph/controller behavior, root-motion extraction, blending, events, masks, physics, and error handling.

AnimSmith checks and thresholds

No engine-specific check applies without a profile. The engine-neutral catalog still provides exact source contracts:

Check idExact default boundaryGeneric-runtime use
time-monotonicstrict increase; negative tolerance 0.0001 s; late-first-key note after 0.017 sEnforces the glTF timing requirement and identifies an unauthored clamp-held prefix.
quat-normabsolute length deviation greater than 0.001Prevents unstable runtime interpolation.
scale-keyscomponent range greater than 1e-4Makes animated scale explicit.
non-uniform-scalerelative spread greater than 1e-4Flags a transform/skin/physics portability risk.
rest-world-scaleselected node factor 1.0 ± 0.0001 inclusiveChecks project-declared attachment/IK nodes without guessing units from bounds.
loop-closure0.01 m and 1.0°Checks a declared cyclic endpoint.
loop-seam-vel / loop-seam-rot0.1 m/s / 5.0°/sFinds wrap velocity discontinuity.
in-placeXZ speed at least 0.5 m/s counts as travellingEnforces declared movement ownership.

Use the complete check catalog for structural rig, duration, FPS, gait, sync, foot-slide, and bind-pose contracts. Do not select engine-addressability; it is defined only for the exact Bevy tuple.

The scale-domain measurements are the engine-neutral output of #267, and the selected-node policy is #268. The profile-specific advice work in #155 does not invent a generic importer. Static placement baking #224 and skinned rest/bind reparameterization #269 remain distinct repair contracts.

Configure the runtime contract

Declare only what the project actually knows:

[rig]
profile = "humanoid"

[runtime_nodes]
selectors = ["weapon_socket", "ik_*_target"]

[checks.rest-world-scale]
expected_uniform_scale = 1.0
uniform_scale_tolerance = 0.0001

[clips."locomotion_*"]
loop = true
movement_owner_xz = "gameplay"
speed_mps = { value = 3.0, tolerance = 0.2 }

There is no fallback or nearest engine profile. Adding a made-up [engine] tuple is an operator error, not a way to label a custom runtime.

Common failures and fixes

SymptomEvidence to inspectCorrect owner
Asset is the wrong physical sizeglTF metre contract, source exporter, rest-world-scaleCorrect all lengths in DCC/whole-document conversion, or repair one compensating hierarchy scale.
Animation name lookup is ambiguoussource animation indices and optional namesDefine a runtime-owned unique id policy; glTF names are not identities.
Attachment, IK, or collision anchor driftssource node path, ancestry, affine classRepair transforms or canonicalize supported rest/bind scale, then test runtime composition.
Loop or movement slidesloop checks, in-place, root-motion-speed, foot-slideAlign source motion, declared intent, and controller behavior.
Valid glTF still fails to loaddependency closure, required extensions, runtime logsFix resource packaging/extension support in the exporter or runtime.

Scale and unit workflow

If an exporter wrote centimetre-valued numbers into a format that defines metres, the whole asset is physically wrong: a factor 0.01 whole-document conversion is the relevant operation when the supported-source boundary is met. If the mesh is already the correct world size but a skeleton root carries 0.01 with compensating descendants, whole-document conversion is wrong; use the explicit rest/bind operation instead. That inherited scale also multiplies descendant socket, attachment, IK, and collision-anchor offsets, animation translations, and root-motion distance.

Static transform baking moves supported unskinned placement into geometry. It does not repair a skinned hierarchy. Rest/bind reparameterization covers the accepted skinned design and preserves its stated world-space invariants. The runtime still owns sockets, attachments, IK, collision anchors, root motion, graph behavior, extensions, rendering, physics, and visual acceptance. See Scaling safely and the static asset workflow.