code wiki / (root) / nx_mesh_edit_test.nx

nx_mesh_edit_test.nx source

↩ module page · 82 lines · 4133 B

1// nx_mesh_edit_test.nx -- KAT gate for the DCC modeling verbs. Closed-form 2// invariants only (no external oracle needed -- these are exact integer ops): 3// translate shifts the AABB, scale shrinks it, subdivide quadruples triangles 4// while preserving the AABB + validity, pyramid factory has the right counts + 5// extent. expect_exit: 0. 6 7import "nx_syscalls.nx" 8import "nx_mesh.nx" 9import "nx_mesh_edit.nx" 10 11func w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 12func wn(v: i64) -> i64 { 13 let b: *u8 = sys_mmap(28); var m: i64 = v 14 if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) } 15 let t: *u8 = sys_mmap(28); var k: i64 = 0 16 if m == 0 { t[0] = 48 as u8; k = 1 } 17 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 18 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 } 19 sys_write(1, b, k); return 0 20} 21func chk(cond: i64, pass: *i64, fail: *i64, label: *u8) -> i64 { 22 if cond == 1 { pass[0] = pass[0] + 1; w(" ok " as *u8); w(label); w("\n" as *u8) } 23 else { fail[0] = fail[0] + 1; w(" XX " as *u8); w(label); w("\n" as *u8) } 24 return 0 25} 26func eqi(a: i64, b: i64) -> i64 { if a == b { return 1 } return 0 } 27 28func main() -> i64 { 29 let pass: *i64 = (sys_mmap(8)) as *i64 30 let fail: *i64 = (sys_mmap(8)) as *i64 31 pass[0] = 0 32 fail[0] = 0 33 let bb: *i64 = (sys_mmap(48)) as *i64 34 w("=== nx_mesh_edit KAT (Blender-class modeling verbs) ===\n" as *u8) 35 36 // --- TRANSLATE: cube +/-163840, shift +163840 in x -> x in [0, 327680] --- 37 let c1: *NxMesh = nx_mesh_make_cube(163840, 0) 38 nx_mesh_aabb(c1, bb) 39 chk(eqi(bb[0], 0 - 163840), pass, fail, "cube min_x = -10mm before translate" as *u8) 40 nx_mesh_translate(c1, 163840, 0, 0) 41 nx_mesh_aabb(c1, bb) 42 chk(eqi(bb[0], 0), pass, fail, "after +10mm x: min_x = 0" as *u8) 43 chk(eqi(bb[3], 327680), pass, fail, "after +10mm x: max_x = 20mm" as *u8) 44 chk(eqi(bb[1], 0 - 163840), pass, fail, "y untouched by x-translate" as *u8) 45 46 // --- SCALE: fresh cube, scale by 1/2 -> +/-81920 --- 47 let c2: *NxMesh = nx_mesh_make_cube(163840, 0) 48 nx_mesh_scale_rat(c2, 1, 2) 49 nx_mesh_aabb(c2, bb) 50 chk(eqi(bb[3], 81920), pass, fail, "scale 1/2: max_x = 5mm" as *u8) 51 chk(eqi(bb[0], 0 - 81920), pass, fail, "scale 1/2: min_x = -5mm" as *u8) 52 chk(eqi(nx_mesh_validate(c2), NX_MESH_OK), pass, fail, "scaled cube still valid" as *u8) 53 54 // --- SUBDIVIDE: cube 8v/12t -> 44v/48t, AABB preserved, valid --- 55 let c3: *NxMesh = nx_mesh_make_cube(163840, 0) 56 let s3: *NxMesh = nx_mesh_subdivide(c3) 57 w(" subdiv cube: verts=" as *u8); wn(s3.n_verts); w(" tris=" as *u8); wn(s3.n_tris); w("\n" as *u8) 58 chk(eqi(s3.n_tris, 48), pass, fail, "subdivide quadruples tris (12 -> 48)" as *u8) 59 chk(eqi(s3.n_verts, 44), pass, fail, "subdivide verts = 8 + 12*3 = 44" as *u8) 60 chk(eqi(nx_mesh_validate(s3), NX_MESH_OK), pass, fail, "subdivided mesh valid (indices in range)" as *u8) 61 nx_mesh_aabb(s3, bb) 62 chk(eqi(bb[3], 163840), pass, fail, "subdivide preserves AABB (max_x still 10mm)" as *u8) 63 chk(eqi(bb[0], 0 - 163840), pass, fail, "subdivide preserves AABB (min_x still -10mm)" as *u8) 64 65 // --- PYRAMID: 5v/6t, apex at z=20mm, base +/-10mm --- 66 let p: *NxMesh = nx_mesh_make_pyramid(163840, 327680, 0) 67 chk(eqi(p.n_verts, 5), pass, fail, "pyramid has 5 verts" as *u8) 68 chk(eqi(p.n_tris, 6), pass, fail, "pyramid has 6 tris" as *u8) 69 chk(eqi(nx_mesh_validate(p), NX_MESH_OK), pass, fail, "pyramid valid" as *u8) 70 nx_mesh_aabb(p, bb) 71 chk(eqi(bb[2], 0), pass, fail, "pyramid base at z=0" as *u8) 72 chk(eqi(bb[5], 327680), pass, fail, "pyramid apex at z=20mm" as *u8) 73 74 // --- SUBDIVIDE PYRAMID: 6t -> 24t, 5+18=23 verts --- 75 let sp: *NxMesh = nx_mesh_subdivide(p) 76 chk(eqi(sp.n_tris, 24), pass, fail, "subdivided pyramid 6 -> 24 tris" as *u8) 77 chk(eqi(sp.n_verts, 23), pass, fail, "subdivided pyramid 5 + 6*3 = 23 verts" as *u8) 78 79 w("=== VERDICT pass=" as *u8); wn(pass[0]); w(" fail=" as *u8); wn(fail[0]); w(" ===\n" as *u8) 80 if fail[0] == 0 { return 0 } 81 return 1 82}