code wiki / _hdl_build / nx_gltf_mesh_gate.nx
nx_gltf_mesh_gate.nx source
↩ module page · 103 lines · 6176 B
1// nx_gltf_mesh_gate.nx -- ★F6: export the meshed being as a standard .glb and SELF-VERIFY the bytes (parse the container
2// back: magic/version/lengths/chunk types), so we never ship a malformed asset. Also checks tm_ovf()==0 (the capacity-guard
3// debt fix). Writes knowledge/nishi_being.glb -- a real, universally-readable 3D model. license_tier: ORIGINAL expect_exit: 0
4import "nx_syscalls.nx"
5import "nx_trimesh.nx"
6import "nx_isosurf.nx"
7import "nx_bodyatlas.nx"
8import "nx_gltf_mesh.nx"
9
10func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
11func pn(v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 }
12func ru32(buf: *u8, at: i64) -> i64 { return (buf[at] as i64) + ((buf[at+1] as i64)<<8) + ((buf[at+2] as i64)<<16) + ((buf[at+3] as i64)<<24) }
13func b4(buf: *u8, at: i64, a: i64, b: i64, c: i64, d: i64) -> i64 { if (buf[at] as i64)!=a {return 0} if (buf[at+1] as i64)!=b {return 0} if (buf[at+2] as i64)!=c {return 0} if (buf[at+3] as i64)!=d {return 0} return 1 }
14func hasstr(buf: *u8, n: i64, needle: *u8) -> i64 {
15 var m: i64=0; while needle[m]!=(0 as u8){m=m+1}
16 var i: i64=0
17 while i+m<=n { var k: i64=0; while k<m { if buf[i+k]!=needle[k] {k=m+9} else {k=k+1} } if k==m {return 1} i=i+1 }
18 return 0
19}
20
21const GX: i64 = 32
22const GY: i64 = 110
23const GZ: i64 = 20
24const GC: i64 = 18
25const OX: i64 = 0-288
26const OY: i64 = 0-990
27const OZ: i64 = 0-180
28
29func main() -> i64 {
30 hw("=== nx_gltf_mesh_gate -- export the meshed being as .glb + self-verify the container ===\n" as *u8)
31 var fails: i64 = 0
32 atlas_build(0) // auto-syncs pose now (no manual atlas_sync_pose needed)
33 // mesh the skin
34 let grid: *i64 = sys_mmap((GX+1)*(GY+1)*(GZ+1)*8) as *i64
35 var i: i64 = 0
36 while i <= GX { var jj: i64=0; while jj <= GY { var k: i64=0; while k <= GZ { grid[(i*(GY+1)+jj)*(GZ+1)+k] = ba_sdf(OX+i*GC, OY+jj*GC, OZ+k*GC, 1); k=k+1 } jj=jj+1 } i=i+1 }
37 tm_reset()
38 surface_nets(grid, GX, GY, GZ, OX, OY, OZ, GC, 0, 216+172*256+152*65536)
39 // per-part vertex colours
40 let vp: *i64 = sys_mmap(24) as *i64
41 i = 0
42 let nv0: i64 = tm_nv()
43 while i < nv0 { tm_vpos(i, vp); let kk: i64 = ba_nearest(vp[0], vp[1], vp[2], 1); if kk>=0 { tm_vcol(i, ba_part_color(kk)) } else { tm_vcol(i, 216+172*256+152*65536) } i=i+1 }
44 let NV: i64 = tm_nv(); let NT: i64 = tm_nt()
45 hw(" mesh: verts="); pn(NV); hw(" tris="); pn(NT); hw(" overflow="); pn(tm_ovf()); hw("\n" as *u8)
46 // T0 debt-fix: no silent overflow
47 var t0: i64 = 0
48 if tm_ovf() == 0 { if NV > 1000 { t0 = 1 } }
49 if t0 == 1 { hw("T0 PASS mesh built within capacity (overflow guard clean)\n" as *u8) } else { fails=fails+1; hw("T0 FAIL overflow="); pn(tm_ovf()); hw("\n" as *u8) }
50
51 // export
52 let out: *u8 = sys_mmap(8388608)
53 let total: i64 = gltf_export(out)
54 hw(" glb bytes="); pn(total); hw("\n" as *u8)
55
56 // ---- SELF-VERIFY the GLB container ----
57 var t1: i64 = 0
58 if b4(out, 0, 103, 108, 84, 70) == 1 { t1 = 1 } // "glTF"
59 let ver: i64 = ru32(out, 4)
60 let hdrTotal: i64 = ru32(out, 8)
61 if ver != 2 { t1 = 0 }
62 if hdrTotal != total { t1 = 0 }
63 if t1 == 1 { hw("T1 PASS header: magic 'glTF', version 2, length "); pn(hdrTotal); hw(" == written\n" as *u8) } else { fails=fails+1; hw("T1 FAIL header ver="); pn(ver); hw(" hdrTotal="); pn(hdrTotal); hw("\n" as *u8) }
64
65 let jsonLen: i64 = ru32(out, 12)
66 var t2: i64 = 0
67 if b4(out, 16, 74, 83, 79, 78) == 1 { t2 = 1 } // "JSON"
68 let binLenPos: i64 = 20 + jsonLen
69 let binLen: i64 = ru32(out, binLenPos)
70 var t3: i64 = 0
71 if b4(out, binLenPos+4, 66, 73, 78, 0) == 1 { t3 = 1 } // "BIN\0"
72 // chunk arithmetic closes exactly
73 let sum: i64 = 12 + 8 + jsonLen + 8 + binLen
74 var t4: i64 = 0
75 if sum == total { t4 = 1 }
76 hw(" chunks: jsonPad="); pn(jsonLen); hw(" binLen="); pn(binLen); hw(" 12+8+json+8+bin="); pn(sum); hw("\n" as *u8)
77 if t2 == 1 { hw("T2 PASS JSON chunk type ok\n" as *u8) } else { fails=fails+1; hw("T2 FAIL\n" as *u8) }
78 if t3 == 1 { hw("T3 PASS BIN chunk type ok\n" as *u8) } else { fails=fails+1; hw("T3 FAIL\n" as *u8) }
79 if t4 == 1 { hw("T4 PASS chunk arithmetic closes (12+8+json+8+bin == total)\n" as *u8) } else { fails=fails+1; hw("T4 FAIL sum="); pn(sum); hw(" total="); pn(total); hw("\n" as *u8) }
80
81 // JSON references the expected attributes
82 var t5: i64 = 0
83 if hasstr(out, 20+jsonLen, "POSITION" as *u8) == 1 { if hasstr(out, 20+jsonLen, "COLOR_0" as *u8) == 1 { if hasstr(out, 20+jsonLen, "5126" as *u8) == 1 { t5 = 1 } } }
84 if t5 == 1 { hw("T5 PASS JSON declares POSITION + COLOR_0 + float component (5126)\n" as *u8) } else { fails=fails+1; hw("T5 FAIL\n" as *u8) }
85
86 // BIN size == the accessor byte math (NV*12 pos + NV*6 nrm [pad] + NV*4 col + NT*3*4 idx)
87 let expectPos: i64 = NV*12
88 let expectMin: i64 = NV*12 + NV*6 + NV*4 + NT*3*4 // lower bound (before alignment padding)
89 var t6: i64 = 0
90 if binLen >= expectMin { if binLen <= expectMin + 8 { t6 = 1 } } // within one alignment pad
91 if t6 == 1 { hw("T6 PASS BIN length matches the vertex/index byte math\n" as *u8) } else { fails=fails+1; hw("T6 FAIL binLen="); pn(binLen); hw(" expect~"); pn(expectMin); hw("\n" as *u8) }
92
93 // ---- write the .glb ----
94 let fd: i64 = sys_openat_wr("knowledge/nishi_being.glb\x00" as *u8, 0x1a4)
95 sys_write(fd, out, total)
96 sys_close(fd)
97 hw("wrote knowledge/nishi_being.glb ("); pn(total); hw(" bytes)\n" as *u8)
98
99 if fails == 0 { hw("GLTF-MESH-GATE GREEN -- the meshed being exports as a STANDARD .glb (POSITION+NORMAL+COLOR_0+indices, PBR, doubleSided), container self-verified byte-exact. F6 asset-IO rung. Opens in any glTF viewer. Residual: multi-mesh scene (all systems) + texture images.\n" as *u8); sys_exit(0); return 0 }
100 hw("GLTF-MESH-GATE RED fails="); pn(fails); hw("\n" as *u8)
101 sys_exit(1)
102 return 1
103}