code wiki / (root) / nx_scene3d.nx

nx_scene3d.nx source

↩ module page · 132 lines · 5004 B

1// nx_scene3d.nx -- reusable 3D scene primitives: integer trig (Bhaskara Q10) + rotate + perspective project + 2// per-face Lambert-shaded, depth-sorted cube. Extracted from the proven cube gates so the native game window and 3// the gates share ONE implementation of the 3D math (no duplicate sprawl). Composes nx_depth_tri. Pure integer, 4// deterministic, no gcc/GL. license_tier: ORIGINAL 5import "nx_syscalls.nx" 6import "nx_image.nx" 7import "nx_depth_tri.nx" 8 9const SC_AMB: i64 = 105 // ambient floor (~41%) 10 11func sc_isin(deg: i64) -> i64 { 12 var d: i64 = deg % 360 13 if d < 0 { d = d + 360 } 14 var sign: i64 = 1 15 if d >= 180 { sign = 0 - 1; d = d - 180 } 16 let hh: i64 = d * (180 - d) 17 return sign * (4 * hh * 1024 / (40500 - hh)) 18} 19func sc_icos(deg: i64) -> i64 { return sc_isin(deg + 90) } 20 21struct Cube3D { 22 cvx: *i64, cvy: *i64, cvz: *i64, 23 rx: *i64, ry: *i64, rz: *i64, 24 px: *i64, py: *i64, pz: *i64, 25 o: *i64, 26 S: i64, focal: i64, dist: i64 27} 28const CUBE3D_BYTES: i64 = 128 29 30func sc_cube_new(S: i64, focal: i64, dist: i64) -> *Cube3D { 31 let c: *Cube3D = sys_mmap(CUBE3D_BYTES) as *Cube3D 32 c.cvx = sys_mmap(64) as *i64 33 c.cvy = sys_mmap(64) as *i64 34 c.cvz = sys_mmap(64) as *i64 35 c.rx = sys_mmap(64) as *i64 36 c.ry = sys_mmap(64) as *i64 37 c.rz = sys_mmap(64) as *i64 38 c.px = sys_mmap(64) as *i64 39 c.py = sys_mmap(64) as *i64 40 c.pz = sys_mmap(64) as *i64 41 c.o = sys_mmap(32) as *i64 42 c.S = S; c.focal = focal; c.dist = dist 43 let cvx: *i64 = c.cvx 44 let cvy: *i64 = c.cvy 45 let cvz: *i64 = c.cvz 46 cvx[0]=0-S; cvy[0]=0-S; cvz[0]=0-S 47 cvx[1]=S; cvy[1]=0-S; cvz[1]=0-S 48 cvx[2]=S; cvy[2]=S; cvz[2]=0-S 49 cvx[3]=0-S; cvy[3]=S; cvz[3]=0-S 50 cvx[4]=0-S; cvy[4]=0-S; cvz[4]=S 51 cvx[5]=S; cvy[5]=0-S; cvz[5]=S 52 cvx[6]=S; cvy[6]=S; cvz[6]=S 53 cvx[7]=0-S; cvy[7]=S; cvz[7]=S 54 return c 55} 56 57// n.L for a face (normal forced OUTWARD via centroid sign), light L=(3,4,12) 58func sc_ndotl(rx: *i64, ry: *i64, rz: *i64, ia: i64, ib: i64, ic: i64, id: i64) -> i64 { 59 let ux: i64 = rx[ib]-rx[ia]; let uy: i64 = ry[ib]-ry[ia]; let uz: i64 = rz[ib]-rz[ia] 60 let vx: i64 = rx[id]-rx[ia]; let vy: i64 = ry[id]-ry[ia]; let vz: i64 = rz[id]-rz[ia] 61 var nx: i64 = uy*vz - uz*vy 62 var ny: i64 = uz*vx - ux*vz 63 var nz: i64 = ux*vy - uy*vx 64 let sx: i64 = rx[ia]+rx[ib]+rx[ic]+rx[id] 65 let sy: i64 = ry[ia]+ry[ib]+ry[ic]+ry[id] 66 let sz: i64 = rz[ia]+rz[ib]+rz[ic]+rz[id] 67 if nx*sx + ny*sy + nz*sz < 0 { nx = 0-nx; ny = 0-ny; nz = 0-nz } 68 return nx*3 + ny*4 + nz*12 69} 70func sc_shade(ndl: i64, nlmax: i64) -> i64 { 71 var d: i64 = ndl 72 if d < 0 { d = 0 } 73 if d > nlmax { d = nlmax } 74 return SC_AMB + ((255 - SC_AMB) * d) / nlmax 75} 76func sc_face(c: *Cube3D, fb: *Image, zb: *i64, ia: i64, ib: i64, ic: i64, id: i64, r: i64, g: i64, b: i64, nlmax: i64) -> i64 { 77 let rx: *i64 = c.rx 78 let ry: *i64 = c.ry 79 let rz: *i64 = c.rz 80 let px: *i64 = c.px 81 let py: *i64 = c.py 82 let pz: *i64 = c.pz 83 let sh: i64 = sc_shade(sc_ndotl(rx, ry, rz, ia, ib, ic, id), nlmax) 84 let rr: i64 = r * sh / 255 85 let gg: i64 = g * sh / 255 86 let bb: i64 = b * sh / 255 87 depth_tri_render(fb, zb, px[ia], py[ia], pz[ia], px[ib], py[ib], pz[ib], px[ic], py[ic], pz[ic], rr, gg, bb, 1) 88 depth_tri_render(fb, zb, px[ia], py[ia], pz[ia], px[ic], py[ic], pz[ic], px[id], py[id], pz[id], rr, gg, bb, 1) 89 return 0 90} 91 92// draw a lit, depth-sorted cube at screen (cx,cy), Y-angle ay, X-angle ax. Caller clears fb + depth-clears zb. 93func sc_cube_draw(c: *Cube3D, fb: *Image, zb: *i64, cx: i64, cy: i64, ay: i64, ax: i64) -> i64 { 94 let SA: i64 = sc_isin(ay) 95 let CA: i64 = sc_icos(ay) 96 let SB: i64 = sc_isin(ax) 97 let CB: i64 = sc_icos(ax) 98 let cvx: *i64 = c.cvx 99 let cvy: *i64 = c.cvy 100 let cvz: *i64 = c.cvz 101 let rx: *i64 = c.rx 102 let ry: *i64 = c.ry 103 let rz: *i64 = c.rz 104 let px: *i64 = c.px 105 let py: *i64 = c.py 106 let pz: *i64 = c.pz 107 let dist: i64 = c.dist 108 let focal: i64 = c.focal 109 var i: i64 = 0 110 while i < 8 { 111 let x1: i64 = (cvx[i] * CA + cvz[i] * SA) / 1024 112 let z1: i64 = (0 - (cvx[i] * SA) + cvz[i] * CA) / 1024 113 let ry2: i64 = (cvy[i] * CB - z1 * SB) / 1024 114 let rz2: i64 = (cvy[i] * SB + z1 * CB) / 1024 115 rx[i] = x1 116 ry[i] = ry2 117 rz[i] = rz2 118 let zc: i64 = rz2 + dist 119 px[i] = cx + (x1 * focal) / zc 120 py[i] = cy - (ry2 * focal) / zc 121 pz[i] = zc 122 i = i + 1 123 } 124 let nlmax: i64 = 4 * c.S * c.S * 13 125 sc_face(c, fb, zb, 4, 5, 6, 7, 80, 120, 255, nlmax) // +Z blue 126 sc_face(c, fb, zb, 0, 1, 2, 3, 235, 220, 90, nlmax) // -Z amber 127 sc_face(c, fb, zb, 1, 5, 6, 2, 255, 90, 90, nlmax) // +X red 128 sc_face(c, fb, zb, 0, 4, 7, 3, 90, 220, 220, nlmax) // -X cyan 129 sc_face(c, fb, zb, 3, 2, 6, 7, 110, 230, 130, nlmax) // +Y green 130 sc_face(c, fb, zb, 0, 1, 5, 4, 230, 120, 230, nlmax) // -Y magenta 131 return 0 132}