code wiki / (root) / nx_autorig_pose_gate.nx

nx_autorig_pose_gate.nx

buildroot/runtime/nx_autorig_pose_gate.nx

26551 B496 linesdepth 5pulls 14 transitivereach 0 importersview sourcekind gate/prooftopic autorig
docsdependenciesstructsconstsfunctions

about

nx_autorig_pose_gate.nx -- THE END-TO-END DONE-RULE GATE FOR DC16 (the BEND case): a BARE mesh goes through nx_curveskel (skeleton) then nx_boneheat (weights), a 90 degree shoulder SWING is baked into the asset as a POSE and PLAYED by the served nx_nxa_play, and the deformed skin is measured through md_measure -- this estate's ONE mesh deviation ruler, never a second one -- plus a direct crease read across the shoulder. THE POSE IS A BAKED WORLD DELTA, BECAUSE THAT IS THE PLAYER'S CONTRACT. nx_nxa_play applies, per joint, M x = D(x - bind_t) + bind_t + dt with NO hierarchy walk at runtime (nxa_format_spec.md), so a single-joint entry moves only that joint's skinned band -- measured 2026-09-05: one entry on joint 1 read md max=3 against a 10 mm bar while the ring crease read 5 mm, i.e. a local sleeve, not a swing. A real bend therefore carries one entry per joint of the swung subtree: D = R and dt = (R - I)(bind_t_j - P), which is exactly the rigid swing out = R(v - P) + P about the shoulder pivot P, while the rest of the body stays put. UNITS, MEASURED NOT ASSUMED: the NXMESH handed to md_measure is in millimetres (NXA 0.01 mm -> tenths -> mm at nm_put_tri), and md_measure reports in 0.1 mm: the 16-joint swing read max=259 (a ~26 mm tip), the twist sleeve read 3 (0.3 mm). A bar written in 0.01 mm quanta here was 10x too high and failed a real swing. WHAT IT PROVES AND WHAT IT DOES NOT. Smooth geodesic weights make the shoulder a SOFTER crease than the hard nearest-joint boundary (the adjacent-ring displacement jump is smaller), and the pose really swings the limb (md_measure posed-vs-rest reaches a derived floor). It does NOT prove the twist case: candy-wrapper collapse under an axial twist is a DEFORMER property (nx_skeleton is linear-blend only, no dual-quaternion path), and smoother weights make that collapse worse, so it is deferred to a dual-quaternion rung on the deformer's board. SUBJECTS: the two libs in-process, the PLAYER forked as the deployed binary at its absolute path. license_tier: ORIGINAL expect_exit: 0

dependencies 8 imports · 0 importers

nx_syscalls.nx nx_gate_verdict.nx nx_nxa.nx nx_curveskel_lib.nx nx_tool_run.nx nx_nxmesh_lib.nx nx_mmdev_lib.nx nx_nxa_fk.nx nx_autorig_pose_gate.nx

imports: nx_syscalls.nxnx_gate_verdict.nxnx_nxa.nxnx_curveskel_lib.nxnx_tool_run.nxnx_nxmesh_lib.nxnx_mmdev_lib.nxnx_nxa_fk.nx

imported by: nobody (leaf or entry point)

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

main gv_ctr 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 ↻ gv_head gv_puts sys_write ↻ sys_mkdir sys_mmap ↻ ag_prism sys_mmap ↻ ag_ring_xy ag_tri ag_write2 sys_mmap ↻ nxa_tag4 bh_nxa_write sys_mmap ↻ nxa_check2 nxa_magic sys_openat_wr sys_write ↻ sys_close cs_run cs_run_cells sys_mmap ↻ sys_read_file

structs

none

consts

