code wiki / _hdl_build / nx_autorig_gate.nx

nx_autorig_gate.nx source

↩ module page · 168 lines · 8937 B

1// nx_autorig_gate.nx -- prove AUTO-RIG + physics-param EMIT works on every generated object (no per-object 2// hand-authoring). T1 all 8 t2mesh objects rig: spanning tree (bones == parts-1), 0 forced joins, masses > 0. 3// T2 rigs VARY by object (>=5 distinct bone counts). T3 person: 18 parts / 17 bones and the derived root IS 4// the hips (largest volume = pelvis-style root, like real rigs) + every bone has positive length. T4 5// determinism (two builds byte-identical). T5 NXRG1 pack round-trip + corrupt-reject + person.nxrg written. 6// T6 physical sensibility: dumbbell weights equal mass, heavier than the bar. license_tier: ORIGINAL expect_exit: 0 7import "nx_syscalls.nx" 8import "nx_sdfrender.nx" 9import "nx_t2mesh.nx" 10import "nx_autorig.nx" 11 12func hw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 13func pn(v: i64) -> i64 { 14 let b: *u8 = sys_mmap(32) as *u8 15 var x: i64 = v; var neg: i64 = 0 16 if x < 0 { neg = 1; x = 0 - x } 17 var i: i64 = 31 18 if x == 0 { b[i] = 48 as u8; i = i - 1 } 19 while x > 0 { b[i] = (48 + x % 10) as u8; x = x / 10; i = i - 1 } 20 if neg == 1 { b[i] = 45 as u8; i = i - 1 } 21 sys_write(1, (b as i64 + i + 1) as *u8, 31 - i) 22 return 0 23} 24 25func rg_parent(bones: *i64, nb: i64, child: i64) -> i64 { 26 var i: i64 = 0 27 while i < nb { if bones[i * 2 + 1] == child { return bones[i * 2] } i = i + 1 } 28 return 0 - 1 29} 30 31func rg_one(base: i64, bones: *i64, masses: *i64, soft: *i64, out: *i64, prompt: *u8, failp: *i64) -> i64 { 32 t2m_prompt(base, prompt) 33 ar_build(base, bones, masses, soft, out) 34 let np: i64 = out[0] 35 let nb: i64 = out[1] 36 hw(" '"); hw(prompt); hw("' -> "); hw(t2m_name(t2m_id_of(prompt))) 37 hw(": parts="); pn(np); hw(" bones="); pn(nb); hw(" root="); pn(out[2]); hw(" forced="); pn(out[3]) 38 var ok: i64 = 1 39 if nb != np - 1 { ok = 0 } 40 if out[3] != 0 { ok = 0 } 41 var i: i64 = 0 42 while i < np { if masses[i] < 1 { ok = 0 } i = i + 1 } 43 if ok == 1 { hw(" [rigged]\n" as *u8) } else { hw(" [BAD]\n" as *u8); failp[0] = failp[0] + 1 } 44 return nb 45} 46 47func main() -> i64 { 48 let base: i64 = sys_mmap(sdf_bytes()) as i64 49 let bones: *i64 = sys_mmap(AR_MAXP * 2 * 8) as *i64 50 let masses: *i64 = sys_mmap(AR_MAXP * 8) as *i64 51 let soft: *i64 = sys_mmap(AR_MAXP * 8) as *i64 52 let out: *i64 = sys_mmap(8 * 8) as *i64 53 let bones2: *i64 = sys_mmap(AR_MAXP * 2 * 8) as *i64 54 let masses2: *i64 = sys_mmap(AR_MAXP * 8) as *i64 55 let soft2: *i64 = sys_mmap(AR_MAXP * 8) as *i64 56 let out2: *i64 = sys_mmap(8 * 8) as *i64 57 let nbs: *i64 = sys_mmap(16 * 8) as *i64 58 let failp: *i64 = sys_mmap(8) as *i64 59 failp[0] = 0 60 hw("=== nx_autorig_gate -- every emitted object AUTO-derives skeleton + mass + collision + soft params ===\n" as *u8) 61 62 nbs[0] = rg_one(base, bones, masses, soft, out, "a red rubber ball" as *u8, failp) 63 nbs[1] = rg_one(base, bones, masses, soft, out, "a snowman in the yard" as *u8, failp) 64 nbs[2] = rg_one(base, bones, masses, soft, out, "a heavy dumbbell" as *u8, failp) 65 nbs[3] = rg_one(base, bones, masses, soft, out, "a tall oak tree" as *u8, failp) 66 nbs[4] = rg_one(base, bones, masses, soft, out, "a mushroom" as *u8, failp) 67 nbs[5] = rg_one(base, bones, masses, soft, out, "a glass bottle" as *u8, failp) 68 nbs[6] = rg_one(base, bones, masses, soft, out, "an Elara person figure" as *u8, failp) 69 nbs[7] = rg_one(base, bones, masses, soft, out, "a desert cactus" as *u8, failp) 70 71 var fails: i64 = failp[0] 72 if fails == 0 { hw("T1 PASS all 8 objects rig: spanning tree, 0 forced joins, masses positive\n" as *u8) } 73 else { hw("T1 FAIL " as *u8); pn(fails); hw(" bad rigs\n" as *u8) } 74 75 var distinct: i64 = 0 76 var a: i64 = 0 77 while a < 8 { 78 var seen: i64 = 0 79 var b: i64 = 0 80 while b < a { if nbs[b] == nbs[a] { seen = 1 } b = b + 1 } 81 if seen == 0 { distinct = distinct + 1 } 82 a = a + 1 83 } 84 if distinct >= 5 { hw("T2 PASS rigs VARY by object: " as *u8); pn(distinct); hw("/8 distinct bone counts\n" as *u8) } 85 else { hw("T2 FAIL only " as *u8); pn(distinct); hw(" distinct\n" as *u8); fails = fails + 1 } 86 87 // T3 the person rig: 18 parts / 17 bones, root = hips (idx 7, largest volume = pelvis root), bones have length 88 t2m_prompt(base, "an Elara person figure" as *u8) 89 ar_build(base, bones, masses, soft, out) 90 var t3: i64 = 1 91 if out[0] != 18 { t3 = 0 } 92 if out[1] != 17 { t3 = 0 } 93 if out[2] != 7 { t3 = 0 } 94 let p: *i64 = (base + O_PARTS) as *i64 95 var bi: i64 = 0 96 while bi < out[1] { 97 let pa: i64 = bones[bi * 2] 98 let ch: i64 = bones[bi * 2 + 1] 99 let dx: i64 = p[ch * 6] - p[pa * 6] 100 let dy: i64 = p[ch * 6 + 1] - p[pa * 6 + 1] 101 let dz: i64 = p[ch * 6 + 2] - p[pa * 6 + 2] 102 if dx * dx + dy * dy + dz * dz < 1 { t3 = 0 } 103 bi = bi + 1 104 } 105 if t3 == 1 { 106 hw("T3 PASS person: 18 parts / 17 bones, derived root = HIPS -- the pelvis-style root real rigs use; all bones have length\n" as *u8) 107 hw(" skeleton: " as *u8) 108 bi = 0 109 while bi < out[1] { pn(bones[bi * 2]); hw(">" as *u8); pn(bones[bi * 2 + 1]); hw(" " as *u8); bi = bi + 1 } 110 hw("\n" as *u8) 111 } else { hw("T3 FAIL parts=" as *u8); pn(out[0]); hw(" bones=" as *u8); pn(out[1]); hw(" root=" as *u8); pn(out[2]); hw("\n" as *u8); fails = fails + 1 } 112 113 // T7 ANATOMICAL CHAIN (the star-bias killer): limbs must chain through their neighbors, not hang off a 114 // fat root's long support reach. person indices: 0 head 1 neck 2 chest 8/10 upper arms 9/11 forearms 115 // 12/13 hands 14/15 legs 16/17 feet. 116 var t7: i64 = 1 117 if rg_parent(bones, out[1], 9) != 8 { t7 = 0 } // forearm L -> upper arm L 118 if rg_parent(bones, out[1], 11) != 10 { t7 = 0 } // forearm R -> upper arm R 119 if rg_parent(bones, out[1], 12) != 9 { t7 = 0 } // hand L -> forearm L 120 if rg_parent(bones, out[1], 13) != 11 { t7 = 0 } // hand R -> forearm R 121 if rg_parent(bones, out[1], 8) != 2 { t7 = 0 } // upper arm L -> CHEST, not hips 122 if rg_parent(bones, out[1], 10) != 2 { t7 = 0 } // upper arm R -> CHEST 123 if rg_parent(bones, out[1], 0) != 1 { t7 = 0 } // head -> neck 124 if rg_parent(bones, out[1], 16) != 14 { t7 = 0 } // foot L -> leg L 125 if rg_parent(bones, out[1], 17) != 15 { t7 = 0 } // foot R -> leg R 126 if t7 == 1 { hw("T7 PASS ANATOMICAL chains: forearm>arm>chest, hand>forearm, head>neck, foot>leg -- min-surface-gap MST follows anatomy, no star-bias\n" as *u8) } 127 else { hw("T7 FAIL a limb attached to the wrong parent -- star-bias/misattachment present\n" as *u8); fails = fails + 1 } 128 129 // T4 determinism 130 ar_build(base, bones2, masses2, soft2, out2) 131 var diff: i64 = 0 132 if out2[0] != out[0] { diff = 1 } 133 if out2[1] != out[1] { diff = 1 } 134 if out2[2] != out[2] { diff = 1 } 135 var k: i64 = 0 136 while k < out[1] * 2 { if bones2[k] != bones[k] { diff = 1 } k = k + 1 } 137 k = 0 138 while k < out[0] { if masses2[k] != masses[k] { diff = 1 } if soft2[k] != soft[k] { diff = 1 } k = k + 1 } 139 if diff == 0 { hw("T4 PASS determinism: two rig builds identical\n" as *u8) } 140 else { hw("T4 FAIL rig differs across builds\n" as *u8); fails = fails + 1 } 141 142 // T5 NXRG1 pack: round-trip + corrupt-reject + persist 143 let buf: *u8 = sys_mmap(4096) as *u8 144 let plen: i64 = ar_pack(base, bones, masses, soft, out, buf) 145 var t5: i64 = 1 146 if ar_unpack_ok(buf, plen) != 1 { t5 = 0 } 147 buf[2] = 81 as u8 148 if ar_unpack_ok(buf, plen) != 0 { t5 = 0 } 149 buf[2] = 82 as u8 150 if ar_unpack_ok(buf, plen) != 1 { t5 = 0 } 151 let fd: i64 = sys_openat_wr("knowledge/person.nxrg" as *u8, 0x1a4) 152 if fd < 0 { t5 = 0 } else { sys_write(fd, buf, plen); sys_close(fd) } 153 if t5 == 1 { hw("T5 PASS NXRG1 pack: " as *u8); pn(plen); hw("B, round-trip valid, corrupt-REJECTED, wrote knowledge/person.nxrg\n" as *u8) } 154 else { hw("T5 FAIL pack\n" as *u8); fails = fails + 1 } 155 156 // T6 physical sensibility: dumbbell weights equal + heavier than the bar 157 t2m_prompt(base, "a heavy dumbbell" as *u8) 158 ar_build(base, bones, masses, soft, out) 159 var t6: i64 = 1 160 if masses[0] != masses[1] { t6 = 0 } 161 if masses[0] <= masses[2] { t6 = 0 } 162 if t6 == 1 { hw("T6 PASS physics params sensible: dumbbell weights equal mass " as *u8); pn(masses[0]); hw(" each, bar lighter " as *u8); pn(masses[2]); hw("\n" as *u8) } 163 else { hw("T6 FAIL masses w0=" as *u8); pn(masses[0]); hw(" w1=" as *u8); pn(masses[1]); hw(" bar=" as *u8); pn(masses[2]); hw("\n" as *u8); fails = fails + 1 } 164 165 if fails == 0 { hw("GATE GREEN: auto-rig EMITS skeleton + mass + collision + soft params for EVERY generated object, derived from geometry -- the physics half of the emitter is wired at v0.\n" as *u8) } 166 else { hw("GATE RED fails=" as *u8); pn(fails); hw("\n" as *u8) } 167 return fails 168}