code wiki / _hdl_build / nx_explode3d_gate.nx
nx_explode3d_gate.nx source
↩ module page · 317 lines · 13983 B
1// nx_explode3d_gate.nx -- teeth for R2: the 3D exploded-view engine DRIVEN BY THE REAL STEP ASSEMBLY.
2// Parses banked as1-oc-214.stp (nx_step_parse R1a) -> DFS the occurrence tree -> one 3D part per leaf
3// instance (box/prism STAND-INS by product name; real face tessellation = R1b) -> nx_explode3d staged
4// radial explode -> nx_meshrender frames -> ANIMATED APNG knowledge/nx_explode_as1.apng (assemble<->explode
5// loop = the explodeview signature). T1 part count == INDEPENDENT occurrence-expansion count (two different
6// computations agree) · T2 mean pairwise part distance strictly MONOTONIC in t · T3 exploded >= 2x assembled
7// spread · T4 pose determinism (same t -> same bytes) · T5 staged depth (depth-3 parts travel further than
8// depth-1) · T6 renders non-vacuous + assembled differs from exploded · T7 APNG written (signature + size).
9// expect_exit: 0 license_tier: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_step_parse.nx"
12import "nx_explode3d.nx"
13import "nx_render_core.nx"
14import "nx_meshrender.nx"
15import "nx_apng.nx"
16
17func xg_tooth(name: *u8, pass: i64, fails: *i64) -> i64 {
18 sp_puts(" " as *u8); sp_puts(name); sp_puts(" -> " as *u8)
19 if pass == 1 { sp_puts("PASS\n" as *u8); return 0 }
20 sp_puts("FAIL\n" as *u8)
21 fails[0] = fails[0] + 1
22 return 0
23}
24
25// layout law lives in nx_explode3d (ex3_rad/ex3_dyv) -- shared with the explodelab tree generator
26
27// framebuffer coverage vs background + additive checksum (determinism/difference probes)
28func xg_cover(fb: *i64, n: i64, bg: i64) -> i64 { var k: i64 = 0; var i: i64 = 0; while i < n { if fb[i] != bg { k = k + 1 } i = i + 1 } return k }
29func xg_chk(v: *i64, n: i64) -> i64 { var x: i64 = 0; var i: i64 = 0; while i < n { x = x + v[i] * (1 + (i % 7)); i = i + 1 } return x }
30
31func main() -> i64 {
32 sp_puts("=== nx_explode3d_gate -- 3D staged explode of the REAL as1 STEP assembly ===\n" as *u8)
33 let fails: *i64 = sys_mmap(8) as *i64
34 fails[0] = 0
35
36 // ---- parse the real STEP file (R1a) ----
37 let buf: *u8 = sys_mmap(4194304)
38 let aid: *i64 = sys_mmap(524288) as *i64
39 let anm: *i64 = sys_mmap(524288) as *i64
40 let anl: *i64 = sys_mmap(524288) as *i64
41 let aao: *i64 = sys_mmap(524288) as *i64
42 let aal: *i64 = sys_mmap(524288) as *i64
43 let st: *i64 = sys_mmap(256) as *i64
44 let n: i64 = sp_read_file("knowledge/fetched/step_as1.stp" as *u8, buf, 4194304)
45 if n <= 0 { sp_puts("MISSING step_as1.stp -- run nx_step_sample_fetch\nRED\n" as *u8); return 1 }
46 let ig0: i64 = sp_init(st, buf, n, aid, anm, anl, aao, aal)
47 let cnt: i64 = sp_scan(st)
48 let pe: *i64 = sys_mmap(2048) as *i64
49 let ce: *i64 = sys_mmap(2048) as *i64
50 let en: i64 = sp_nauo_collect(st, pe, ce, 256)
51 sp_puts("entities=" as *u8); sp_putn(cnt); sp_puts(" edges=" as *u8); sp_putn(en); sp_puts("\n" as *u8)
52
53 // root = parent that is never a child
54 var rootpd: i64 = 0 - 1
55 var i: i64 = 0
56 while i < en {
57 let p: i64 = pe[i]
58 var ischild: i64 = 0
59 var j: i64 = 0
60 while j < en { if ce[j] == p { ischild = 1 } j = j + 1 }
61 if ischild == 0 { rootpd = p }
62 i = i + 1
63 }
64
65 // ---- INDEPENDENT expanded-occurrence count (relaxation over the edge list, no DFS) ----
66 let dpd: *i64 = sys_mmap(1024) as *i64
67 var nd: i64 = 0
68 var e2: i64 = 0
69 while e2 < en {
70 var side: i64 = 0
71 while side < 2 {
72 var v: i64 = pe[e2]
73 if side == 1 { v = ce[e2] }
74 var seen: i64 = 0
75 var q: i64 = 0
76 while q < nd { if dpd[q] == v { seen = 1 } q = q + 1 }
77 if seen == 0 { dpd[nd] = v; nd = nd + 1 }
78 side = side + 1
79 }
80 e2 = e2 + 1
81 }
82 let occ: *i64 = sys_mmap(1024) as *i64
83 let occn: *i64 = sys_mmap(1024) as *i64
84 var q2: i64 = 0
85 while q2 < nd { occ[q2] = 0; if dpd[q2] == rootpd { occ[q2] = 1 } q2 = q2 + 1 }
86 var pass: i64 = 0
87 while pass < 12 {
88 var q3: i64 = 0
89 while q3 < nd { occn[q3] = 0; if dpd[q3] == rootpd { occn[q3] = 1 } q3 = q3 + 1 }
90 var e3: i64 = 0
91 while e3 < en {
92 var pi: i64 = 0 - 1
93 var ci: i64 = 0 - 1
94 var q4: i64 = 0
95 while q4 < nd {
96 if dpd[q4] == pe[e3] { pi = q4 }
97 if dpd[q4] == ce[e3] { ci = q4 }
98 q4 = q4 + 1
99 }
100 if pi >= 0 { if ci >= 0 { occn[ci] = occn[ci] + occ[pi] } }
101 e3 = e3 + 1
102 }
103 var q5: i64 = 0
104 while q5 < nd { occ[q5] = occn[q5]; q5 = q5 + 1 }
105 pass = pass + 1
106 }
107 var leafinst: i64 = 0
108 var q6: i64 = 0
109 while q6 < nd {
110 var hasout: i64 = 0
111 var e4: i64 = 0
112 while e4 < en { if pe[e4] == dpd[q6] { hasout = 1 } e4 = e4 + 1 }
113 if hasout == 0 { leafinst = leafinst + occ[q6] }
114 q6 = q6 + 1
115 }
116 sp_puts("independent expanded leaf instances=" as *u8); sp_putn(leafinst); sp_puts("\n" as *u8)
117
118 // ---- build the 3D scene by DFS (part per leaf instance; stand-in geometry by product name) ----
119 let e: *i64 = sys_mmap(256) as *i64
120 let lverts: *i64 = sys_mmap(131072) as *i64
121 let wverts: *i64 = sys_mmap(131072) as *i64
122 let idx: *i64 = sys_mmap(196608) as *i64
123 let home: *i64 = sys_mmap(2048) as *i64
124 let dir: *i64 = sys_mmap(2048) as *i64
125 let dep: *i64 = sys_mmap(1024) as *i64
126 let vst: *i64 = sys_mmap(1024) as *i64
127 let vct: *i64 = sys_mmap(1024) as *i64
128 let exsc: *i64 = sys_mmap(16) as *i64
129 let ig1: i64 = ex3_init(e, lverts, idx, home, dir, dep, vst, vct, 4096, 8192, 64, exsc)
130
131 // colors: packed (a<<24 | b<<16 | g<<8 | r)
132 let C_GOLD: i64 = 4280860390 // nut r230 g190 b40
133 let C_RED: i64 = 4280824550 // bolt r230 g50 b40
134 let C_GRN: i64 = 4284139580 // rod r60 g200 b90
135 let C_GRY: i64 = 4288714390 // plate r150 g150 b160
136 let C_BLU: i64 = 4293294150 // l-bracket r70 g120 b230
137 let C_WHT: i64 = 4292006610 // default r210 g210 b210
138 let BG: i64 = 4280293912 // background r24 g26 b32
139
140 let s_pd: *i64 = sys_mmap(2048) as *i64
141 let s_dep: *i64 = sys_mmap(2048) as *i64
142 let s_x: *i64 = sys_mmap(2048) as *i64
143 let s_y: *i64 = sys_mmap(2048) as *i64
144 let s_z: *i64 = sys_mmap(2048) as *i64
145 let s_px: *i64 = sys_mmap(2048) as *i64
146 let s_py: *i64 = sys_mmap(2048) as *i64
147 let s_pz: *i64 = sys_mmap(2048) as *i64
148 let out2: *i64 = sys_mmap(16) as *i64
149 var sp2: i64 = 0
150 if rootpd >= 0 {
151 s_pd[0] = rootpd; s_dep[0] = 0
152 s_x[0] = 0; s_y[0] = 2200; s_z[0] = 0
153 s_px[0] = 0; s_py[0] = 0; s_pz[0] = 0
154 sp2 = 1
155 }
156 var overflow: i64 = 0
157 while sp2 > 0 {
158 sp2 = sp2 - 1
159 let pd: i64 = s_pd[sp2]
160 let d: i64 = s_dep[sp2]
161 let px: i64 = s_x[sp2]
162 let py: i64 = s_y[sp2]
163 let pz: i64 = s_z[sp2]
164 let ppx: i64 = s_px[sp2]
165 let ppy: i64 = s_py[sp2]
166 let ppz: i64 = s_pz[sp2]
167 var haschild: i64 = 0
168 var k: i64 = 0
169 var e5: i64 = 0
170 while e5 < en {
171 if pe[e5] == pd {
172 haschild = 1
173 let cd: i64 = d + 1
174 let ig2: i64 = ex3_oct(k, out2)
175 let r: i64 = ex3_rad(cd)
176 let cx: i64 = px + (out2[0] * r) / 16384
177 let cz: i64 = pz + (out2[1] * r) / 16384
178 let cy: i64 = py + ex3_dyv(cd)
179 if sp2 < 250 {
180 s_pd[sp2] = ce[e5]; s_dep[sp2] = cd
181 s_x[sp2] = cx; s_y[sp2] = cy; s_z[sp2] = cz
182 s_px[sp2] = px; s_py[sp2] = py; s_pz[sp2] = pz
183 sp2 = sp2 + 1
184 } else { overflow = 1 }
185 k = k + 1
186 }
187 e5 = e5 + 1
188 }
189 if haschild == 0 {
190 // LEAF instance -> a real 3D part; explode dir = radial from its parent's centroid
191 let prodi: i64 = sp_pd_product(st, pd)
192 let pidx: i64 = ex3_part_begin(e, px, py, pz, px - ppx, py - ppy, pz - ppz, d)
193 var done: i64 = 0
194 if prodi >= 0 {
195 let isnut: i64 = sp_prod_name_is(st, prodi, "nut" as *u8)
196 if isnut == 1 { let g1: i64 = ex3_add_prism(e, px, py, pz, 900, 420, 0, C_GOLD); done = 1 }
197 if done == 0 {
198 let isbolt: i64 = sp_prod_name_is(st, prodi, "bolt" as *u8)
199 if isbolt == 1 { let g2: i64 = ex3_add_prism(e, px, py, pz, 520, 1300, 0, C_RED); done = 1 }
200 }
201 if done == 0 {
202 let isrod: i64 = sp_prod_name_is(st, prodi, "rod" as *u8)
203 if isrod == 1 { let g3: i64 = ex3_add_prism(e, px, py, pz, 460, 3400, 1, C_GRN); done = 1 }
204 }
205 if done == 0 {
206 let isplate: i64 = sp_prod_name_is(st, prodi, "plate" as *u8)
207 if isplate == 1 { let g4: i64 = ex3_add_box(e, px, py, pz, 4400, 300, 2800, C_GRY); done = 1 }
208 }
209 if done == 0 {
210 let islb: i64 = sp_prod_name_is(st, prodi, "l-bracket" as *u8)
211 if islb == 1 { let g5: i64 = ex3_add_box(e, px, py, pz, 1000, 2000, 800, C_BLU); done = 1 }
212 }
213 }
214 if done == 0 { let g6: i64 = ex3_add_box(e, px, py, pz, 900, 900, 900, C_WHT) }
215 }
216 }
217 sp_puts("scene parts=" as *u8); sp_putn(e[4])
218 sp_puts(" verts=" as *u8); sp_putn(e[1])
219 sp_puts(" tris=" as *u8); sp_putn(e[3])
220 sp_puts(" overflow=" as *u8); sp_putn(overflow); sp_puts("\n" as *u8)
221
222 var t1: i64 = 0
223 if e[4] == leafinst { if e[4] >= 10 { if overflow == 0 { t1 = 1 } } }
224 let ig3: i64 = xg_tooth("T1 DFS parts == independent occurrence expansion (>=10)" as *u8, t1, fails)
225
226 // T2 monotonic explode spread
227 let m0: i64 = ex3_mean_pairdist(e, 0)
228 let m1: i64 = ex3_mean_pairdist(e, 256)
229 let m2: i64 = ex3_mean_pairdist(e, 512)
230 let m3: i64 = ex3_mean_pairdist(e, 768)
231 let m4: i64 = ex3_mean_pairdist(e, 1024)
232 sp_puts("mean pair distance t=0/256/512/768/1024: " as *u8)
233 sp_putn(m0); sp_puts(" " as *u8); sp_putn(m1); sp_puts(" " as *u8); sp_putn(m2); sp_puts(" " as *u8); sp_putn(m3); sp_puts(" " as *u8); sp_putn(m4); sp_puts("\n" as *u8)
234 var t2: i64 = 0
235 if m0 < m1 { if m1 < m2 { if m2 < m3 { if m3 < m4 { t2 = 1 } } } }
236 let ig4: i64 = xg_tooth("T2 spread strictly monotonic in t" as *u8, t2, fails)
237
238 var t3: i64 = 0
239 if m4 >= 2 * m0 { t3 = 1 }
240 let ig5: i64 = xg_tooth("T3 exploded spread >= 2x assembled" as *u8, t3, fails)
241
242 // T4 pose determinism
243 let ig6: i64 = ex3_pose(e, 512, wverts)
244 let ck1: i64 = xg_chk(wverts, e[1] * 4)
245 let ig7: i64 = ex3_pose(e, 0, wverts)
246 let ig8: i64 = ex3_pose(e, 512, wverts)
247 let ck2: i64 = xg_chk(wverts, e[1] * 4)
248 var t4: i64 = 0
249 if ck1 == ck2 { t4 = 1 }
250 let ig9: i64 = xg_tooth("T4 pose(t) deterministic (same t -> same bytes)" as *u8, t4, fails)
251
252 // T5 staged depth: deeper parts travel further at full explode
253 let d1: i64 = ex3_mean_disp_at_depth(e, 1024, 1)
254 let d3: i64 = ex3_mean_disp_at_depth(e, 1024, 3)
255 sp_puts("mean displacement depth1=" as *u8); sp_putn(d1); sp_puts(" depth3=" as *u8); sp_putn(d3); sp_puts("\n" as *u8)
256 var t5: i64 = 0
257 if d3 > d1 { if d1 > 0 { t5 = 1 } }
258 let ig10: i64 = xg_tooth("T5 staged: depth-3 travels further than depth-1" as *u8, t5, fails)
259
260 // T6+T7 render 16-frame assemble<->explode loop -> APNG
261 let W: i64 = 256
262 let H: i64 = 192
263 let N: i64 = W * H
264 let fb: *i64 = sys_mmap(N * 8) as *i64
265 let zb: *i64 = sys_mmap(N * 8) as *i64
266 let proj: *i64 = sys_mmap(128) as *i64
267 let roty: *i64 = sys_mmap(128) as *i64
268 let mv: *i64 = sys_mmap(128) as *i64
269 let trans: *i64 = sys_mmap(128) as *i64
270 let mvp: *i64 = sys_mmap(128) as *i64
271 let vbuf: *i64 = sys_mmap(64) as *i64
272 let clipbuf: *i64 = sys_mmap(64) as *i64
273 let scr: *i64 = sys_mmap(131072) as *i64 // PER-VERTEX: nverts*4 i64 (192B was a latent under-size, masked by page rounding)
274 let tribuf: *i64 = sys_mmap(128) as *i64
275 let ap: *u8 = sys_mmap(16777216)
276 let seq: *i64 = sys_mmap(8) as *i64
277 seq[0] = 0
278 var o: i64 = apng_open(ap, W, H, 16)
279 var cov0: i64 = 0
280 var cov7: i64 = 0
281 var chA: i64 = 0
282 var chB: i64 = 0
283 var fr: i64 = 0
284 while fr < 16 {
285 var t: i64 = 0
286 if fr < 8 { t = fr * 146 } else { t = (15 - fr) * 146 }
287 let igp: i64 = ex3_pose(e, t, wverts)
288 let drawn: i64 = mr_render(wverts, e[1], idx, e[3], proj, roty, mv, trans, mvp, vbuf, clipbuf, scr, tribuf, fb, zb, W, H, 28, 40000, 30, BG)
289 let cv: i64 = xg_cover(fb, N, BG)
290 if fr == 0 { cov0 = cv; chA = xg_chk(fb, N) }
291 if fr == 7 { cov7 = cv; chB = xg_chk(fb, N) }
292 var first: i64 = 0
293 if fr == 0 { first = 1 }
294 o = apng_frame(ap, o, seq, fb, W, H, 12, first)
295 fr = fr + 1
296 }
297 o = apng_close(ap, o)
298 sp_puts("coverage assembled=" as *u8); sp_putn(cov0); sp_puts(" exploded=" as *u8); sp_putn(cov7); sp_puts("\n" as *u8)
299 var t6: i64 = 0
300 if cov0 > 200 { if cov7 > 200 { if chA != chB { t6 = 1 } } }
301 let ig11: i64 = xg_tooth("T6 frames non-vacuous + assembled != exploded" as *u8, t6, fails)
302
303 let fd: i64 = sys_openat_wr("knowledge/nx_explode_as1.apng" as *u8, 0x1a4)
304 var t7: i64 = 0
305 if fd >= 0 {
306 sys_write(fd, ap, o)
307 sys_close(fd)
308 if o > 2000 { if ap[1] == (80 as u8) { t7 = 1 } }
309 }
310 sp_puts("APNG bytes=" as *u8); sp_putn(o); sp_puts(" -> knowledge/nx_explode_as1.apng\n" as *u8)
311 let ig12: i64 = xg_tooth("T7 animated explode APNG written" as *u8, t7, fails)
312
313 sp_puts("\nfails=" as *u8); sp_putn(fails[0]); sp_puts("\n" as *u8)
314 if fails[0] == 0 { sp_puts("GREEN -- 3D staged explode of the REAL as1 STEP tree, 7/7 (geometry = R1b stand-ins, stated)\n" as *u8); return 0 }
315 sp_puts("RED\n" as *u8)
316 return 1
317}