30const AG_DIR: *u8 = "/tmp/nx_autorig_pose_gate"
31const AG_MODE_DIR: i64 = 493
32const AG_PLAY: *u8 = "/volume1/homes/elderwesto/nishihost/nx_nxa_play.elf"
33const AG_AROUND: i64 = 4
34const AG_LEN: i64 = 6000 // 60 mm prism, 0.01 mm units
35const AG_RINGS: i64 = 61 // one ring per mm
36const AG_RING_STEP: i64 = 100 // mm between rings in 0.01 mm units
37const AG_R: i64 = 300 // 3 mm half-width
38const AG_CELLS: i64 = 64
39const AG_VERT_CAP: i64 = 1024
40const AG_TRI_CAP: i64 = 4096
41const AG_POSE_ID: i64 = 1
42const AG_POSE_ID_ARG: *u8 = "1"
43const AG_WFULL_ARG: *u8 = "1000"
44const AG_Q12_SIN45: i64 = 2896 // round(4096 x sin 45): a 90 degree turn about x is (s,0,0,s)
45const AG_POSE_HDR_WORDS: i64 = 3 // npose, pid, ne
46const AG_POSE_ENTRY_WORDS: i64 = 8 // joint, qx qy qz qw, tx ty tz (the player's entry layout)
47const AG_MIN_SUBTREE: i64 = 2 // a swing of fewer than two joints is a sleeve, not a limb
48const AG_CAPTURE_CAP: i64 = 65536
49const AG_ARGV_SLOTS: i64 = 8
50const AG_WORD_BYTES: i64 = 8
51const AG_CWD_CAP: i64 = 4096
52const AG_NO_TIMEOUT: i64 = 0
53const AG_SLASH: i64 = 47
54const AG_NXA_PER_TENTH: i64 = 10 // NXA 0.01 mm -> NXMESH input tenths of a mm
55const AG_MD_MIN_SWING: i64 = 100 // 10 mm in md_measure's 0.1 mm units (see UNITS above): a third of the 30 mm limb must move
56const AG_MAGIC: *u8 = "NXMSH2" // the ruler reads ntris at 12 and never the magic; written for readers that do
57const AG_MAGIC_LEN: i64 = 6
58const AG_MAGIC_FIELD: i64 = 8
59const AG_ROOT: i64 = 0 - 1

functions

61func hw(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 1: main calls 1: sys_write
62func ag_ring_xy(k: i64, r: i64, out: *i64) -> i64
called by 1: ag_prism
69func ag_tri(tris: *i64, st: *i64, a: i64, b: i64, c: i64) -> i64
called by 1: ag_prism
75func ag_prism(vert: *i64, tris: *i64, st: *i64, r: i64, z0: i64, z1: i64, rings: i64) -> i64
called by 1: main calls 3: sys_mmapag_ring_xyag_tri
120func ag_write2(path: *u8, vert: *i64, tris: *i64, st: *i64) -> i64
called by 1: main calls 3: sys_mmapnxa_tag4bh_nxa_write
136func ag_append_swing(inpath: *u8, outpath: *u8, info: *i64) -> i64
220func ag_dirname(path: *u8, out: *u8) -> i64
called by 1: ag_play
231func ag_play(inp: *u8, outp: *u8, cap: *u8, olen: *i64) -> i64
243func ag_find(b: *u8, n: i64, lit: *u8) -> i64
called by 2: ag_hasag_num_after
257func ag_has(b: *u8, n: i64, lit: *u8) -> i64 { if ag_find(b, n, lit) >= 0 { return 1 } return 0 }
called by 1: main calls 1: ag_find
260func ag_num_after(b: *u8, n: i64, key: *u8) -> i64
called by 1: main calls 1: ag_find
280func ag_nxmesh(b: *u8, flen: i64) -> *u8
312func ag_disp(ra: *u8, fa: i64, pb: *u8, fb: i64, v: i64) -> i64
called by 1: ag_max_ring_jump calls 2: nxa_findnxa_tag4
323func ag_max_ring_jump(ra: *u8, fa: i64, pb: *u8, fb: i64) -> i64
called by 1: main calls 1: ag_disp
340func ag_open(path: *u8, lp: *i64) -> i64
called by 1: main calls 1: sys_read_file
345func ag_files_equal(pa: *u8, pb: *u8) -> i64
called by 1: main calls 2: sys_mmapsys_read_file
358func main() -> i64