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}