nx_gltf2mesh_rig_gate.nx
buildroot/runtime/nx_gltf2mesh_rig_gate.nx
about
nx_gltf2mesh_rig_gate.nx -- THE GATE FOR R22, RIG-CARRYING glTF INGEST (contract g2_skin_weights).
SUBJECT: the nx_gltf2mesh ELF, forked for real, asked for an .nxa output. The claim under test is
that a rigged glTF donor's SKELETON AND SKIN SURVIVE INGEST -- the exact thing nx_roundtrip measured
as lost on 2026-08-22 (9 named parts -> 1, 192 bytes = 8 x 24 dropped layer records, on every
rigged donor). So the load-bearing teeth read the emitted NXANIM01 back through INDEPENDENT
readers, not through the subject's own status line:
- nx_asset_floor_gate (a shipped, separately-written NXA reader) reports verts/tris/joints;
- nxa_find from nx_nxa.nx (the ONE checksum definition every NXA reader imports) verifies the
TOC and every section's payload checksum;
- this gate's own minimal TOC walk checks the SKIN/SKEL word lengths against what the donor's
vertex and joint counts REQUIRE (computed, never eyeballed) and sums every vertex's weights.
FIXTURES ARE THE REAL DONORS, BY ABSOLUTE PATH, PLUS ONE FIXTURE ASSEMBLED AT RUNTIME: the
count-mismatch donor is nishi_being_walk.glb with ONE accessor's count patched (8180 -> 8189, same
text length so the glb stays well-formed). A hand-authored glb would test the fixture's authoring;
a patched real donor tests the subject. Outputs are UNLINKED AT SETUP -- a gate that is not
idempotent reports on its first run and lies about every run after (measured on this estate today).
DERIVED EXPECTATIONS, QUOTED FROM THE DONORS' OWN JSON (read 2026-08-22, offset 20 of each glb):
nishi_being_walk.glb: POSITION count 8180, indices count 49080 (-> 16360 index triples), skins
[{"joints":[1..11]}], node 2 "Lsh" translation [-185,520,15] under node 1 "root" (no
translation) -> joint 1 binds at (-185, 520, 15) mm and joint 0 is the root (parent -1).
⚠JOINT COUNT IS NO LONGER QUOTED FROM THIS DONOR -- see RG_WALK_JOINTS. Quoting a published
artifact freezes ITS vintage as the spec, and on 2026-08-26 the donor was republished with the
spec-correct FLOAT normals AND the emitter's current 11-joint rig, turning two teeth RED for a
reason that was never about the subject. The other expectations here (vertex/index counts, the
Lsh bind) are STRUCTURAL and unchanged by that republish; only the rig grew.
nishi-in-seedsan-proportions.glb: POSITION 6728, indices 40332 (-> 13444), joints [1..11],
node 2 "Lsh" translation [-65,520,15].
synth/elf.glb: skins ABSENT (skin_joints=0) -- the unskinned control.
license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 4 imports · 0 importers
imports: nx_syscalls.nxnx_gate_verdict.nxnx_tool_run.nxnx_nxa.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 38 | const RG_SUBJECT_DEFAULT: *u8 = "/volume1/homes/elderwesto/nishihost/nx_gltf2mesh.elf" |
| 39 | const RG_FLOOR_GATE: *u8 = "/volume1/homes/elderwesto/nishihost/nx_asset_floor_gate.elf" |
| 40 | const RG_WALK: *u8 = "/volume1/homes/elderwesto/nishihost/sites/nishifamily/compare/vam/nishi_being_walk.glb" |
| 41 | const RG_SEED: *u8 = "/volume1/homes/elderwesto/nishihost/sites/nishifamily/exceed/vrm/nishi-in-seedsan-proportions.glb" |
| 42 | const RG_ELF: *u8 = "/volume1/homes/elderwesto/nishihost/sites/nishifamily/synth/elf.glb" |
| 44 | const RG_DIR: *u8 = "/tmp/nx_gltf2mesh_rig_gate" |
| 45 | const RG_WALK_NXA: *u8 = "/tmp/nx_gltf2mesh_rig_gate/walk.nxa" |
| 46 | const RG_SEED_NXA: *u8 = "/tmp/nx_gltf2mesh_rig_gate/seed.nxa" |
| 47 | const RG_ELF_NXA: *u8 = "/tmp/nx_gltf2mesh_rig_gate/elf.nxa" |
| 48 | const RG_ELF_MSH: *u8 = "/tmp/nx_gltf2mesh_rig_gate/elf.nxmesh" |
| 49 | const RG_MIS_GLB: *u8 = "/tmp/nx_gltf2mesh_rig_gate/mismatch.glb" |
| 50 | const RG_MIS_NXA: *u8 = "/tmp/nx_gltf2mesh_rig_gate/mismatch.nxa" |
| 53 | const RG_WALK_VERTS: i64 = 8180 |
| 54 | const RG_WALK_TRIS: i64 = 16360 |
| 61 | const RG_WALK_JOINTS: i64 = 11 |
| 62 | const RG_WALK_LSH_X: i64 = 0 - 185 |
| 63 | const RG_WALK_LSH_Y: i64 = 520 |
| 64 | const RG_WALK_LSH_Z: i64 = 15 |
| 65 | const RG_SEED_VERTS: i64 = 6728 |
| 66 | const RG_SEED_TRIS: i64 = 13444 |
| 67 | const RG_SEED_JOINTS: i64 = 11 |
| 68 | const RG_SEED_LSH_X: i64 = 0 - 65 |
| 69 | const RG_SEED_LSH_Y: i64 = 520 |
| 70 | const RG_SEED_LSH_Z: i64 = 15 |
| 71 | const RG_LSH_JOINT: i64 = 1 // joints[1] == node 2 == "Lsh" in both donors |
| 72 | const RG_BIND_TOL_MM: i64 = 1 // f32 -> mm decode truncates below one unit; the donor values are whole mm |
| 75 | const RG_MIS_ANCHOR: *u8 = "\x22bufferView\x22:4,\x22componentType\x22:5121,\x22normalized\x22:true,\x22count\x22:8180" |
| 76 | const RG_MIS_FROM: i64 = 48 // '0' -- the last digit of 8180 ... |
| 77 | const RG_MIS_TO: i64 = 57 // '9' -- ... becomes 8189: same length, a different count |
| 80 | const RG_VRM: *u8 = "/volume1/homes/elderwesto/nishihost/sites/nishifamily/exceed/vrm/seed-san.vrm" |
| 81 | const RG_VRM_NXA: *u8 = "/tmp/nx_gltf2mesh_rig_gate/vrm.nxa" |
| 82 | const RG_DIS_GLB: *u8 = "/tmp/nx_gltf2mesh_rig_gate/disjoint.glb" |
| 83 | const RG_DIS_NXA: *u8 = "/tmp/nx_gltf2mesh_rig_gate/disjoint.nxa" |
| 87 | const RG_DIS_JSON: *u8 = "{\x22asset\x22:{\x22version\x22:\x222.0\x22},\x22scene\x22:0,\x22scenes\x22:[{\x22nodes\x22:[0]}],\x22nodes\x22:[{\x22children\x22:[1,2,3,4,5,6]},{\x22name\x22:\x22jA0\x22},{\x22name\x22:\x22jA1\x22},{\x22name\x22:\x22jB0\x22},{\x22name\x22:\x22jB1\x22},{\x22mesh\x22:0,\x22skin\x22:0},{\x22mesh\x22:1,\x22skin\x22:1}],\x22meshes\x22:[{\x22primitives\x22:[{\x22attributes\x22:{\x22POSITION\x22:0,\x22JOINTS_0\x22:1,\x22WEIGHTS_0\x22:2},\x22indices\x22:3}]},{\x22primitives\x22:[{\x22attributes\x22:{\x22POSITION\x22:4,\x22JOINTS_0\x22:5,\x22WEIGHTS_0\x22:6},\x22indices\x22:7}]}],\x22skins\x22:[{\x22joints\x22:[1,2],\x22inverseBindMatrices\x22:8},{\x22joints\x22:[3,4],\x22inverseBindMatrices\x22:9}],\x22accessors\x22:[{\x22bufferView\x22:0,\x22componentType\x22:5126,\x22count\x22:3,\x22type\x22:\x22VEC3\x22},{\x22bufferView\x22:1,\x22componentType\x22:5121,\x22count\x22:3,\x22type\x22:\x22VEC4\x22},{\x22bufferView\x22:2,\x22componentType\x22:5121,\x22normalized\x22:true,\x22count\x22:3,\x22type\x22:\x22VEC4\x22},{\x22bufferView\x22:3,\x22componentType\x22:5123,\x22count\x22:3,\x22type\x22:\x22SCALAR\x22},{\x22bufferView\x22:4,\x22componentType\x22:5126,\x22count\x22:3,\x22type\x22:\x22VEC3\x22},{\x22bufferView\x22:5,\x22componentType\x22:5121,\x22count\x22:3,\x22type\x22:\x22VEC4\x22},{\x22bufferView\x22:6,\x22componentType\x22:5121,\x22normalized\x22:true,\x22count\x22:3,\x22type\x22:\x22VEC4\x22},{\x22bufferView\x22:7,\x22componentType\x22:5123,\x22count\x22:3,\x22type\x22:\x22SCALAR\x22},{\x22bufferView\x22:8,\x22componentType\x22:5126,\x22count\x22:2,\x22type\x22:\x22MAT4\x22},{\x22bufferView\x22:9,\x22componentType\x22:5126,\x22count\x22:2,\x22type\x22:\x22MAT4\x22}],\x22bufferViews\x22:[{\x22buffer\x22:0,\x22byteOffset\x22:0,\x22byteLength\x22:36},{\x22buffer\x22:0,\x22byteOffset\x22:36,\x22byteLength\x22:12},{\x22buffer\x22:0,\x22byteOffset\x22:48,\x22byteLength\x22:12},{\x22buffer\x22:0,\x22byteOffset\x22:60,\x22byteLength\x22:6},{\x22buffer\x22:0,\x22byteOffset\x22:68,\x22byteLength\x22:36},{\x22buffer\x22:0,\x22byteOffset\x22:104,\x22byteLength\x22:12},{\x22buffer\x22:0,\x22byteOffset\x22:116,\x22byteLength\x22:12},{\x22buffer\x22:0,\x22byteOffset\x22:128,\x22byteLength\x22:6},{\x22buffer\x22:0,\x22byteOffset\x22:136,\x22byteLength\x22:128},{\x22buffer\x22:0,\x22byteOffset\x22:264,\x22byteLength\x22:128}],\x22buffers\x22:[{\x22byteLength\x22:392}]}" |
| 88 | const RG_GLB_MAGIC: i64 = 1179937895 // 'g''l''T''F' little-endian |
| 89 | const RG_GLB_VER: i64 = 2 |
| 90 | const RG_CH_JSON: i64 = 1313821514 // 'J''S''O''N' |
| 91 | const RG_CH_BIN: i64 = 5130562 // 'B''I''N'0 |
| 92 | const RG_F32_ONE: i64 = 1065353216 // 1.0f bit pattern |
| 93 | const RG_U8_FULL: i64 = 255 // normalized u8 weight 1.0 |
| 94 | const RG_DIS_BINLEN: i64 = 392 |
| 95 | const RG_GLB_HDR: i64 = 12 |
| 96 | const RG_CHUNK_HDR: i64 = 8 |
| 97 | const RG_ASCII_SP: i64 = 32 |
| 98 | const RG_ALIGN4: i64 = 4 |
| 99 | const RG_MAT4_BYTES_G: i64 = 64 |
| 102 | const RG_NXA_NSEC_OFF: i64 = 16 |
| 103 | const RG_NXA_TOC_OFF: i64 = 32 |
| 104 | const RG_NXA_TOC_ROW: i64 = 32 |
| 105 | const RG_NXA_TOC_OFF_FIELD: i64 = 8 |
| 106 | const RG_NXA_TOC_WL_FIELD: i64 = 16 |
| 107 | const RG_TAG_BYTES: i64 = 4 |
| 108 | const RG_WORD: i64 = 8 |
| 109 | const RG_SKIN_WORDS: i64 = 8 |
| 110 | const RG_SKEL_WORDS: i64 = 8 |
| 111 | const RG_VEC4: i64 = 4 |
| 112 | const RG_Q12: i64 = 4096 |
| 113 | const RG_BYTE_RADIX: i64 = 256 |
| 114 | const RG_BYTE_MASK: i64 = 255 |
| 115 | const RG_MSH_HDR: i64 = 16 |
| 116 | const RG_MSH_LAYROW: i64 = 24 |
| 117 | const RG_MSH_TRIREC_PLUS_ID: i64 = 88 // 84-byte record + 4-byte per-tri layer id, as nx_gltf2mesh writes it |
| 118 | const RG_MSH_NLAY_OFF: i64 = 8 |
| 119 | const RG_MSH_NTRI_OFF: i64 = 12 |
| 120 | const RG_U32: i64 = 4 |
| 122 | const RG_CAPTURE_CAP: i64 = 262144 |
| 123 | const RG_ARGV_SLOTS: i64 = 8 |
| 124 | const RG_MODE_DIR: i64 = 493 |
| 125 | const RG_ASCII_ZERO: i64 = 48 |
| 126 | const RG_ASCII_NINE: i64 = 57 |
| 127 | const RG_DECIMAL: i64 = 10 |
| 128 | const RG_EXEC_FAIL: i64 = 127 |
functions
| 130 | func rg_rd64(b: *u8, off: i64) -> i64 |
| 136 | func rg_rd32(b: *u8, off: i64) -> i64 called by 1: main |
| 142 | func rg_tag_eq(b: *u8, off: i64, t: *u8) -> i64 called by 1: rg_sec |
| 148 | func rg_sec(b: *u8, t: *u8, wl: *i64) -> i64 |
| 159 | func rg_exists(path: *u8) -> i64 |
| 165 | func rg_run(subject: *u8, a1: *u8, a2: *u8, out: *u8, outlen: *i64) -> i64 |
| 174 | func rg_num_after(buf: *u8, n: i64, key: *u8) -> i64 |
| 203 | func rg_find_all(b: *u8, n: i64, lit: *u8, cnt: *i64) -> i64 called by 1: main |
| 218 | func rg_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } |
| 219 | func rg_wr32le(b: *u8, o: i64, v: i64) -> i64 called by 1: rg_write_disjoint |
| 229 | func rg_write_disjoint(path: *u8) -> i64 |
| 284 | func rg_floor_read(path: *u8, r: *i64, cap: *u8, olen: *i64) -> i64 |
| 296 | func rg_skin_audit(b: *u8, ko: i64, nv: i64, nj: i64, st: *i64) -> i64 |
| 324 | func main(argc: i64, argv: *i64) -> i64 |