Expand description
HMA1: per-bone local quaternion animation tracks (the HMD8 pose-palette
replacement cooked by psx-anim-cook).
Each clip stores, per bone, a rotation track and a translation code:
- rotation: one key, or keys every 1/2/3/4/6/8/16 source frames (the clip header maps the playback position to each rate with one multiply, so a bone’s key lookup is an index, not a search);
- 8-bit keys are range-reduced (i8 base + 4/6/8-bit offsets per component), 12-bit keys are packed; the cooker picks per bone;
- translation: the bind value, one per-clip value, or range-reduced Q2 keys (quarter cooked units, so hierarchy rounding stays small).
Model::decode evaluates every bone parents-first into model-space
affines. Composition runs on the GTE (MVMVA sf=0, rounded on the CPU) so
it matches the host reference decoder bit for bit; on other targets the
same arithmetic runs in Rust.
Layout (little endian): u16 n_bones, u16 n_clips, u8 parent[n] (0xff root), pad to 2, i16 bind_t[n][3] (Q2), pad to 4, u32 clip_off[clip_count]; clip: u16 n_int, u8 flags, u8 qfmt(=3), u16 seg[7], u16 factor_q15[7], u8 mode[n], pad to 2, then byte-packed tracks.
Structs§
- Affine
- Jaw
- A local rotation folded into one bone before its children compose: the
GoldSrc mouth controller, which adds to one Euler angle of the jaw bone.
For a Z-rotation controller that is
delta * local(post == false); for an X-rotation controller it islocal * delta(post == true). - Model
- A validated HMA1 blob.
Constants§
Functions§
- quat_
mul - Q12 quaternion product a * b.