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}