code wiki / _hdl_build / nx_viz3d_cube_gate.nx
nx_viz3d_cube_gate.nx source
↩ module page · 96 lines · 7715 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_viz3d_cube_gate.nx -- GATE for the SOVEREIGN 3D viewport (rung V1, foundation of Nishi first-party 3D viz).
4// Renders a rotating wireframe CUBE as a self-running turntable: 12 frames (30 deg apart), each a sovereign 0-JS
5// HTML/SVG page projecting the cube's 8 vertices + 12 edges with the fixed-point (NO-FLOAT) 3D math in nx_viz3d, each
6// carrying an HTML <meta http-equiv=refresh> to the next (looping) -> open cube3d_0.html in the Nishi browser and the
7// cube SPINS, ~1fps, no JS, no server. The first concrete step toward "see these things" (STL/CAD/Blender-class).
8// T1 the fixed-point projection is correct (a known vertex -> the computed screen point) AND rotation moves points.
9// T2 sovereign (0 JS) + the 12 frames written + the meta-refresh chain loops. T3 NEVER-BRICK.
10// T4 LIAR-KILL (corrupt the sin table -> the projection diverges -> the rendered cube is wrong). expect_exit: 0
11// license_tier: ORIGINAL
12import "nx_viz3d.nx"
13import "nx_fpga_verilog.nx" // vlg_wr_str / vlg_wr_int
14import "nx_syscalls.nx"
15
16func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
17" as *u8); return ok }
18func has_sub(buf: *u8, len: i64, s: *u8) -> i64 { var sl: i64=0; while s[sl]!=(0 as u8){sl=sl+1} var p: i64=0; while p+sl<=len { var m: i64=1; var j: i64=0; while j<sl { if buf[p+j]!=s[j] {m=0} j=j+1 } if m==1 {return 1} p=p+1 } return 0 }
19
20func render_cube(buf: *u8, ang: i64, next: i64, tbl: *i64, vx: *i64, vy: *i64, vz: *i64, ea: *i64, eb: *i64) -> i64 {
21 let sx: *i64=sys_mmap(8*16) as *i64; let sy: *i64=sys_mmap(8*16) as *i64; let pp: *i64=sys_mmap(16) as *i64
22 var v: i64=0
23 while v<8 { vp_project(vx[v], vy[v], vz[v], ang, tbl, pp); sx[v]=pp[0]; sy[v]=pp[1]; v=v+1 }
24 var o: i64=0
25 o=vlg_wr_str(buf,o,"<!doctype html><html><head><meta charset='utf-8'><title>Nishi 3D — cube</title>\x00" as *u8)
26 o=vlg_wr_str(buf,o,"<meta http-equiv='refresh' content='1;url=cube3d_\x00" as *u8); o=vlg_wr_int(buf,o,next); o=vlg_wr_str(buf,o,".html'>\x00" as *u8)
27 o=vlg_wr_str(buf,o,"<style>body{background:#070707;color:#cfc;font-family:monospace;margin:0;padding:18px;text-align:center}h1{color:#39ff14;font-size:18px}p{color:#8b8;font-size:12px}</style></head><body>\x00" as *u8)
28 o=vlg_wr_str(buf,o,"<h1>Nishi Sovereign 3D — rotating cube (no-float, 0-JS)</h1>\x00" as *u8)
29 o=vlg_wr_str(buf,o,"<svg width='600' height='420' xmlns='http://www.w3.org/2000/svg'><rect x='0' y='0' width='600' height='420' fill='#070707'/>\x00" as *u8)
30 var e: i64=0
31 while e<12 {
32 let a: i64=ea[e]; let b: i64=eb[e]
33 o=vlg_wr_str(buf,o,"<line x1='\x00" as *u8); o=vlg_wr_int(buf,o,sx[a]); o=vlg_wr_str(buf,o,"' y1='\x00" as *u8); o=vlg_wr_int(buf,o,sy[a]); o=vlg_wr_str(buf,o,"' x2='\x00" as *u8); o=vlg_wr_int(buf,o,sx[b]); o=vlg_wr_str(buf,o,"' y2='\x00" as *u8); o=vlg_wr_int(buf,o,sy[b]); o=vlg_wr_str(buf,o,"' stroke='#39ff14' stroke-width='2'/>\x00" as *u8)
34 e=e+1
35 }
36 v=0; while v<8 { o=vlg_wr_str(buf,o,"<circle cx='\x00" as *u8); o=vlg_wr_int(buf,o,sx[v]); o=vlg_wr_str(buf,o,"' cy='\x00" as *u8); o=vlg_wr_int(buf,o,sy[v]); o=vlg_wr_str(buf,o,"' r='3' fill='#bfffb0'/>\x00" as *u8); v=v+1 }
37 o=vlg_wr_str(buf,o,"</svg><p>frame \x00" as *u8); o=vlg_wr_int(buf,o,ang); o=vlg_wr_str(buf,o,"/12 · rotating around Y, perspective-projected by sovereign fixed-point math · 0 JavaScript, 0 external loads. Open cube3d_0.html and watch it spin.</p></body></html>\n\x00" as *u8)
38 buf[o]=0 as u8
39 return o
40}
41
42func main() -> i64 {
43 gw("=== nx_viz3d_cube_gate: SOVEREIGN 3D viewport V1 -- a rotating wireframe cube (no-float, 0-JS) ===\n" as *u8)
44 var pass: i64 = 0; var total: i64 = 0
45 let tbl: *i64=sys_mmap(8*16) as *i64; vp_fill_sin(tbl)
46 // cube: 8 vertices (+/-100), 12 edges
47 let vx: *i64=sys_mmap(8*8) as *i64; let vy: *i64=sys_mmap(8*8) as *i64; let vz: *i64=sys_mmap(8*8) as *i64
48 vx[0]=0-100;vy[0]=0-100;vz[0]=0-100; vx[1]=100;vy[1]=0-100;vz[1]=0-100; vx[2]=100;vy[2]=100;vz[2]=0-100; vx[3]=0-100;vy[3]=100;vz[3]=0-100
49 vx[4]=0-100;vy[4]=0-100;vz[4]=100; vx[5]=100;vy[5]=0-100;vz[5]=100; vx[6]=100;vy[6]=100;vz[6]=100; vx[7]=0-100;vy[7]=100;vz[7]=100
50 let ea: *i64=sys_mmap(8*16) as *i64; let eb: *i64=sys_mmap(8*16) as *i64
51 ea[0]=0;eb[0]=1; ea[1]=1;eb[1]=2; ea[2]=2;eb[2]=3; ea[3]=3;eb[3]=0
52 ea[4]=4;eb[4]=5; ea[5]=5;eb[5]=6; ea[6]=6;eb[6]=7; ea[7]=7;eb[7]=4
53 ea[8]=0;eb[8]=4; ea[9]=1;eb[9]=5; ea[10]=2;eb[10]=6; ea[11]=3;eb[11]=7
54
55 // T1: projection correctness + rotation
56 let pp: *i64=sys_mmap(16) as *i64
57 vp_project(100,100,100,0,tbl,pp); let okpt: i64 = pp[0]; let okpt2: i64 = pp[1]
58 vp_project(100,0,100,0,tbl,pp); let p0x: i64=pp[0]
59 vp_project(100,0,100,3,tbl,pp); let p3x: i64=pp[0]
60 total=total+1; var t1ok: i64=1; if okpt!=360 {t1ok=0} if okpt2!=150 {t1ok=0} if p0x==p3x {t1ok=0}
61 if t1ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
62 gw("T1 fixed-point projection: (100,100,100)@0 -> (\x00" as *u8); gn(okpt); gw(",\x00" as *u8); gn(okpt2); gw(") (=360,150); rotation moves x \x00" as *u8); gn(p0x); gw("->\x00" as *u8); gn(p3x); gw("\n" as *u8)
63
64 // render + write the 12 turntable frames
65 let buf: *u8=sys_mmap(16384); let fname: *u8=sys_mmap(64)
66 var wmis: i64=0; var sov: i64=1; var chainok: i64=1
67 var ang: i64=0
68 while ang<12 {
69 let nxt: i64 = (ang+1) % 12
70 let len: i64 = render_cube(buf, ang, nxt, tbl, vx, vy, vz, ea, eb)
71 if has_sub(buf, len, "<script\x00" as *u8)==1 { sov=0 }
72 var cf: i64=0; cf=vlg_wr_str(fname,0,"url=cube3d_\x00" as *u8); cf=vlg_wr_int(fname,cf,nxt); cf=vlg_wr_str(fname,cf,".html\x00" as *u8); fname[cf]=0 as u8
73 if has_sub(buf, len, fname)==0 { chainok=0 }
74 var fo: i64=0; fo=vlg_wr_str(fname,0,"web_assets/cube3d_\x00" as *u8); fo=vlg_wr_int(fname,fo,ang); fo=vlg_wr_str(fname,fo,".html\x00" as *u8); fname[fo]=0 as u8
75 let fd: i64=sys_openat_wr(fname, 420)
76 if fd>=0 { let wr: i64=sys_write(fd,buf,len); sys_close(fd); if wr!=len {wmis=wmis+1} } else { wmis=wmis+1 }
77 ang=ang+1
78 }
79 total=total+1; if sov==1 { if wmis==0 { if chainok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
80 gw("T2 sovereign (0 <script>) + 12 turntable frames written to web_assets/cube3d_0..11.html + refresh chain loops; write-fail=\x00" as *u8); gn(wmis); gw("\n" as *u8)
81
82 // T3: never-brick
83 total=total+1; pass=pass+1
84 gw(" [PASS] T3 never-brick (#26): pure-integer fixed-point math + text render + file write; zero hardware-state writes\n" as *u8)
85
86 // T4: liar-kill -- corrupt the sin table; a projection that depends on it must diverge
87 vp_project(100,0,100,3,tbl,pp); let gx: i64=pp[0]
88 tbl[3] = 0 // corrupt sin(90)
89 vp_project(100,0,100,3,tbl,pp); let bx: i64=pp[0]
90 total=total+1; if bx != gx { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
91 gw("T4 liar-kill: corrupting the sin table -> projection x goes \x00" as *u8); gn(gx); gw(" -> \x00" as *u8); gn(bx); gw(" (the 3D render depends on the real math)\n" as *u8)
92
93 gw("\n=== nx_viz3d_cube_gate " as *u8); gn(pass); gw("/" as *u8); gn(total)
94 if pass == total { gw(" GREEN (a SOVEREIGN no-float 3D renderer: open web_assets/cube3d_0.html in the Nishi browser and watch a 3D cube SPIN, 0-JS -- the foundation of Nishi 3D visualization)\n" as *u8); sys_exit(0); return 0 }
95 gw(" RED\n" as *u8); sys_exit(1); return 1
96}