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}