code wiki / (root) / nx_nxa_posewrite_lib.nx

nx_nxa_posewrite_lib.nx

buildroot/runtime/nx_nxa_posewrite_lib.nx

7463 B170 linesdepth 2pulls 3 transitivereach 34 importersview sourcekind librarytopic nxa
docsdependenciesstructsconstsfunctions

about

nx_nxa_posewrite_lib.nx -- THE ONE POSE-SECTION WRITER for the NXA format (spec: knowledge/nxa_format_spec.md POSE). WHY (measured 2026-09-05, /compare/modding MD3): the estate had exactly ONE writer of a POSE section -- inline inside nx_nxa_pose freeze, an organ that is SOURCE-ONLY -- and nx_nxa_retarget, which computes a complete pose (a world-delta quat and a dt per target joint, the exact POSE entry shape), published it by BAKING the posed VERT in place instead. The baked donor is a statue with a different shape: nx_nxa_play reads poses_in_library=0 joints_posed=0 on every retargeted output while the house rig reads 104/104, so nothing downstream can replay, hold, or sequence the pose. A writer that lives in one organ and is re-typed in the next is the duplicate-ruler defect; this lib is that writer, composed by both (nx_nxa_retarget emit=pose today; nx_nxa_pose freeze is the migration owed). Layout written (nx_nxa.nx + the nx_nxa_pose incumbent): header 4 words [magic, NXA_VER, nsections, toc_check]; TOC 4 words per section [tag, byte_offset, word_len, payload_check]; payloads follow in TOC order. POSE payload: [count, then per pose: pose_id, nentries, entries of NPW_WPE=8 words (joint, qx, qy, qz, qw q12, dtx, dty, dtz MODEL units)]. Every existing section EXCEPT an old POSE is copied unchanged; the new POSE payload keeps every old pose whose id differs from the one written (so re-emitting an id REPLACES, never DUPLICATES) and appends the new one LAST. q and dt are indexed by JOINT id (q[joint*4], dt[joint*3]) and jl lists the joints to emit, so a dense per-joint table (the retarget) and a tracked subset (the freeze) share one signature. license_tier: ORIGINAL No hw writes (Rule 26).

dependencies 2 imports · 8 importers

nx_syscalls.nx nx_nxa.nx nx_nxa_posewrite_lib.nx nx_gate_rig_motion_20260909.nx nx_gate_rig_motion_context_t140.nx nx_gate_rig_motion_palette_t140.nx nx_gate_rig_motion_stream_t140.nx nx_nxa_bind.nx nx_nxa_bind_t29.nx nx_nxa_pose.nx nx_nxa_retarget.nx

imports: nx_syscalls.nxnx_nxa.nx

imported by: nx_gate_rig_motion_20260909.nxnx_gate_rig_motion_context_t140.nxnx_gate_rig_motion_palette_t140.nxnx_gate_rig_motion_stream_t140.nxnx_nxa_bind.nxnx_nxa_bind_t29.nxnx_nxa_pose.nxnx_nxa_retarget.nx

structs

none

consts

20const NPW_WPE: i64 = 8 // words per POSE entry (spec)
21const NPW_HDR_BYTES: i64 = 32 // 4 header words
22const NPW_TOC_BYTES: i64 = 32 // 4 TOC words per section
23const NPW_TOC_W: i64 = 4
24const NPW_TOC_MAX: i64 = 64 // nxa_find refuses ns > 64, so a writer must refuse before making such a file
25const NPW_MODE: i64 = 420 // 0644, every sibling NXA writer
26const NPW_ERR_NOTNXA: i64 = 0 - 1
27const NPW_ERR_TOCFULL: i64 = 0 - 2
28const NPW_ERR_OPEN: i64 = 0 - 3
29const NPW_ERR_SHORT: i64 = 0 - 4
30const NPW_ERR_PAYLOAD: i64 = 0 - 5 // built payload did not fill its predicted length: a partition that did not sum
31const NPW_ST_SECTIONS: i64 = 0 // st[] slots the writer fills for the caller's receipt
32const NPW_ST_KEPT: i64 = 1
33const NPW_ST_PLEN: i64 = 2
34const NPW_ST_N: i64 = 3
35const NPW_ST_W: i64 = 4

functions

38func npw_payload_words(b: *u8, flen: i64, pid: i64, n: i64, st: *i64) -> i64
called by 1: npw_write calls 2: nxa_findnxa_tag4
59func npw_build_payload(b: *u8, flen: i64, pid: i64, jl: *i64, q: *i64, dt: *i64, n: i64, pp: *i64) -> i64
called by 1: npw_write calls 2: nxa_findnxa_tag4
97func npw_put(fd: i64, p: *u8, n: i64) -> i64
110func npw_write(b: *u8, flen: i64, pid: i64, jl: *i64, q: *i64, dt: *i64, n: i64, outp: *u8, st: *i64) -> i64