code wiki / (root) / nx_stl_write_mesh_test.nx

nx_stl_write_mesh_test.nx source

↩ module page · 91 lines · 4264 B

1// nx_stl_write_mesh_test.nx -- KAT gate: the GENERAL mesh exporter writes an 2// ARBITRARY NxMesh to binary STL that the existing reader/slicer pipeline accepts. 3// Proves (a) cube parity with the hardcoded writer, (b) Q14->f32->Q14 units survive 4// EXACTLY end-to-end (10mm corner comes back as 163840 Q14), (c) a NON-cube mesh 5// (quad) also round-trips -> the seam is general, not cube-special. expect_exit: 0. 6 7import "nx_syscalls.nx" 8import "nx_le.nx" 9import "nx_f32_encode.nx" 10import "nx_mesh.nx" 11import "nx_stl_write.nx" 12import "nx_stl.nx" 13 14func w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 15func wn(v: i64) -> i64 { 16 let b: *u8 = sys_mmap(28); var m: i64 = v 17 if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) } 18 let t: *u8 = sys_mmap(28); var k: i64 = 0 19 if m == 0 { t[0] = 48 as u8; k = 1 } 20 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 21 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 } 22 sys_write(1, b, k); return 0 23} 24func chk(cond: i64, pass: *i64, fail: *i64, label: *u8) -> i64 { 25 if cond == 1 { pass[0] = pass[0] + 1; w(" ok " as *u8); w(label); w("\n" as *u8) } 26 else { fail[0] = fail[0] + 1; w(" XX " as *u8); w(label); w("\n" as *u8) } 27 return 0 28} 29func eqi(a: i64, b: i64) -> i64 { if a == b { return 1 } return 0 } 30 31func max_abs_coord(m: *NxMesh) -> i64 { 32 var mx: i64 = 0 33 var i: i64 = 0 34 while i < m.n_verts { 35 var ax: i64 = nx_mesh_get_vertex_x(m, i); if ax < 0 { ax = 0 - ax } 36 var ay: i64 = nx_mesh_get_vertex_y(m, i); if ay < 0 { ay = 0 - ay } 37 var az: i64 = nx_mesh_get_vertex_z(m, i); if az < 0 { az = 0 - az } 38 if ax > mx { mx = ax } 39 if ay > mx { mx = ay } 40 if az > mx { mx = az } 41 i = i + 1 42 } 43 return mx 44} 45 46func main() -> i64 { 47 let pass: *i64 = (sys_mmap(8)) as *i64 48 let fail: *i64 = (sys_mmap(8)) as *i64 49 pass[0] = 0 50 fail[0] = 0 51 w("=== nx_stl_write_mesh KAT (general NxMesh -> STL -> existing reader) ===\n" as *u8) 52 53 // --- CUBE via the mesh factory: half-extent 10mm (163840 Q14) -> 20mm cube --- 54 let cube: *NxMesh = nx_mesh_make_cube(163840, 0) 55 chk(eqi(cube.n_verts, 8), pass, fail, "factory cube has 8 verts" as *u8) 56 chk(eqi(cube.n_tris, 12), pass, fail, "factory cube has 12 tris" as *u8) 57 58 let buf: *u8 = sys_mmap(4096) 59 let n: i64 = nx_stl_write_mesh(buf, cube) 60 w(" wrote bytes=" as *u8); wn(n); w("\n" as *u8) 61 chk(eqi(n, 684), pass, fail, "cube STL size = 84 + 50*12 = 684" as *u8) 62 chk(eqi(nx_le_read_u32(buf, 80), 12), pass, fail, "header n_tris field = 12" as *u8) 63 64 // round-trip through the EXISTING reader the slicer uses 65 let r: *NxStlResult = nx_stl_load_binary(buf, n) 66 w(" reader verdict=" as *u8); wn(r.verdict) 67 w(" n_tris=" as *u8); wn(r.n_tris_header) 68 w(" uniq=" as *u8); wn(r.n_verts_unique); w("\n" as *u8) 69 chk(eqi(r.verdict, NX_STL_OK), pass, fail, "existing reader ACCEPTS general-writer STL" as *u8) 70 chk(eqi(r.n_tris_header, 12), pass, fail, "reader sees 12 triangles" as *u8) 71 chk(eqi(r.n_verts_unique, 8), pass, fail, "reader dedups 36 corners -> 8 (valid topology)" as *u8) 72 73 // UNITS PROOF: a 10mm corner must come back as 163840 Q14 EXACTLY 74 let mx: i64 = max_abs_coord(r.mesh) 75 w(" max|coord| Q14=" as *u8); wn(mx); w(" (10mm == 163840)\n" as *u8) 76 chk(eqi(mx, 163840), pass, fail, "Q14->f32->Q14 EXACT: 10mm survives as 163840" as *u8) 77 78 // --- NON-CUBE: a flat quad (4 verts, 2 tris) proves it is not cube-special --- 79 let quad: *NxMesh = nx_mesh_make_quad(0, 0, 163840, 163840, 0) 80 let buf2: *u8 = sys_mmap(1024) 81 let n2: i64 = nx_stl_write_mesh(buf2, quad) 82 chk(eqi(n2, 184), pass, fail, "quad STL size = 84 + 50*2 = 184" as *u8) 83 let r2: *NxStlResult = nx_stl_load_binary(buf2, n2) 84 chk(eqi(r2.verdict, NX_STL_OK), pass, fail, "reader accepts arbitrary (quad) mesh" as *u8) 85 chk(eqi(r2.n_tris_header, 2), pass, fail, "reader sees 2 triangles" as *u8) 86 chk(eqi(r2.n_verts_unique, 4), pass, fail, "quad dedups to 4 corners" as *u8) 87 88 w("=== VERDICT pass=" as *u8); wn(pass[0]); w(" fail=" as *u8); wn(fail[0]); w(" ===\n" as *u8) 89 if fail[0] == 0 { return 0 } 90 return 1 91}