nx_dcc_to_print_test.nx source
↩ module page · 108 lines · 5244 B
1// nx_dcc_to_print_test.nx -- DCC->PRINT CAPSTONE on AUTHORED, SCULPTED geometry.
2//
3// The cube capstone proved a hardcoded cube prints. This proves the WHOLE DCC
4// toolchain feeds the real pipeline: an icosphere built from an octahedron
5// (nx_mesh_sculpt) is SCULPTED with an inflate brush (a north-pole bump), placed
6// on the bed with the translate verb (nx_mesh_edit), exported with the GENERAL
7// writer (nx_stl_write_mesh), then run through the EXISTING reader + QIDI slicer +
8// G-code emitter -- supports auto-generated for the spherical overhangs. Every
9// geometry op is sovereign + gate-proven; the downstream fabrication stack is all
10// reused. model(sculpted) -> print, end to end. expect_exit: 0.
11
12import "nx_syscalls.nx"
13import "nx_mesh.nx"
14import "nx_mesh_edit.nx"
15import "nx_mesh_sculpt.nx"
16import "nx_stl_write.nx"
17import "nx_stl.nx"
18import "nx_machine_graph.nx"
19import "nx_material_profile.nx"
20import "nx_gcode_emit.nx"
21import "nx_slice_pipeline.nx"
22
23func w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
24func wn(v: i64) -> i64 {
25 let b: *u8 = sys_mmap(28); var m: i64 = v
26 if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) }
27 let t: *u8 = sys_mmap(28); var k: i64 = 0
28 if m == 0 { t[0] = 48 as u8; k = 1 }
29 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
30 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 }
31 sys_write(1, b, k); return 0
32}
33func smoke_count(buf: *u8, len: i64, needle: *u8) -> i64 {
34 var nlen: i64 = 0; while needle[nlen] != 0 { nlen = nlen + 1 }
35 if len < nlen { return 0 }
36 var count: i64 = 0; var i: i64 = 0; let last: i64 = len - nlen
37 while i <= last {
38 var j: i64 = 0; var matched: i64 = 1
39 while j < nlen { if buf[i + j] != needle[j] { matched = 0; j = nlen } j = j + 1 }
40 if matched == 1 { count = count + 1 }
41 i = i + 1
42 }
43 return count
44}
45func chk(cond: i64, pass: *i64, fail: *i64, label: *u8) -> i64 {
46 if cond == 1 { pass[0] = pass[0] + 1; w(" ok " as *u8); w(label); w("\n" as *u8) }
47 else { fail[0] = fail[0] + 1; w(" XX " as *u8); w(label); w("\n" as *u8) }
48 return 0
49}
50func eqi(a: i64, b: i64) -> i64 { if a == b { return 1 } return 0 }
51
52func main() -> i64 {
53 let pass: *i64 = (sys_mmap(8)) as *i64
54 let fail: *i64 = (sys_mmap(8)) as *i64
55 pass[0] = 0
56 fail[0] = 0
57 let bb: *i64 = (sys_mmap(48)) as *i64
58 w("=== DCC->print: sculpted icosphere -> existing QIDI slicer -> G-code ===\n" as *u8)
59
60 // 1. AUTHOR in our Blender/ZBrush-class tools: icosphere + inflate brush
61 let model: *NxMesh = nx_mesh_make_icosphere(163840, 2, 0) // 10mm radius, subdiv 2
62 nx_mesh_sculpt_brush(model, 0, 0, 163840, 81920, 32768) // +2mm bump at north pole
63 chk(eqi(model.n_tris, 128), pass, fail, "authored sculpted mesh: 128 tris" as *u8)
64
65 // 2. PLACE on the bed with the translate verb (corner -> origin, z>=0)
66 nx_mesh_aabb(model, bb)
67 nx_mesh_translate(model, 0 - bb[0], 0 - bb[1], 0 - bb[2])
68 nx_mesh_aabb(model, bb)
69 chk(eqi(bb[2], 0), pass, fail, "model sits on bed (min_z = 0)" as *u8)
70 let height_mm: i64 = bb[5] / 16384
71 w(" model z-height(mm)=" as *u8); wn(height_mm); w("\n" as *u8)
72
73 // 3. EXPORT with the general writer
74 let stl: *u8 = sys_mmap(16384)
75 let n: i64 = nx_stl_write_mesh(stl, model)
76 chk(eqi(n, 84 + 50 * 128), pass, fail, "STL written (84 + 50*128 = 6484 B)" as *u8)
77
78 // 4. EXISTING reader
79 let r: *NxStlResult = nx_stl_load_binary(stl, n)
80 chk(eqi(r.verdict, NX_STL_OK), pass, fail, "existing reader OK on sculpted STL" as *u8)
81 chk(eqi(r.n_tris_header, 128), pass, fail, "reader sees 128 triangles" as *u8)
82 let mesh: *NxMesh = r.mesh
83
84 // 5. EXISTING QIDI slicer -> G-code (supports auto-built for overhangs)
85 let qidi: *NxMachineGraph = nx_machine_graph_qidi_xmax3()
86 let pla: *NxMaterialProfile = nx_material_profile_generic_pla()
87 let lh: i64 = 3277 // 0.2mm layer
88 let lw: i64 = 6554 // 0.4mm width
89 let e: *NxGcodeEmitter = nx_gemit_new(qidi, pla, lh, lw, 4194304)
90 chk((e as i64) != 0, pass, fail, "gcode emitter created" as *u8)
91 nx_gemit_preamble(e)
92 let n_layers: i64 = nx_slice_pipe_run_v2(e, mesh, 20, lh) // 20% infill
93 let n_g1: i64 = smoke_count(e.buf, e.len, "G1 X" as *u8)
94 w(" layers=" as *u8); wn(n_layers)
95 w(" gcode_bytes=" as *u8); wn(e.len); w(" G1_moves=" as *u8); wn(n_g1); w("\n" as *u8)
96
97 // 6. real G-code assertions (~22mm @0.2mm ~ 110 layers)
98 chk(n_layers >= 50, pass, fail, "sliced >= 50 layers" as *u8)
99 chk(n_layers <= 250, pass, fail, "layer count sane (<=250)" as *u8)
100 chk(smoke_count(e.buf, e.len, "M104 S" as *u8) >= 1, pass, fail, "hotend heat command present" as *u8)
101 chk(smoke_count(e.buf, e.len, "M84" as *u8) >= 1, pass, fail, "motors-off at end present" as *u8)
102 chk(n_g1 >= 100, pass, fail, "many G1 extrusion moves" as *u8)
103 chk(e.len >= 10000, pass, fail, "substantial real G-code emitted" as *u8)
104
105 w("=== VERDICT pass=" as *u8); wn(pass[0]); w(" fail=" as *u8); wn(fail[0]); w(" ===\n" as *u8)
106 if fail[0] == 0 { return 0 }
107 return 1
108}