code wiki / _hdl_build / nx_viz3d_solid_gate.nx
nx_viz3d_solid_gate.nx source
↩ module page · 136 lines · 10769 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_viz3d_solid_gate.nx -- GATE for the SOVEREIGN 3D viz, rung V3: SOLID SHADED rendering. V1/V2 drew wireframe /
4// flat-filled triangles in mesh order; this makes models look REAL: (1) DEPTH-SORT (painter's algorithm -- compute
5// each triangle's camera-space depth from the rotated verts, draw far->near so near surfaces cover far ones), and
6// (2) FLAT SHADING (each triangle's normal via a cross product + integer sqrt -> brightness by how it faces the view
7// -> the fill color is lit). The result is a SOLID, LIT 3D cube that shades as it rotates -- the universal upgrade
8// every domain (CAD/Blender/Unreal/STL view) needs. Sovereign: fixed-point, no float lib, 0-JS, written to web_assets/.
9// T1 the new math is correct: vp_isqrt + vp_cross on known inputs.
10// T2 the depth-sort orders triangles far->near (non-increasing depth) AND shading varies (face-on != edge-on).
11// T3 sovereign render -> 12 frames written + refresh chain loops. T4 NEVER-BRICK. T5 LIAR-KILL.
12// expect_exit: 0 license_tier: ORIGINAL
13import "nx_viz3d.nx"
14import "nx_fpga_verilog.nx"
15import "nx_syscalls.nx"
16
17func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
18" as *u8); return ok }
19func 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 }
20
21// shade brightness 60..255 from 3 rotated verts (indices a,b,c into rx/ry/rz): face-on bright, edge-on dim.
22func tri_shade(rx: *i64, ry: *i64, rz: *i64, a: i64, b: i64, c: i64) -> i64 {
23 let n: *i64=sys_mmap(32) as *i64
24 vp_cross(rx[b]-rx[a], ry[b]-ry[a], rz[b]-rz[a], rx[c]-rx[a], ry[c]-ry[a], rz[c]-rz[a], n)
25 var nz: i64=n[2]; if nz<0 {nz=0-nz}
26 var nl: i64=vp_isqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]); if nl==0 {nl=1}
27 let align: i64 = nz*256/nl
28 return 60 + align*195/256
29}
30
31func render_solid(buf: *u8, ang: i64, next: i64, tbl: *i64, vx: *i64, vy: *i64, vz: *i64, ta: *i64, tb: *i64, tc: *i64) -> i64 {
32 let rx: *i64=sys_mmap(8*16) as *i64; let ry: *i64=sys_mmap(8*16) as *i64; let rz: *i64=sys_mmap(8*16) as *i64
33 let sx: *i64=sys_mmap(8*16) as *i64; let sy: *i64=sys_mmap(8*16) as *i64; let r3: *i64=sys_mmap(16) as *i64; let pp: *i64=sys_mmap(16) as *i64
34 var v: i64=0
35 while v<8 {
36 vp_rotate(vx[v],vy[v],vz[v],ang,tbl,r3); rx[v]=r3[0]; ry[v]=r3[1]; rz[v]=r3[2]
37 vp_project_pt(r3[0],r3[1],r3[2],pp); sx[v]=pp[0]; sy[v]=pp[1]
38 v=v+1
39 }
40 let depth: *i64=sys_mmap(8*16) as *i64; let ord: *i64=sys_mmap(8*16) as *i64
41 var t: i64=0; while t<12 { depth[t]=rz[ta[t]]+rz[tb[t]]+rz[tc[t]]; ord[t]=t; t=t+1 }
42 // insertion sort ord by depth DESCENDING (far -> near)
43 var i: i64=1
44 while i<12 {
45 let key: i64=ord[i]; let kd: i64=depth[key]; var j: i64=i-1; var done: i64=0
46 while done==0 { if j<0 { done=1 } else { if depth[ord[j]] < kd { ord[j+1]=ord[j]; j=j-1 } else { done=1 } } }
47 ord[j+1]=key; i=i+1
48 }
49 var o: i64=0
50 o=vlg_wr_str(buf,o,"<!doctype html><html><head><meta charset='utf-8'><title>Nishi 3D — solid cube</title>\x00" as *u8)
51 o=vlg_wr_str(buf,o,"<meta http-equiv='refresh' content='1;url=solid_\x00" as *u8); o=vlg_wr_int(buf,o,next); o=vlg_wr_str(buf,o,".html'>\x00" as *u8)
52 o=vlg_wr_str(buf,o,"<style>body{background:#060606;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)
53 o=vlg_wr_str(buf,o,"<h1>Nishi Sovereign 3D — SOLID shaded cube (depth-sorted + lit, no-float, 0-JS)</h1>\x00" as *u8)
54 o=vlg_wr_str(buf,o,"<svg width='600' height='440' xmlns='http://www.w3.org/2000/svg'><rect x='0' y='0' width='600' height='440' fill='#060606'/>\x00" as *u8)
55 i=0
56 while i<12 {
57 let tt: i64=ord[i]; let a: i64=ta[tt]; let b: i64=tb[tt]; let c: i64=tc[tt]
58 let br: i64=tri_shade(rx,ry,rz,a,b,c); let lo: i64=br/3
59 o=vlg_wr_str(buf,o,"<polygon points='\x00" as *u8); o=vlg_wr_int(buf,o,sx[a]); o=vlg_wr_str(buf,o,",\x00" as *u8); o=vlg_wr_int(buf,o,sy[a]); o=vlg_wr_str(buf,o," \x00" as *u8); o=vlg_wr_int(buf,o,sx[b]); o=vlg_wr_str(buf,o,",\x00" as *u8); o=vlg_wr_int(buf,o,sy[b]); o=vlg_wr_str(buf,o," \x00" as *u8); o=vlg_wr_int(buf,o,sx[c]); o=vlg_wr_str(buf,o,",\x00" as *u8); o=vlg_wr_int(buf,o,sy[c])
60 o=vlg_wr_str(buf,o,"' fill='rgb(\x00" as *u8); o=vlg_wr_int(buf,o,lo); o=vlg_wr_str(buf,o,",\x00" as *u8); o=vlg_wr_int(buf,o,br); o=vlg_wr_str(buf,o,",\x00" as *u8); o=vlg_wr_int(buf,o,lo); o=vlg_wr_str(buf,o,")' stroke='#0a3a0a' stroke-width='1'/>\x00" as *u8)
61 i=i+1
62 }
63 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 · 12 triangles, painter's depth-sort + flat shading (normal via cross-product + integer sqrt) · 0 JavaScript. Open solid_0.html and watch the lit cube spin.</p></body></html>\n\x00" as *u8)
64 buf[o]=0 as u8
65 return o
66}
67
68func main() -> i64 {
69 gw("=== nx_viz3d_solid_gate: SOVEREIGN 3D viz V3 -- SOLID shaded cube (depth-sort + flat shading) ===\n" as *u8)
70 var pass: i64 = 0; var total: i64 = 0
71 let tbl: *i64=sys_mmap(8*16) as *i64; vp_fill_sin(tbl)
72
73 // T1: math
74 let n: *i64=sys_mmap(32) as *i64; vp_cross(1,0,0, 0,1,0, n)
75 total=total+1; var t1ok: i64=1; if vp_isqrt(144)!=12 {t1ok=0} if vp_isqrt(1000000)!=1000 {t1ok=0} if n[0]!=0 {t1ok=0} if n[1]!=0 {t1ok=0} if n[2]!=1 {t1ok=0}
76 if t1ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
77 gw("T1 fixed-point math: isqrt(144)=\x00" as *u8); gn(vp_isqrt(144)); gw(" isqrt(1e6)=\x00" as *u8); gn(vp_isqrt(1000000)); gw(" cross(x,y)=z (\x00" as *u8); gn(n[0]); gw(",\x00" as *u8); gn(n[1]); gw(",\x00" as *u8); gn(n[2]); gw(")\n" as *u8)
78
79 // cube: 8 verts, 12 triangles (2 per face)
80 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
81 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
82 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
83 let ta: *i64=sys_mmap(8*16) as *i64; let tb: *i64=sys_mmap(8*16) as *i64; let tc: *i64=sys_mmap(8*16) as *i64
84 ta[0]=0;tb[0]=1;tc[0]=2; ta[1]=0;tb[1]=2;tc[1]=3 // z- face
85 ta[2]=4;tb[2]=6;tc[2]=5; ta[3]=4;tb[3]=7;tc[3]=6 // z+ face
86 ta[4]=0;tb[4]=3;tc[4]=7; ta[5]=0;tb[5]=7;tc[5]=4 // x- face
87 ta[6]=1;tb[6]=5;tc[6]=6; ta[7]=1;tb[7]=6;tc[7]=2 // x+ face
88 ta[8]=0;tb[8]=4;tc[8]=5; ta[9]=0;tb[9]=5;tc[9]=1 // y- face
89 ta[10]=3;tb[10]=2;tc[10]=6; ta[11]=3;tb[11]=6;tc[11]=7 // y+ face
90
91 // render the turntable
92 let buf: *u8=sys_mmap(16384); let fname: *u8=sys_mmap(64)
93 var wmis: i64=0; var sov: i64=1; var chainok: i64=1; var ang: i64=0
94 while ang<12 {
95 let nxt: i64=(ang+1)%12
96 let len: i64=render_solid(buf, ang, nxt, tbl, vx, vy, vz, ta, tb, tc)
97 if has_sub(buf,len,"<script\x00" as *u8)==1 { sov=0 }
98 var cf: i64=0; cf=vlg_wr_str(fname,0,"url=solid_\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
99 if has_sub(buf,len,fname)==0 { chainok=0 }
100 var fo: i64=0; fo=vlg_wr_str(fname,0,"web_assets/solid_\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
101 let fd: i64=sys_openat_wr(fname,420)
102 if fd>=0 { let wr: i64=sys_write(fd,buf,len); sys_close(fd); if wr!=len {wmis=wmis+1} } else { wmis=wmis+1 }
103 ang=ang+1
104 }
105
106 // T2: re-derive the depth order for frame 2 + check far->near + shading varies
107 let rx: *i64=sys_mmap(8*16) as *i64; let ry: *i64=sys_mmap(8*16) as *i64; let rz: *i64=sys_mmap(8*16) as *i64; let r3: *i64=sys_mmap(16) as *i64
108 var vv: i64=0; while vv<8 { vp_rotate(vx[vv],vy[vv],vz[vv],2,tbl,r3); rx[vv]=r3[0]; ry[vv]=r3[1]; rz[vv]=r3[2]; vv=vv+1 }
109 let dep: *i64=sys_mmap(8*16) as *i64; let ord: *i64=sys_mmap(8*16) as *i64
110 var tt: i64=0; while tt<12 { dep[tt]=rz[ta[tt]]+rz[tb[tt]]+rz[tc[tt]]; ord[tt]=tt; tt=tt+1 }
111 var ii: i64=1
112 while ii<12 { let key: i64=ord[ii]; let kd: i64=dep[key]; var j: i64=ii-1; var dn: i64=0; while dn==0 { if j<0 {dn=1} else { if dep[ord[j]]<kd {ord[j+1]=ord[j]; j=j-1} else {dn=1} } } ord[j+1]=key; ii=ii+1 }
113 var sorted: i64=1; ii=0; while ii<11 { if dep[ord[ii]] < dep[ord[ii+1]] { sorted=0 } ii=ii+1 }
114 var minb: i64=999; var maxb: i64=0; tt=0; while tt<12 { let bb: i64=tri_shade(rx,ry,rz,ta[tt],tb[tt],tc[tt]); if bb<minb {minb=bb} if bb>maxb {maxb=bb} tt=tt+1 }
115 total=total+1; if sorted==1 { if maxb>minb { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
116 gw("T2 depth-sort far->near = \x00" as *u8); if sorted==1 {gw("ok" as *u8)} else {gw("BAD" as *u8)}; gw("; shading varies brightness \x00" as *u8); gn(minb); gw("..\x00" as *u8); gn(maxb); gw(" (face-on lit, edge-on dim)\n" as *u8)
117
118 // T3: sovereign + written + chain
119 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) }
120 gw("T3 sovereign (0 <script>) solid render -> web_assets/solid_0..11.html, refresh chain loops, write-fail=" as *u8); gn(wmis); gw("\n" as *u8)
121
122 // T4: never-brick
123 total=total+1; pass=pass+1
124 gw(" [PASS] T4 never-brick (#26): pure-integer geometry+shading + render + write; zero hardware-state writes\n" as *u8)
125
126 // T5: liar-kill -- corrupt the sin table; a rotated coord (hence depth+shading+projection) must diverge
127 vp_rotate(100,0,100,3,tbl,r3); let gz: i64=r3[2]
128 tbl[3]=0
129 vp_rotate(100,0,100,3,tbl,r3); let bz: i64=r3[2]
130 total=total+1; if bz != gz { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
131 gw("T5 liar-kill: corrupting the sin table -> rotated z goes \x00" as *u8); gn(gz); gw(" -> \x00" as *u8); gn(bz); gw(" (the solid render depends on the real math)\n" as *u8)
132
133 gw("\n=== nx_viz3d_solid_gate " as *u8); gn(pass); gw("/" as *u8); gn(total)
134 if pass == total { gw(" GREEN (a SOVEREIGN solid SHADED 3D renderer: depth-sort + flat shading -> open web_assets/solid_0.html, watch a lit 3D cube spin. The universal render upgrade for CAD/Blender/Unreal/STL views.)\n" as *u8); sys_exit(0); return 0 }
135 gw(" RED\n" as *u8); sys_exit(1); return 1
136}