code wiki / _hdl_build / nx_worldpop_gate.nx

nx_worldpop_gate.nx source

↩ module page · 146 lines · 6793 B

1// nx_worldpop_gate.nx -- ★SOVEREIGN INFINIGEN: POPULATE a world with vegetation. Render a procedural landscape, 2// then place procedural TREES on the terrain (projected + distance-scaled, painter's order far->near) = a LIVING 3// landscape. Proves the modules compose: nx_worldgen (nature) + nx_treegen (vegetation). 4// T1 the populated world renders with markedly more canopy-green than the bare world (trees were placed) 5// T2 determinism + PNG knowledge/nx_worldpop.png (bare world | populated world) 6// license_tier: ORIGINAL expect_exit: 0 7import "nx_syscalls.nx" 8import "nx_png.nx" 9import "nx_worldgen.nx" 10import "nx_treegen.nx" 11 12func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 13func 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 } 14 15const KEY: i64 = 16711935 // 0xFF00FF magenta chroma-key (255,0,255) 16const CAMY_EYE: i64 = 1050 17const WFOC: i64 = 360 // must match nx_worldgen WG_FOCAL 18const WHOR: i64 = 46 // WG_HORIZON 19 20func greencount(fb: *i64, n: i64) -> i64 { var s: i64=0; var i: i64=0; while i<n { let px: i64=fb[i]; let r: i64=px&255; let g: i64=(px>>8)&255; let b: i64=(px>>16)&255; if g>r+8 { if g>b+8 { s=s+1 } } i=i+1 } return s } 21 22func main() -> i64 { 23 hw("=== nx_worldpop_gate -- populate a world with procedural vegetation ===\n" as *u8) 24 var fails: i64 = 0 25 let WW: i64 = wg_w(); let WH: i64 = wg_h(); let wnpx: i64 = WW*WH 26 let TW: i64 = tg_w(); let TH: i64 = tg_h() 27 let seed: i64 = 11 28 29 // bare world 30 let bare: *i64 = sys_mmap(wnpx*8) as *i64 31 worldgen_render(seed, 0, bare) 32 let gbare: i64 = greencount(bare, wnpx) 33 34 // one tree sprite (magenta key bg) + its bbox 35 let P: *i64 = sys_mmap(TG_CAP*TG_STR*8) as *i64 36 let np: i64 = treegen_build(P, 5) 37 let spr: *i64 = sys_mmap(TW*TH*8) as *i64 38 treegen_render(P, np, 300, 4, 255, 0, 255, spr) 39 var minx: i64=TW; var maxx: i64=0; var miny: i64=TH; var maxy: i64=0 40 var i: i64 = 0 41 while i < TW*TH { if spr[i] != KEY { let x: i64=i%TW; let y: i64=i/TW; if x<minx{minx=x} if x>maxx{maxx=x} if y<miny{miny=y} if y>maxy{maxy=y} } i=i+1 } 42 let tpw: i64 = maxx-minx+1; let tph: i64 = maxy-miny+1 43 hw(" tree sprite bbox "); pn(tpw); hw("x"); pn(tph); hw("\n" as *u8) 44 45 // populated world = copy bare, then composite trees 46 let pop: *i64 = sys_mmap(wnpx*8) as *i64 47 i = 0 48 while i < wnpx { pop[i] = bare[i]; i=i+1 } 49 let camy: i64 = wg_max(WATER, wg_terrain_h(0,0,seed)) + CAMY_EYE 50 51 // scatter placements on a jittered grid; keep only grassy foreground; collect (rz,px,py,sh) then paint far->near 52 let NP: i64 = 40 53 let plc: *i64 = sys_mmap(NP*4*8) as *i64 54 var npl: i64 = 0 55 var gz: i64 = 0 56 while gz < 8 { 57 var gx: i64 = 0 58 while gx < 6 { 59 let wz: i64 = 3200 + gz*1750 + (gx*613 % 900) 60 let wx: i64 = (gx-3)*wz*3/10 + (gz*457 % 800) - 400 // spread with FOV, jitter 61 let h: i64 = wg_terrain_h(wx, wz, seed) 62 if h > WATER+90 { if h < 1500 { 63 let px: i64 = WW/2 + wx*WFOC/wz 64 let py: i64 = WH/2 - WHOR - (h - camy)*WFOC/wz 65 let sh: i64 = 150*6000/wz // distance-scaled screen height 66 if sh > 7 { if px > 0-40 { if px < WW+40 { if py > 0 { if py < WH { 67 plc[npl*4]=wz; plc[npl*4+1]=px; plc[npl*4+2]=py; plc[npl*4+3]=sh; npl=npl+1 68 } } } } } 69 } } 70 gx = gx + 1 71 } 72 gz = gz + 1 73 } 74 // sort far->near (insertion sort by rz descending, so painting overdraws near-over-far) 75 var a: i64 = 1 76 while a < npl { 77 let kz: i64=plc[a*4]; let k1: i64=plc[a*4+1]; let k2: i64=plc[a*4+2]; let k3: i64=plc[a*4+3] 78 var b: i64 = a 79 var go: i64 = 1 80 while go == 1 { 81 if b <= 0 { go = 0 } 82 else { 83 if plc[(b-1)*4] < kz { 84 plc[b*4]=plc[(b-1)*4]; plc[b*4+1]=plc[(b-1)*4+1]; plc[b*4+2]=plc[(b-1)*4+2]; plc[b*4+3]=plc[(b-1)*4+3] 85 b = b - 1 86 } else { go = 0 } 87 } 88 } 89 plc[b*4]=kz; plc[b*4+1]=k1; plc[b*4+2]=k2; plc[b*4+3]=k3 90 a = a + 1 91 } 92 // paint 93 var pi: i64 = 0 94 while pi < npl { 95 let px: i64=plc[pi*4+1]; let py: i64=plc[pi*4+2]; let sh: i64=plc[pi*4+3] 96 let sw: i64 = sh*tpw/tph 97 var oy: i64 = py - sh 98 while oy <= py { 99 if oy >= 0 { if oy < WH { 100 let fy: i64 = miny + (oy-(py-sh))*tph/sh 101 var ox: i64 = px - sw/2 102 while ox <= px + sw/2 { 103 if ox >= 0 { if ox < WW { 104 let fx: i64 = minx + (ox-(px-sw/2))*tpw/sw 105 if fx>=0 { if fx<TW { if fy>=0 { if fy<TH { 106 let s: i64 = spr[fy*TW+fx] 107 if s != KEY { pop[oy*WW+ox] = s } 108 } } } } 109 } } 110 ox = ox + 1 111 } 112 } } 113 oy = oy + 1 114 } 115 pi = pi + 1 116 } 117 let gpop: i64 = greencount(pop, wnpx) 118 hw(" placed "); pn(npl); hw(" trees | green px: bare="); pn(gbare); hw(" populated="); pn(gpop); hw("\n" as *u8) 119 var T1: i64 = 0 120 if gpop > gbare + 4000 { if npl > 8 { T1 = 1 } } 121 if T1 == 1 { hw("T1 PASS the world was POPULATED with trees (canopy green increased)\n" as *u8) } 122 else { fails=fails+1; hw("T1 FAIL not enough trees placed\n" as *u8) } 123 124 // gallery bare | populated 125 let GW: i64 = WW*2 126 let gal: *i64 = sys_mmap(GW*WH*8) as *i64 127 var y: i64 = 0 128 while y < WH { var x: i64=0; while x<WW { gal[y*GW+x]=bare[y*WW+x]; gal[y*GW+WW+x]=pop[y*WW+x]; x=x+1 } y=y+1 } 129 write_png(gal, GW, WH, "knowledge/nx_worldpop.png" as *u8) 130 131 // determinism 132 let pop2: *i64 = sys_mmap(wnpx*8) as *i64 133 worldgen_render(seed, 0, pop2) 134 var ddet: i64 = 0 135 i = 0 136 while i < wnpx { if pop2[i] != bare[i] { ddet=ddet+1 } i=i+1 } 137 var T2: i64 = 0 138 if ddet == 0 { T2 = 1 } 139 if T2 == 1 { hw("T2 PASS determinism + PNG knowledge/nx_worldpop.png (bare | populated)\n" as *u8) } 140 else { fails=fails+1; hw("T2 FAIL ddet="); pn(ddet); hw("\n" as *u8) } 141 142 if fails == 0 { hw("WORLDPOP-GATE 2/2 GREEN -- a LIVING landscape: procedural terrain POPULATED with procedural trees (worldgen + treegen compose), sovereign, no ML, no assets\n" as *u8); sys_exit(0); return 0 } 143 hw("WORLDPOP-GATE RED fails="); pn(fails); hw("\n" as *u8) 144 sys_exit(1) 145 return 1 146}