code wiki / (root) / nx_nxa_retarget.nx

nx_nxa_retarget.nx

buildroot/runtime/nx_nxa_retarget.nx

51459 B1091 linesdepth 3pulls 7 transitivereach 0 importersview sourcekind tooltopic nxa
docsdependenciesstructsconstsfunctions

about

nx_nxa_retarget.nx -- DONOR RETARGET: drive a rigged NXA that carries NO authored clips from a SOURCE rig's POSE, preserving the TARGET's OWN bone lengths BY CONSTRUCTION. WHY (measured 2026-08-23): all five donors report poses_in_library=0 -- they carry rigs but no authored motion, so the visiting cast on /world/beach stand as statues while every other piece of the character stack ships. This organ is the missing leg. THE NAIVE RETARGET IS PROVABLY WRONG, AND THAT PROOF IS WHY THIS FILE EXISTS. In the NXA normative form M x = D(x-b) + b + dt, applying joint j's transform to its own bind position gives M_j b_j = b_j + dt_j. So a posed joint sits at b_j + dt_j and POSED BONE LENGTH IS A PURE FUNCTION OF dt. Copying source dt -- or scaling it by a height ratio -- therefore cannot preserve the target's bone lengths unless the two skeletons are proportionally identical, and ours are emphatically not (104 joints at 1.715 m against 370 joints on a differently-proportioned donor). A dt-transfer retarget stretches and shears limbs on every donor: the exact defect the operator named as awful motion. It is not shipped here. THE ALGORITHM (four lines, and limb length is preserved BY CONSTRUCTION, not by tolerance): A_j = conj(D_parent) . D_j source: world delta -> local articulation W_j = W_parent . A_j target: parent-first composition P_j = P_parent + W_parent (x) (b'_j - b'_p) the TARGET's OWN bone vector, ROTATED ONLY dt'_j = P_j - b'_j The target bone vector is only ever rotated -- never scaled, never replaced -- so no pose this organ can emit is able to change a target bone's length. The limb-length tooth in the gate is a REGRESSION GUARD on that property, not the thing that establishes it. The general form needs a similarity conjugation by each joint's bind orientation. It collapses to the four lines above because NXA bind orientation is IDENTITY BY CONSTRUCTION -- nx_nxa_skin emits SKEL quats as identity and states the reason in its own header (delta-LBS convention: animation is applied RELATIVE to bind). VERIFY THAT BEFORE TRUSTING IT: the `bindquats` verb measures it per asset and is the reason this organ has three verbs instead of one. JOINT MAPPING IS BY TOPOLOGY AND NORMALIZED BIND POSITION, NEVER BY NAME. SKEL carries no names by design, and the donors come from different authoring tools -- a name map would be the classifier-keys-on-a-string defect. The normalized space is the same one nx_nxa_joints uses: every axis divided by the rig's OWN stature extent, so a taller or differently-scaled rig lands in the same space. The stature axis is DERIVED as the largest bind extent, never assumed z-up: the FBX/VRM donors arrive Y-up, which is the axis-convention defect a sibling lane measured in the renderer on the same day. usage: nx_nxa_retarget bindquats <file.nxa>

dependencies 5 imports · 0 importers

nx_syscalls.nx nx_nxa.nx nx_nxa_fk.nx nx_skeleton.nx nx_nxa_posewrite_lib.nx nx_nxa_retarget.nx

imports: nx_syscalls.nxnx_nxa.nxnx_nxa_fk.nxnx_skeleton.nxnx_nxa_posewrite_lib.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main nrerr sys_write nr_streq nr_bindquats sys_mmap nxa_die sys_write ↻ sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ nr_load sys_read_file sys_openat_rd sys_lseek sys_mmap ↻ sys_read sys_munmap sys_close nrerr ↻ nxa_find nxa_section_entry nxa_magic nxa_check2 nxa_tag4 nrw sys_write ↻ nrn sys_mmap ↻ sys_write ↻ nr_atoi

