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}