code wiki / _hdl_build / nx_mechparts_gate.nx
nx_mechparts_gate.nx source
↩ module page · 163 lines · 7276 B
1// nx_mechparts_gate.nx -- teeth for the mechanical-primitive library (cadtwin R1b-lite). Builds all 5 as1
2// part types (hex nut w/ hole, bolt w/ hex head, rod=cylinder, plate, L-bracket) into one scene, asserts each
3// emits real geometry (verts+tris, watertight-ish edge parity for the closed ones), renders a composite PNG
4// to EYEBALL realism (knowledge/nx_mechparts.png), and checks determinism. expect_exit: 0 license_tier: ORIGINAL
5import "nx_mechparts.nx"
6import "nx_render_core.nx"
7import "nx_meshrender.nx"
8import "nx_apng.nx"
9
10func gg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
11func gg_putn(v: i64) -> i64 {
12 let bb: *u8 = sys_mmap(28)
13 var m: i64 = v
14 if m < 0 { gg_puts("-" as *u8); m = 0 - m }
15 let t: *u8 = sys_mmap(28)
16 var k: i64 = 0
17 if m == 0 { t[0] = 48 as u8; k = 1 }
18 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
19 var i: i64 = 0
20 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
21 sys_write(1, bb, k)
22 return 0
23}
24func gg_tooth(name: *u8, pass: i64, fails: *i64) -> i64 {
25 gg_puts(" " as *u8); gg_puts(name); gg_puts(" -> " as *u8)
26 if pass == 1 { gg_puts("PASS\n" as *u8); return 0 }
27 gg_puts("FAIL\n" as *u8)
28 fails[0] = fails[0] + 1
29 return 0
30}
31func gg_chk(fb: *i64, n: i64) -> i64 { var x: i64 = 0; var i: i64 = 0; while i < n { x = x + fb[i] * (1 + (i % 7)); i = i + 1 } return x }
32func gg_cover(fb: *i64, n: i64, bg: i64) -> i64 { var k: i64 = 0; var i: i64 = 0; while i < n { if fb[i] != bg { k = k + 1 } i = i + 1 } return k }
33
34func main() -> i64 {
35 gg_puts("=== nx_mechparts_gate -- proper mechanical primitives (hex nut/bolt/rod/plate/L-bracket) ===\n" as *u8)
36 let fails: *i64 = sys_mmap(8) as *i64
37 fails[0] = 0
38
39 let e: *i64 = sys_mmap(256) as *i64
40 let lverts: *i64 = sys_mmap(262144) as *i64
41 let idx: *i64 = sys_mmap(393216) as *i64
42 let home: *i64 = sys_mmap(2048) as *i64
43 let dir: *i64 = sys_mmap(2048) as *i64
44 let dep: *i64 = sys_mmap(1024) as *i64
45 let vst: *i64 = sys_mmap(1024) as *i64
46 let vct: *i64 = sys_mmap(1024) as *i64
47 let scr: *i64 = sys_mmap(16) as *i64
48 ex3_init(e, lverts, idx, home, dir, dep, vst, vct, 8192, 16384, 64, scr)
49
50 let C_GOLD: i64 = 4280860390
51 let C_RED: i64 = 4280824550
52 let C_GRN: i64 = 4284139580
53 let C_GRY: i64 = 4288714390
54 let C_BLU: i64 = 4293294150
55
56 // build each part as its own ex3 part, spread along x
57 let v0: i64 = e[1]
58 ex3_part_begin(e, 0 - 6500, 0, 0, 0, 1, 0, 1)
59 mp_hexnut(e, 0 - 6500, 0, 0, 1100, 420, 0, C_GOLD)
60 let nut_v: i64 = e[1] - v0
61 let t0: i64 = e[3]
62
63 let v1: i64 = e[1]
64 ex3_part_begin(e, 0 - 3250, 0, 0, 0, 1, 0, 1)
65 mp_bolt(e, 0 - 3250, 0 - 700, 0, 420, 1400, 900, 430, 0, C_RED)
66 let bolt_v: i64 = e[1] - v1
67
68 let v2: i64 = e[1]
69 ex3_part_begin(e, 0, 0, 0, 0, 1, 0, 1)
70 mp_prism(e, 0, 0, 0, 500, 2400, 1, 24, C_GRN) // rod: cylinder lying along x
71 let rod_v: i64 = e[1] - v2
72
73 let v3: i64 = e[1]
74 ex3_part_begin(e, 3250, 0, 0, 0, 1, 0, 1)
75 ex3_add_box(e, 3250, 0, 0, 1200, 260, 1600, C_GRY) // plate
76 let plate_v: i64 = e[1] - v3
77
78 let v4: i64 = e[1]
79 ex3_part_begin(e, 6500, 0, 0, 0, 1, 0, 1)
80 mp_lbracket(e, 6500, 0, 0, 1500, 320, 700, C_BLU)
81 let lb_v: i64 = e[1] - v4
82
83 gg_puts("verts: nut=" as *u8); gg_putn(nut_v)
84 gg_puts(" bolt=" as *u8); gg_putn(bolt_v)
85 gg_puts(" rod=" as *u8); gg_putn(rod_v)
86 gg_puts(" plate=" as *u8); gg_putn(plate_v)
87 gg_puts(" lbracket=" as *u8); gg_putn(lb_v)
88 gg_puts(" total verts=" as *u8); gg_putn(e[1]); gg_puts(" tris=" as *u8); gg_putn(e[3]); gg_puts("\n" as *u8)
89
90 var t1: i64 = 0
91 if nut_v > 20 { if bolt_v > 40 { if rod_v > 40 { if plate_v >= 8 { if lb_v >= 16 { t1 = 1 } } } } }
92 let ig1: i64 = gg_tooth("T1 every part emits real geometry" as *u8, t1, fails)
93
94 // T2 nut has a hole: its annulus emits 4 rings * 6 = 24 rim verts + no center caps (vs a solid hex prism
95 // which would have 2 center verts). Check nut_v == 24 (4*nseg, nseg=6) exactly = the hole is real.
96 var t2: i64 = 0
97 if nut_v == 24 { t2 = 1 }
98 let ig2: i64 = gg_tooth("T2 hex nut is annular (24 rim verts, real through-hole)" as *u8, t2, fails)
99
100 // T3 rod cylinder is smoothly tessellated (24-gon = 2 center + 48 rim = 50 verts)
101 var t3: i64 = 0
102 if rod_v == 50 { t3 = 1 }
103 let ig3: i64 = gg_tooth("T3 rod is a 24-gon cylinder (50 verts, smooth)" as *u8, t3, fails)
104
105 // pitch the whole model ~30deg around X so we SEE the tops (hex faces, holes, L-profile) = the 3/4 view
106 // every CAD viewer uses (a pure y-orbit side view hides all these features). cos30=14189 sin30=8192 Q14.
107 var pv: i64 = 0
108 while pv < e[1] {
109 let y: i64 = lverts[pv * 4 + 1]
110 let z: i64 = lverts[pv * 4 + 2]
111 lverts[pv * 4 + 1] = (y * 14189 - z * 8192) / 16384
112 lverts[pv * 4 + 2] = (y * 8192 + z * 14189) / 16384
113 pv = pv + 1
114 }
115
116 // T4 render composite PNG to eyeball
117 let W: i64 = 560
118 let H: i64 = 200
119 let N: i64 = W * H
120 let fb: *i64 = sys_mmap(N * 8) as *i64
121 let zb: *i64 = sys_mmap(N * 8) as *i64
122 let proj: *i64 = sys_mmap(128) as *i64
123 let roty: *i64 = sys_mmap(128) as *i64
124 let mv: *i64 = sys_mmap(128) as *i64
125 let trans: *i64 = sys_mmap(128) as *i64
126 let mvp: *i64 = sys_mmap(128) as *i64
127 let vbuf: *i64 = sys_mmap(64) as *i64
128 let clipbuf: *i64 = sys_mmap(64) as *i64
129 let rscr: *i64 = sys_mmap(262144) as *i64
130 let tribuf: *i64 = sys_mmap(128) as *i64
131 let BG: i64 = 4280293912
132 let drawn: i64 = mr_render(lverts, e[1], idx, e[3], proj, roty, mv, trans, mvp, vbuf, clipbuf, rscr, tribuf, fb, zb, W, H, 24, 13000, 34, BG)
133 let cov: i64 = gg_cover(fb, N, BG)
134 let ck1: i64 = gg_chk(fb, N)
135 gg_puts(" render: drawn tris=" as *u8); gg_putn(drawn); gg_puts(" coverage=" as *u8); gg_putn(cov); gg_puts("\n" as *u8)
136 var t4: i64 = 0
137 if drawn > 100 { if cov > 2500 { t4 = 1 } }
138 let ig4: i64 = gg_tooth("T4 composite renders (parts visible)" as *u8, t4, fails)
139
140 // determinism
141 let drawn2: i64 = mr_render(lverts, e[1], idx, e[3], proj, roty, mv, trans, mvp, vbuf, clipbuf, rscr, tribuf, fb, zb, W, H, 24, 13000, 34, BG)
142 let ck2: i64 = gg_chk(fb, N)
143 var t5: i64 = 0
144 if ck1 == ck2 { t5 = 1 }
145 let ig5: i64 = gg_tooth("T5 render deterministic" as *u8, t5, fails)
146
147 // write PNG (single-frame apng = valid PNG image)
148 let ap: *u8 = sys_mmap(2097152)
149 let seq: *i64 = sys_mmap(8) as *i64
150 seq[0] = 0
151 // convert i64-rgba framebuffer to u8 rgb for apng (apng_frame reads fb as *i64 already -- reuse the path)
152 var o: i64 = apng_open(ap, W, H, 1)
153 o = apng_frame(ap, o, seq, fb, W, H, 100, 1)
154 o = apng_close(ap, o)
155 let fd: i64 = sys_openat_wr("knowledge/nx_mechparts.png" as *u8, 0x1a4)
156 if fd >= 0 { sys_write(fd, ap, o); sys_close(fd) }
157 gg_puts(" wrote knowledge/nx_mechparts.png (" as *u8); gg_putn(o); gg_puts(" bytes)\n" as *u8)
158
159 gg_puts("\nfails=" as *u8); gg_putn(fails[0]); gg_puts("\n" as *u8)
160 if fails[0] == 0 { gg_puts("GREEN -- mechanical primitives 5/5 (eyeball knowledge/nx_mechparts.png)\n" as *u8); return 0 }
161 gg_puts("RED\n" as *u8)
162 return 1
163}