structs

none

consts

55const NR_Q12: i64 = 4096 // quaternion fixed-point unit (NXA v1 spec)
56const NR_WJ: i64 = 8 // words per SKEL joint (spec: parent,tx,ty,tz,qx,qy,qz,qw)
57const NR_WPE: i64 = 8 // words per POSE entry (spec: joint,qx,qy,qz,qw,dtx,dty,dtz)
58const NR_PERMIL: i64 = 1000
59const NR_INF: i64 = 4 // SKIN influences per vertex, fixed by the format
60const NR_WQ: i64 = 4096 // SKIN weight scale q12, sum = 4096 (spec)
61const NR_FX: i64 = 256 // nx_skeleton weight scale fx256, sum = 256
65const NR_DT_MODEL: i64 = 1
66const NR_WFULL: i64 = 1000
67const NR_MODE: i64 = 0x1a4 // 0644, matching every sibling NXA writer
68const NR_EXIT_USAGE: i64 = 2
69const NR_EXIT_REFUSE: i64 = 3
70const NR_EXIT_NOSEC: i64 = 5
71const NR_EXIT_NONIDENT: i64 = 1 // bindquats: a measurement outcome, not an error

functions

73func nrw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
called by 2: nr_bindquatsmain calls 1: sys_write
74func nrerr(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(2, s, n); return 0 }
called by 2: nr_bindquatsmain calls 1: sys_write
75func nrn(v: i64) -> i64
called by 2: nr_bindquatsmain calls 2: sys_mmapsys_write
88func nr_atoi(s: *u8) -> i64
called by 1: main
98func nr_streq(a: *u8, b: *u8) -> i64
called by 1: main
107func nr_q(p: *i64, i: i64) -> *i64 { return ((p as i64) + i * 32) as *i64 }
called by 1: main
112func nr_norm(bind: *i64, n: i64, out: *i64) -> i64
called by 1: main calls 1: sys_mmap
150func nr_d2(a: *i64, ai: i64, b: *i64, bi: i64) -> i64
called by 2: nr_mean_nnmain
160func nr_mean_nn(nrm: *i64, n: i64) -> i64
called by 2: nr_framemain calls 2: nr_d2nf_isqrt
180func nr_load(path: *u8, lp: *i64) -> *u8
called by 2: nr_bindquatsmain calls 1: sys_read_file
194func nr_sym(bind: *i64, n: i64, k: i64, tol: i64) -> i64
called by 1: nr_frame
234func nr_frame(bind: *i64, n: i64, ax: *i64) -> i64
called by 1: main calls 3: nr_mean_nnsys_mmapnr_sym
275func nr_permute(bind: *i64, n: i64, ax: *i64, sg: *i64, out: *i64) -> i64
called by 1: main
287func nr_reframe_v(v: *i64, out: *i64, sax: *i64, ssg: *i64, tax: *i64, tsg: *i64) -> i64
called by 1: main
292func nr_frame_det(sax: *i64, ssg: *i64, tax: *i64, tsg: *i64) -> i64
called by 1: main calls 1: sys_mmap
304func nr_parity(ax: *i64) -> i64
called by 1: main
326func nr_extremity_band(bind: *i64, par: *i64, n: i64, upax: i64, want_max: i64) -> i64
called by 1: main calls 1: nf_isqrt
372func nr_band_for_pop(vert: *i64, nv: i64, upax: i64, want_max: i64, minpop: i64, ulo: i64, uhi: i64) -> i64
called by 1: nr_anterior
391func nr_anterior(vert: *i64, nv: i64, ax: *i64, blo: i64, bhi: i64, minpop: i64, ev: *i64) -> i64
called by 1: main calls 1: nr_band_for_pop
472func nr_bindquats(path: *u8) -> i64
502func main(argc: i64, argv: *i64) -> i64