code wiki / _hdl_build / nx_engine_lod_gate.nx

nx_engine_lod_gate.nx source

↩ module page · 316 lines · 14237 B

1// nx_engine_lod_gate.nx -- ★ENGINE CONVERGENCE RUNG 2: LOD -- the INFINIGEN x ENGINE fusion, not a Nanite clone. 2// GENERATIVE LOD (generated citizens): the being is re-sampled FROM ITS OWN SDF at the cell size its distance 3// warrants -- no stored clusters, no streaming; the GENERATOR is the compression. (Nanite exists because Unreal 4// must virtualize AUTHORED geometry; generated content gets LOD for free. Better than either.) 5// AUTHORED LOD (corpus citizens): vertex-cluster decimation for the Stanford bunny (quality path = the ecosystem 6// QEM organ, unbridged -- named residual). 7// CAPACITY INVERSION (causal proof): the full-detail scene OVERFLOWS the mesh caps (tm_ovf fires -- it cannot 8// exist); the same scene LOD'd fits and renders. 9// T1 generative LOD ratios + determinism. T2 authored decimation. T3 perceptual (far LOD ~= far full, >=4x fewer 10// tris). T4 capacity inversion. T5 evidence PNG. license_tier: ORIGINAL expect_exit: 0 11import "nx_syscalls.nx" 12import "nx_png.nx" 13import "nx_trimesh.nx" 14import "nx_isosurf.nx" 15import "nx_bodyatlas.nx" 16import "nx_objload.nx" 17 18func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 19func 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 } 20func clearfb(fb: *i64, n: i64, c: i64) -> i64 { var i: i64=0; while i<n { fb[i]=c; i=i+1 } return 0 } 21func filled(fb: *i64, n: i64, bg: i64) -> i64 { var c: i64=0; var i: i64=0; while i<n { if fb[i]!=bg { c=c+1 } i=i+1 } return c } 22func imdiff(a: *i64, b: *i64, n: i64) -> i64 { var s: i64=0; var i: i64=0; while i<n { if a[i]!=b[i] { s=s+1 } i=i+1 } return s } 23func sigdiff(a: *i64, b: *i64, n: i64) -> i64 { 24 var s: i64=0; var i: i64=0 25 while i<n { 26 var d: i64 = (a[i]&255)-(b[i]&255) 27 if d<0 { d=0-d } 28 var d2: i64 = ((a[i]>>8)&255)-((b[i]>>8)&255) 29 if d2<0 { d2=0-d2 } 30 var d3: i64 = ((a[i]>>16)&255)-((b[i]>>16)&255) 31 if d3<0 { d3=0-d3 } 32 if d+d2+d3 > 30 { s=s+1 } 33 i=i+1 34 } 35 return s 36} 37 38const W: i64 = 520 39const H: i64 = 380 40const BG: i64 = 30 + 40*256 + 58*65536 41 42func terr_h(x: i64, z: i64) -> i64 { 43 let n1: i64 = tm_noise3(x, 7777, z, 1500) 44 let n2: i64 = tm_noise3(x, 12345, z, 420) 45 return n1*430/1024 + n2*150/1024 - 300 46} 47func paint(from: i64, to: i64, col: i64) -> i64 { var i: i64=from; while i<to { tm_vcol(i,col); i=i+1 } return 0 } 48 49// ---- generative LOD: polygonize the CURRENT being pose at cell size `cell`, placed at world (bx, ground, bz) ---- 50// grid dims chosen to cover the same local extent (x +-300, y +-990, z +-180) at any cell size. 51func being_lod(cell: i64, bx: i64, ground: i64, bz: i64) -> i64 { 52 let gx: i64 = 600/cell + 1 53 let gy: i64 = 1980/cell + 1 54 let gz: i64 = 370/cell + 1 55 let grid: *i64 = sys_mmap((gx+1)*(gy+1)*(gz+1)*8) as *i64 56 var i: i64 = 0 57 while i <= gx { 58 var j: i64 = 0 59 while j <= gy { 60 var k: i64 = 0 61 while k <= gz { 62 grid[(i*(gy+1)+j)*(gz+1)+k] = ba_sdf(0-300+i*cell, 0-990+j*cell, 0-185+k*cell, 1) 63 k = k + 1 64 } 65 j = j + 1 66 } 67 i = i + 1 68 } 69 let vFrom: i64 = tm_nv() 70 surface_nets(grid, gx, gy, gz, bx-300, ground+900-990, bz-185, cell, 0, 216+172*256+152*65536) 71 let vTo: i64 = tm_nv() 72 let vp: *i64 = sys_mmap(24) as *i64 73 i = vFrom 74 while i < vTo { 75 tm_vpos(i, vp) 76 let kk: i64 = ba_nearest(vp[0]-bx, vp[1]-(ground+900), vp[2]-bz, 1) 77 if kk >= 0 { tm_vcol(i, ba_part_color(kk)) } else { tm_vcol(i, 216+172*256+152*65536) } 78 i = i + 1 79 } 80 return vTo - vFrom 81} 82 83// ---- authored LOD: vertex-cluster decimation of the ENTIRE current buffer (must hold one asset), grid cell `cell` ---- 84func cluster_decimate(cell: i64) -> i64 { 85 let nv: i64 = tm_nv() 86 let nt: i64 = tm_nt() 87 let vx: *i64 = sys_mmap(nv*8) as *i64 88 let vy: *i64 = sys_mmap(nv*8) as *i64 89 let vz: *i64 = sys_mmap(nv*8) as *i64 90 let vc: *i64 = sys_mmap(nv*8) as *i64 91 let ta: *i64 = sys_mmap(nt*8) as *i64 92 let tb: *i64 = sys_mmap(nt*8) as *i64 93 let tc: *i64 = sys_mmap(nt*8) as *i64 94 let vp: *i64 = sys_mmap(24) as *i64 95 let tt: *i64 = sys_mmap(24) as *i64 96 var i: i64 = 0 97 while i < nv { tm_vpos(i, vp); vx[i]=vp[0]; vy[i]=vp[1]; vz[i]=vp[2]; vc[i]=tm_getvcol(i); i=i+1 } 98 var t: i64 = 0 99 while t < nt { tm_tget(t, tt); ta[t]=tt[0]; tb[t]=tt[1]; tc[t]=tt[2]; t=t+1 } 100 // hash: full cell key -> new index 101 let HS: i64 = 131072 102 let HK: *i64 = sys_mmap(HS*8) as *i64 103 let HV: *i64 = sys_mmap(HS*8) as *i64 104 i = 0 105 while i < HS { HK[i]=0; i=i+1 } 106 let map: *i64 = sys_mmap(nv*8) as *i64 107 tm_reset() 108 i = 0 109 while i < nv { 110 let cx: i64 = (vx[i]+1048576)/cell 111 let cy: i64 = (vy[i]+1048576)/cell 112 let cz: i64 = (vz[i]+1048576)/cell 113 let key: i64 = cx*1048573 + cy*8191 + cz + 1 114 var h: i64 = (key*2654435761) & (HS-1) 115 if h < 0 { h = 0-h } 116 var placed: i64 = 0 117 while placed == 0 { 118 if HK[h] == 0 { 119 let ni: i64 = tm_vert(vx[i], vy[i], vz[i]) 120 tm_vcol(ni, vc[i]) 121 HK[h] = key 122 HV[h] = ni 123 map[i] = ni 124 placed = 1 125 } else { 126 if HK[h] == key { map[i] = HV[h]; placed = 1 } else { h = (h+1) & (HS-1) } 127 } 128 } 129 i = i + 1 130 } 131 t = 0 132 while t < nt { 133 let a: i64 = map[ta[t]] 134 let b: i64 = map[tb[t]] 135 let c: i64 = map[tc[t]] 136 var ok: i64 = 1 137 if a == b { ok = 0 } 138 if b == c { ok = 0 } 139 if a == c { ok = 0 } 140 if ok == 1 { tm_tri(a, b, c, 214+208*256+198*65536) } 141 t = t + 1 142 } 143 tm_compute_normals() 144 return tm_nv() 145} 146 147func main() -> i64 { 148 hw("=== nx_engine_lod_gate -- R2 LOD: generative (Infinigen side) + authored decimation (engine side) ===\n" as *u8) 149 var fails: i64 = 0 150 let npx: i64 = W*H 151 tm_set_spec(0) 152 tm_set_tex(0) 153 tm_set_image(0 as *u8, 0, 0) 154 atlas_build(0) 155 atlas_pose(1) 156 157 // ---- T1 GENERATIVE LOD: same SDF, three cell sizes ---- 158 tm_reset() 159 let v18: i64 = being_lod(18, 0, 0, 0) 160 let t18: i64 = tm_nt() 161 tm_reset() 162 let v30: i64 = being_lod(30, 0, 0, 0) 163 let t30: i64 = tm_nt() 164 tm_reset() 165 let v46: i64 = being_lod(46, 0, 0, 0) 166 let t46: i64 = tm_nt() 167 hw(" generative being LODs: cell18 v="); pn(v18); hw("/t="); pn(t18); hw(" cell30 v="); pn(v30); hw("/t="); pn(t30); hw(" cell46 v="); pn(v46); hw("/t="); pn(t46); hw("\n" as *u8) 168 // determinism of a generated LOD 169 tm_reset() 170 let v46b: i64 = being_lod(46, 0, 0, 0) 171 var t1: i64 = 0 172 if t18 > t30*2 { if t30 > t46 { if v46b == v46 { if v46 > 200 { t1 = 1 } } } } 173 if t1 == 1 { hw("T1 PASS GENERATIVE LOD: one SDF, any resolution on demand, deterministic -- no stored clusters (the generator IS the compression)\n" as *u8) } 174 else { fails=fails+1; hw("T1 FAIL\n" as *u8) } 175 176 // ---- T2 AUTHORED LOD: bunny cluster-decimation ---- 177 obj_load("knowledge/stdassets/bunny.obj" as *u8, 1300, 214+208*256+198*65536) 178 let fullV: i64 = tm_nv() 179 let fullT: i64 = tm_nt() 180 let decV: i64 = cluster_decimate(52) 181 let decT: i64 = tm_nt() 182 hw(" bunny: full "); pn(fullV); hw("v/"); pn(fullT); hw("t -> decimated "); pn(decV); hw("v/"); pn(decT); hw("t\n" as *u8) 183 var t2: i64 = 0 184 if fullV == 35947 { if decV*5 < fullV { if decT > 800 { if tm_ovf() == 0 { t2 = 1 } } } } 185 if t2 == 1 { hw("T2 PASS AUTHORED LOD: corpus asset decimated >5x (vertex clustering; QEM organ = the named quality path)\n" as *u8) } 186 else { fails=fails+1; hw("T2 FAIL\n" as *u8) } 187 188 // ---- T3 PERCEPTUAL: far bunny, LOD vs full -- image nearly same, tris >=4x fewer ---- 189 let fA: *i64 = sys_mmap(npx*8) as *i64 190 let fB: *i64 = sys_mmap(npx*8) as *i64 191 obj_load("knowledge/stdassets/bunny.obj" as *u8, 1300, 214+208*256+198*65536) 192 tm_place(0, tm_nv(), 300, 0-150, 500, 450) 193 tm_compute_normals() 194 clearfb(fA, npx, BG) 195 trimesh_render_aa(fA, W, H, 620, 0-330, 3800, 520, 2) 196 obj_load("knowledge/stdassets/bunny.obj" as *u8, 1300, 214+208*256+198*65536) 197 let dec36V: i64 = cluster_decimate(36) 198 let dec36T: i64 = tm_nt() 199 tm_place(0, tm_nv(), 300, 0-150, 500, 450) 200 tm_compute_normals() 201 clearfb(fB, npx, BG) 202 trimesh_render_aa(fB, W, H, 620, 0-330, 3800, 520, 2) 203 let filA: i64 = filled(fA, npx, BG) 204 let dAB: i64 = sigdiff(fA, fB, npx) 205 hw(" distant bunny: full-render px="); pn(filA); hw(" LOD(cell36 "); pn(dec36T); hw("t) significant-diff px="); pn(dAB); hw(" tri ratio x10="); pn(fullT*10/dec36T); hw("\n" as *u8) 206 var t3: i64 = 0 207 if dAB*3 < filA { if dec36T*4 < fullT { t3 = 1 } } 208 if t3 == 1 { hw("T3 PASS PERCEPTUAL: at distance the LOD is near-identical on screen with >=4x fewer triangles (the Nanite promise, measured)\n" as *u8) } 209 else { fails=fails+1; hw("T3 FAIL\n" as *u8) } 210 211 // ---- T4 CAPACITY INVERSION: full-detail scene OVERFLOWS; LOD scene fits ---- 212 obj_load("knowledge/stdassets/bunny.obj" as *u8, 1300, 214+208*256+198*65536) // 35947 213 being_lod(18, 0-900, 0, 620) // ~7k 214 being_lod(18, 400, 0, 1600) // ~7k 215 being_lod(18, 1900, 0, 2600) // ~7k -> exceeds 48k with terrain 216 var tv: i64 = 0 217 while tv < 1681 { tm_vert(0, 0-5000, 0); tv = tv + 1 } // terrain verts would follow... 218 let ovFull: i64 = tm_ovf() 219 hw(" full-detail attempt: verts="); pn(tm_nv()); hw(" OVERFLOW="); pn(ovFull); hw("\n" as *u8) 220 221 // the LOD scene: decimated far bunny + beings at 18/30/46 + terrain + trees 222 obj_load("knowledge/stdassets/bunny.obj" as *u8, 1300, 214+208*256+198*65536) 223 cluster_decimate(52) 224 let bh: i64 = terr_h(1250, 0-420) 225 tm_place(0, tm_nv(), 1250, bh+292, 0-420, 450) 226 let bunnyTo: i64 = tm_nv() 227 // terrain 228 let terrFrom: i64 = tm_nv() 229 let TN: i64 = 41 230 let SP: i64 = 185 231 var gz2: i64 = 0 232 while gz2 < TN { 233 var gx2: i64 = 0 234 while gx2 < TN { 235 let wx: i64 = (gx2-20)*SP 236 let wz: i64 = (gz2-20)*SP 237 let hh2: i64 = terr_h(wx, wz) 238 let vi: i64 = tm_vert(wx, hh2, wz) 239 var col: i64 = 70 + 124*256 + 56*65536 240 if hh2 > 40 { col = 122 + 112*256 + 86*65536 } 241 if hh2 > 170 { col = 224 + 227*256 + 233*65536 } 242 let jit: i64 = tm_hash3(gx2, gz2, 5) % 22 243 tm_vcol(vi, col + jit + jit*256 + jit*65536) 244 gx2 = gx2 + 1 245 } 246 gz2 = gz2 + 1 247 } 248 var qz: i64 = 0 249 while qz < TN-1 { 250 var qx: i64 = 0 251 while qx < TN-1 { 252 let v0: i64 = terrFrom + qz*TN + qx 253 tm_quad(v0, v0+1, v0+TN+1, v0+TN, 0) 254 qx = qx + 1 255 } 256 qz = qz + 1 257 } 258 // trees 259 let tx: *i64 = sys_mmap(6*8) as *i64 260 let tz: *i64 = sys_mmap(6*8) as *i64 261 tx[0]=0-2500; tz[0]=0-1200 262 tx[1]=2450; tz[1]=1500 263 tx[2]=650; tz[2]=0-2400 264 tx[3]=0-1700; tz[3]=2300 265 tx[4]=2900; tz[4]=0-900 266 tx[5]=0-3100; tz[5]=600 267 var t6: i64 = 0 268 while t6 < 6 { 269 let th: i64 = terr_h(tx[t6], tz[t6]) 270 let trF: i64 = tm_nv() 271 tm_cube(tx[t6], th+170, tz[t6], 55, 96+72*256+46*65536) 272 tm_pyramid(tx[t6], th+560, tz[t6], 300, 42+96*256+40*65536) 273 paint(trF, trF+8, 96+72*256+46*65536) 274 paint(trF+8, tm_nv(), 42+96*256+40*65536) 275 t6 = t6 + 1 276 } 277 tm_compute_normals() // bunny/terrain/trees normals; beings keep gradient normals (added after) 278 // beings at LOD by distance: near cell 18, mid 30, far 46 279 let g1: i64 = terr_h(0-900, 620) 280 being_lod(18, 0-900, g1, 620) 281 let g2: i64 = terr_h(400, 2200) 282 being_lod(30, 400, g2, 2200) 283 let g3: i64 = terr_h(2200, 3100) 284 being_lod(46, 2200, g3, 3100) 285 tm_place(0, tm_nv(), 0, 0-650, 0, 1000) 286 tm_set_sun(340, 780, 0-300) 287 tm_shadow_bake() 288 tm_set_tex(70) 289 tm_set_shadow(1) 290 hw(" LOD scene: verts="); pn(tm_nv()); hw(" tris="); pn(tm_nt()); hw(" OVERFLOW="); pn(tm_ovf()); hw("\n" as *u8) 291 let hero: *i64 = sys_mmap(npx*8) as *i64 292 clearfb(hero, npx, BG) 293 trimesh_render_aa(hero, W, H, 620, 0-330, 6600, 520, 2) 294 let filH: i64 = filled(hero, npx, BG) 295 var t4: i64 = 0 296 if ovFull == 1 { if tm_ovf() == 0 { if filH > npx/3 { t4 = 1 } } } 297 if t4 == 1 { hw("T4 PASS CAPACITY INVERSION: the full-detail scene CANNOT EXIST (overflow proven); the LOD scene fits and renders with MORE citizens (3 beings)\n" as *u8) } 298 else { fails=fails+1; hw("T4 FAIL ovFull="); pn(ovFull); hw(" ovLod="); pn(tm_ovf()); hw(" fil="); pn(filH); hw("\n" as *u8) } 299 300 // ---- T5 evidence ---- 301 let GW: i64 = W*2 302 let gal: *i64 = sys_mmap(GW*H*8) as *i64 303 clearfb(gal, GW*H, BG) 304 var y: i64 = 0 305 while y < H { var x: i64=0; while x<W { gal[y*GW+x]=hero[y*W+x]; x=x+1 } y=y+1 } 306 // right panel: the far-bunny perceptual pair overlaid side by side (full render already in fA, LOD in fB) -> show LOD 307 y = 0 308 while y < H { var x: i64=0; while x<W { gal[y*GW+W+x]=fB[y*W+x]; x=x+1 } y=y+1 } 309 write_png(gal, GW, H, "knowledge/nx_engine_lod.png" as *u8) 310 hw("T5 evidence -> knowledge/nx_engine_lod.png (LOD scene w/ 3 beings | far decimated bunny)\n" as *u8) 311 312 if fails == 0 { hw("ENGINE-LOD-GATE GREEN -- R2: GENERATIVE LOD for generated citizens (one SDF, any resolution, zero storage -- beyond Nanite for generated content) + cluster decimation for authored assets + measured perceptual equivalence + a causal capacity inversion. Residual: 128-tri cluster streaming/stitching for authored geometry at Nanite scale; QEM bridge for quality decimation.\n" as *u8); sys_exit(0); return 0 } 313 hw("ENGINE-LOD-GATE RED fails="); pn(fails); hw("\n" as *u8) 314 sys_exit(1) 315 return 1 316}