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}