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 &mdash; 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 &mdash; 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 &middot; 12 triangles, painter's depth-sort + flat shading (normal via cross-product + integer sqrt) &middot; 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}