code wiki / _hdl_build / nx_loop_subdiv_gate.nx
nx_loop_subdiv_gate.nx source
↩ module page · 87 lines · 4829 B
1// nx_loop_subdiv_gate.nx -- proves LOOP SUBDIVISION is a real SMOOTH-LIMIT scheme, not mere refinement.
2// An octahedron (R on each axis) is subdivided once by Loop AND once by linear midpoint (sd_subdivide). Loop
3// REPOSITIONS the poles to the smooth limit (5R/8, hand-exact); linear KEEPS them at R (same silhouette). The
4// neg-control is the linear scheme itself: max radius drops under Loop, stays put under linear = Loop smooths.
5// Converges over a 2nd level. Emits an STL artifact. license_tier: ORIGINAL expect_exit: 0
6import "nx_syscalls.nx"
7import "nx_loop_subdiv.nx"
8
9func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
10func 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 }
11
12// max squared radius over all vertices (avoids sqrt; exact integer)
13func maxsq(base: i64) -> i64 {
14 let h: *i64 = m3_hdr(base)
15 var mx: i64 = 0
16 var i: i64 = 0
17 while i < h[0] {
18 let v: *i64 = m3_vert(base, i)
19 let r: i64 = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]
20 if r > mx { mx = r }
21 i = i + 1
22 }
23 return mx
24}
25
26func main() -> i64 {
27 hw("=== nx_loop_subdiv_gate -- Loop subdivision: smooth-limit vs linear refinement ===\n" as *u8)
28 var fails: i64 = 0
29 let R: i64 = 25600
30
31 let meshIn: i64 = (sys_mmap(m3_bytes())) as i64
32 let meshLoop: i64 = (sys_mmap(m3_bytes())) as i64
33 let meshLin: i64 = (sys_mmap(m3_bytes())) as i64
34 let meshLoop2: i64 = (sys_mmap(m3_bytes())) as i64
35 let seen: *i64 = sys_mmap(4096*8) as *i64
36 let sum: *i64 = sys_mmap(32) as *i64
37
38 // octahedron: 6 axis vertices, 8 faces (equator +x,+y,-x,-y ringed to +z / -z poles)
39 m3_init(meshIn)
40 let p0: i64 = m3_add_vert(meshIn, R, 0, 0)
41 let p1: i64 = m3_add_vert(meshIn, 0 - R, 0, 0)
42 let p2: i64 = m3_add_vert(meshIn, 0, R, 0)
43 let p3: i64 = m3_add_vert(meshIn, 0, 0 - R, 0)
44 let p4: i64 = m3_add_vert(meshIn, 0, 0, R)
45 let p5: i64 = m3_add_vert(meshIn, 0, 0, 0 - R)
46 m3_add_tri(meshIn, p0, p2, p4); m3_add_tri(meshIn, p2, p1, p4); m3_add_tri(meshIn, p1, p3, p4); m3_add_tri(meshIn, p3, p0, p4)
47 m3_add_tri(meshIn, p2, p0, p5); m3_add_tri(meshIn, p1, p2, p5); m3_add_tri(meshIn, p3, p1, p5); m3_add_tri(meshIn, p0, p3, p5)
48
49 loop_subdivide(meshIn, meshLoop, seen, sum)
50 sd_subdivide(meshIn, meshLin)
51 loop_subdivide(meshLoop, meshLoop2, seen, sum)
52
53 let hL: *i64 = m3_hdr(meshLoop)
54 let hL2: *i64 = m3_hdr(meshLoop2)
55 let mLoop: i64 = maxsq(meshLoop)
56 let mLin: i64 = maxsq(meshLin)
57 let mLoop2: i64 = maxsq(meshLoop2)
58 hw(" octa 6v/8t -> Loop "); pn(hL[0]); hw("v/"); pn(hL[1]); hw("t maxR^2 Loop="); pn(mLoop); hw(" Lin="); pn(mLin); hw("\n" as *u8)
59
60 var t1: i64 = 0
61 if hL[0] == 18 { if hL[1] == 32 { t1 = 1 } }
62 if t1 == 1 { hw("T1 PASS Loop topology V=18 (6 even + 12 odd) T=32 (4x)\n" as *u8) } else { fails=fails+1; hw("T1 FAIL topology V="); pn(hL[0]); hw(" T="); pn(hL[1]); hw("\n" as *u8) }
63
64 var t2: i64 = 0
65 if mLoop == 256000000 { t2 = 1 }
66 if t2 == 1 { hw("T2 PASS even vertices REPOSITIONED to the smooth limit (pole R->5R/8=16000, maxR^2=256000000)\n" as *u8) } else { fails=fails+1; hw("T2 FAIL maxR^2 Loop="); pn(mLoop); hw(" expected 256000000\n" as *u8) }
67
68 var t3: i64 = 0
69 if mLin == 655360000 { t3 = 1 }
70 if t3 == 1 { hw("T3 PASS linear midpoint KEEPS originals (maxR^2=25600^2=655360000 = same silhouette)\n" as *u8) } else { fails=fails+1; hw("T3 FAIL maxR^2 Lin="); pn(mLin); hw(" expected 655360000\n" as *u8) }
71
72 var t4: i64 = 0
73 if mLoop < mLin { t4 = 1 }
74 if t4 == 1 { hw("T4 PASS neg-control: Loop SMOOTHS toward the limit (maxR^2 Loop < Lin) -- linear only refines the silhouette\n" as *u8) } else { fails=fails+1; hw("T4 FAIL Loop did not smooth vs linear\n" as *u8) }
75
76 var t5: i64 = 0
77 if hL2[1] == 128 { if mLoop2 <= mLoop { t5 = 1 } }
78 if t5 == 1 { hw("T5 PASS converges: 2nd level "); pn(hL2[0]); hw("v/128t, maxR^2 non-increasing ("); pn(mLoop2); hw(" <= "); pn(mLoop); hw(")\n" as *u8) } else { fails=fails+1; hw("T5 FAIL converge V="); pn(hL2[0]); hw(" T="); pn(hL2[1]); hw(" maxR2="); pn(mLoop2); hw("\n" as *u8) }
79
80 let n: i64 = m3_write_stl(meshLoop2, "knowledge/nx_loop_subdiv.stl\x00" as *u8)
81 hw("T6 artifact -> knowledge/nx_loop_subdiv.stl ("); pn(n); hw(" bytes, "); pn(hL2[1]); hw(" tris)\n" as *u8)
82
83 if fails == 0 { hw("NX-LOOP-SUBDIV GREEN -- smooth-limit subdivision (repositions to the limit) vs linear refine, neg-control bites\n" as *u8); sys_exit(0); return 0 }
84 hw("NX-LOOP-SUBDIV RED fails="); pn(fails); hw("\n" as *u8)
85 sys_exit(1)
86 return 1
87}