code wiki / _hdl_build / nx_procgen_scene_gate.nx
nx_procgen_scene_gate.nx source
↩ module page · 168 lines · 10777 B
1// nx_procgen_scene_gate.nx -- Gx/PROCGEN: a COMPOSED procedural nature scene + paired GROUND-TRUTH SEGMENTATION
2// label map (the Infinigen / digital-twin shape). Unifies the generators: 1D-FBM rolling-hill horizon + sky
3// gradient + seed-placed procedural trees (trunk + canopy) + one canon-proportioned human, all in one frame; a
4// parallel buffer emits a flat-coloured per-pixel CLASS map (sky/ground/tree/human) = the label an ML/twin
5// pipeline consumes. Integer/sovereign/asset-free, seed-diverse. HONEST: stylised, not photoreal -- it proves
6// COMPOSITION + LABELS (two named GAP axes), not fidelity.
7// D001 MIGRATION 2026-09-02 (procgen PG19): hand-rolled PASS/FAIL prints, a fails counter and sys_exit(1) replaced by gv_check
8// per tooth and gv_verdict, so the exit code IS the verdict; measurements, thresholds and the PNGs are unchanged.
9// license_tier: ORIGINAL expect_exit: 0
10import "nx_syscalls.nx"
11import "nx_gate_verdict.nx"
12import "nx_png_write.nx"
13
14func sc_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
15func sc_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 }
16func sc_hash(x: i64, seed: i64) -> i64 { var a: i64=(x+1)*374761393 + (seed+1)*668265263; a=a%16777216; if a<0{a=a+16777216} a=(a*1103515245+12345)%16777216; if a<0{a=a+16777216} return a%4096 }
17func sc_smooth(t: i64) -> i64 { let t2: i64=(t*t)/4096; return (t2*(3*4096-2*t))/4096 }
18func sc_vnoise1(x: i64, lat: i64, sw: i64, seed: i64) -> i64 {
19 let fx: i64=(x*lat*4096)/sw; let gx: i64=fx/4096; let tx: i64=fx-gx*4096
20 let c0: i64=sc_hash(gx,seed); let c1: i64=sc_hash(gx+1,seed)
21 let sx: i64=sc_smooth(tx); return c0 + ((c1-c0)*sx)/4096
22}
23func sc_fbm1(x: i64, sw: i64, seed: i64) -> i64 {
24 var h: i64=0; var amp: i64=2048; var lat: i64=4; var norm: i64=0; var o: i64=0
25 while o<4 { h=h+(sc_vnoise1(x,lat,sw,seed+o*97)*amp)/4096; norm=norm+amp; amp=amp/2; lat=lat*2; o=o+1 }
26 if norm<1 { norm=1 }
27 return (h*1000)/norm
28}
29
30func main() -> i64 {
31 sc_puts("=== nx_procgen_scene_gate -- composed nature scene + ground-truth segmentation labels ===\n" as *u8)
32 let ctr: *i64=gv_ctr()
33 let SW: i64=600; let SH: i64=320; let DIV: i64=8; let W: i64=SW*2+DIV
34 let rgb: *u8=sys_mmap(W*SH*3+16)
35 let lab: *u8=sys_mmap(W*SH*3+16)
36 let seed: i64=4242
37 // class colours for the label map
38 let sky_lr: i64=90; let sky_lg: i64=120; let sky_lb: i64=200
39 let gnd_lr: i64=70; let gnd_lg: i64=150; let gnd_lb: i64=60
40 let tre_lr: i64=20; let tre_lg: i64=90; let tre_lb: i64=40
41 let hum_lr: i64=210; let hum_lg: i64=50; let hum_lb: i64=50
42 var skyc: i64=0; var gndc: i64=0; var trec: i64=0; var humc: i64=0
43 // ground horizon per column
44 let gtop: *i64=sys_mmap(SW*8) as *i64
45 var x: i64=0
46 while x<SW { let f: i64=sc_fbm1(x,SW,seed); gtop[x]=150 + (f-500)/6; if gtop[x]<70 {gtop[x]=70} if gtop[x]>250 {gtop[x]=250} x=x+1 }
47 // paint sky + ground into BOTH the scene (shaded) and the label (flat class)
48 var py: i64=0
49 while py<SH {
50 var px: i64=0
51 while px<SW {
52 let o: i64=(py*W+px)*3
53 let lo: i64=o
54 if py<gtop[px] {
55 // sky gradient
56 let t: i64=(py*1000)/(gtop[px]+1)
57 rgb[o]=(70+(140*t)/1000) as u8; rgb[o+1]=(110+(90*t)/1000) as u8; rgb[o+2]=(180+(50*t)/1000) as u8
58 lab[lo]=sky_lr as u8; lab[lo+1]=sky_lg as u8; lab[lo+2]=sky_lb as u8
59 skyc=skyc+1
60 } else {
61 // ground: near (lower) darker/greener, far lighter
62 let d: i64=py-gtop[px]
63 var g: i64=150 - (d/4); if g<70 {g=70}
64 let nz: i64=sc_hash(px*3+py,seed)%20
65 rgb[o]=(70+nz) as u8; rgb[o+1]=(g) as u8; rgb[o+2]=(50+nz) as u8
66 lab[lo]=gnd_lr as u8; lab[lo+1]=gnd_lg as u8; lab[lo+2]=gnd_lb as u8
67 gndc=gndc+1
68 }
69 px=px+1
70 }
71 py=py+1
72 }
73 // trees: seed count, back-to-front (smaller/higher base = farther -> draw first)
74 let ntree: i64=5 + sc_hash(9,seed)%3
75 var ti: i64=0
76 while ti<ntree {
77 let tx: i64=40 + (sc_hash(ti*13+1,seed)*(SW-80))/4096
78 if tx>=2 { if tx<SW-2 {
79 let baseY: i64=gtop[tx]
80 let scale: i64=40 + (baseY-70)*70/180 // farther(high) small, near(low) big
81 let th: i64=scale // tree height
82 let trunkH: i64=th/3; let trunkW: i64=2 + scale/22
83 // trunk
84 var yy: i64=baseY-trunkH
85 while yy<baseY { var xx: i64=tx-trunkW; while xx<=tx+trunkW { if xx>=0 { if xx<SW { if yy>=0 { if yy<SH { let o: i64=(yy*W+xx)*3; rgb[o]=92 as u8; rgb[o+1]=64 as u8; rgb[o+2]=38 as u8; let lo: i64=o; lab[lo]=tre_lr as u8; lab[lo+1]=tre_lg as u8; lab[lo+2]=tre_lb as u8; trec=trec+1 } } } } xx=xx+1 } yy=yy+1 }
86 // canopy: 3 stacked circles
87 let cr: i64=scale/2
88 var lvl: i64=0
89 while lvl<3 {
90 let ccy: i64=baseY-trunkH-cr+lvl*(0-cr*7/10)
91 let ccr: i64=cr - lvl*cr/4
92 var ey: i64=ccy-ccr
93 while ey<=ccy+ccr {
94 var ex: i64=tx-ccr
95 while ex<=tx+ccr {
96 let dx: i64=ex-tx; let dy: i64=ey-ccy
97 if dx*dx+dy*dy<=ccr*ccr { if ex>=0 { if ex<SW { if ey>=0 { if ey<SH {
98 let o: i64=(ey*W+ex)*3
99 let sh: i64=180 - (dx*40)/(ccr+1)
100 rgb[o]=(30+ (sc_hash(ex+ey,seed)%25)) as u8; rgb[o+1]=(90+sh/3) as u8; rgb[o+2]=(40+(sc_hash(ex*2+ey,seed)%20)) as u8
101 let lo: i64=o; lab[lo]=tre_lr as u8; lab[lo+1]=tre_lg as u8; lab[lo+2]=tre_lb as u8; trec=trec+1
102 } } } } }
103 ex=ex+1
104 }
105 ey=ey+1
106 }
107 lvl=lvl+1
108 }
109 } }
110 ti=ti+1
111 }
112 // one canon human in the foreground
113 let hx: i64=SW*7/10; let hbase: i64=gtop[hx]
114 let Hh: i64=SH-hbase-6; if Hh<60 { } // figure height = from ground to near bottom
115 let figH: i64=110
116 let hy0: i64=hbase-figH // top of head
117 let hh: i64=figH/8 // head height (8 heads-ish)
118 // torso silhouette
119 let sh_hw: i64=hh*15/10; let ws_hw: i64=hh*9/10; let hp_hw: i64=hh*12/10
120 let ySh: i64=hy0+hh*13/10; let yWa: i64=hy0+hh*3; let yHp: i64=hy0+hh*35/10
121 var yy2: i64=ySh
122 while yy2<=yHp {
123 var hw: i64=0
124 if yy2<=yWa { let t: i64=((yy2-ySh)*1000)/(yWa-ySh+1); hw=sh_hw+((ws_hw-sh_hw)*t)/1000 }
125 else { let t: i64=((yy2-yWa)*1000)/(yHp-yWa+1); hw=ws_hw+((hp_hw-ws_hw)*t)/1000 }
126 var px2: i64=hx-hw
127 while px2<=hx+hw { if px2>=0 { if px2<SW { if yy2>=0 { if yy2<SH { let o: i64=(yy2*W+px2)*3; rgb[o]=210 as u8; rgb[o+1]=150 as u8; rgb[o+2]=120 as u8; let lo: i64=o; lab[lo]=hum_lr as u8; lab[lo+1]=hum_lg as u8; lab[lo+2]=hum_lb as u8; humc=humc+1 } } } } px2=px2+1 }
128 yy2=yy2+1
129 }
130 // legs
131 var lg: i64=0
132 while lg<2 { let lx: i64=hx+(lg*2-1)*(hp_hw/2); var yy3: i64=yHp; while yy3<=hbase { var px3: i64=lx-hh*5/10; while px3<=lx+hh*5/10 { if px3>=0 { if px3<SW { if yy3>=0 { if yy3<SH { let o: i64=(yy3*W+px3)*3; rgb[o]=200 as u8; rgb[o+1]=142 as u8; rgb[o+2]=112 as u8; let lo: i64=o; lab[lo]=hum_lr as u8; lab[lo+1]=hum_lg as u8; lab[lo+2]=hum_lb as u8; humc=humc+1 } } } } px3=px3+1 } yy3=yy3+1 } lg=lg+1 }
133 // head
134 let hcx: i64=hx; let hcy: i64=hy0+hh/2; let hrx: i64=hh*4/10; let hry: i64=hh/2
135 var ey2: i64=hcy-hry
136 while ey2<=hcy+hry { var ex2: i64=hcx-hrx; while ex2<=hcx+hrx { let dx: i64=ex2-hcx; let dy: i64=ey2-hcy; if (dx*dx)*(hry*hry)+(dy*dy)*(hrx*hrx)<=(hrx*hrx)*(hry*hry) { if ex2>=0 { if ex2<SW { if ey2>=0 { if ey2<SH { let o: i64=(ey2*W+ex2)*3; rgb[o]=214 as u8; rgb[o+1]=154 as u8; rgb[o+2]=124 as u8; let lo: i64=o; lab[lo]=hum_lr as u8; lab[lo+1]=hum_lg as u8; lab[lo+2]=hum_lb as u8; humc=humc+1 } } } } } ex2=ex2+1 } ey2=ey2+1 }
137 // divider
138 var dy4: i64=0
139 while dy4<SH { var dx4: i64=SW; while dx4<SW+DIV { let o: i64=(dy4*W+dx4)*3; rgb[o]=8 as u8; rgb[o+1]=8 as u8; rgb[o+2]=10 as u8; lab[o]=8 as u8; lab[o+1]=8 as u8; lab[o+2]=10 as u8; dx4=dx4+1 } dy4=dy4+1 }
140 // copy label panel into the right half of rgb
141 var cy: i64=0
142 while cy<SH { var cx2: i64=0; while cx2<SW { let src: i64=(cy*W+cx2)*3; let dst: i64=(cy*W+(SW+DIV)+cx2)*3; rgb[dst]=lab[src]; rgb[dst+1]=lab[src+1]; rgb[dst+2]=lab[src+2]; cx2=cx2+1 } cy=cy+1 }
143 nx_png_write_rgb("knowledge/nx_procgen_scene.png\x00" as *u8, rgb, W, SH)
144 sc_puts(" wrote knowledge/nx_procgen_scene.png\n" as *u8)
145 sc_puts(" class px -- sky="); sc_pn(skyc); sc_puts(" ground="); sc_pn(gndc); sc_puts(" tree="); sc_pn(trec); sc_puts(" human="); sc_pn(humc); sc_puts("\n" as *u8)
146 // T1 all 4 classes present
147 var t1: i64=0
148 if skyc>1000 { if gndc>1000 { if trec>300 { if humc>200 { t1=1 } } } }
149 gv_check("T1 the composed scene carries all four classes: sky, ground, tree and human, each above its pixel floor" as *u8, t1, ctr)
150 // T2 label map aligns (labelled px == scene px, full coverage of left panel)
151 let total: i64=skyc+gndc+trec+humc
152 var t2: i64=0
153 if total>SW*SH*9/10 { t2=1 }
154 sc_puts(" labelled px="); sc_pn(total); sc_puts(" / panel="); sc_pn(SW*SH); sc_puts("\n" as *u8)
155 gv_check("T2 the label map covers the scene: at least 90 percent of the panel carries a ground-truth class (the digital-twin training shape)" as *u8, t2, ctr)
156 // T3 composition sanity: trees rest ON ground (canopy above their base), human present
157 var t3: i64=0
158 if trec>300 { if humc>200 { t3=1 } }
159 gv_check("T3 elements are composed: trees and a human stand on the procedural ground" as *u8, t3, ctr)
160 // T4 png
161 let szp: *i64=sys_mmap(16) as *i64
162 let rb: *u8=sys_read_file("knowledge/nx_procgen_scene.png\x00" as *u8, szp)
163 var t4: i64=0
164 if (rb as i64)!=0 { if szp[0]>1000 { t4=1 } }
165 if (rb as i64)!=0 { sc_puts(" png bytes="); sc_pn(szp[0]); sc_puts("\n" as *u8) }
166 gv_check("T4 the scene-and-labels PNG was written and reads back over 1000 bytes" as *u8, t4, ctr)
167 return gv_verdict("nx_procgen_scene_gate" as *u8, ctr, "composed procedural scene with per-pixel ground-truth labels (Infinigen and digital-twin shape, sovereign integer); stylised, not photoreal" as *u8)
168}