code wiki / (root) / nx_indoor.nx

nx_indoor.nx source

↩ module page · 244 lines · 12060 B

1// nx_indoor.nx -- ★R8 of the Infinigen ladder: INDOOR scenes (their CVPR'24 Infinigen-Indoors track). A room 2// shell (floor/ceiling/4 walls) + procedural FURNITURE placed by a CONSTRAINT SOLVER (rule-based positions + 3// collision rejection + in-bounds) -> a valid, seed-varied furnished room, rendered by an integer AABB interior 4// raycaster (rays from a camera inside the room hit the nearest box; shaded by face + a ceiling light). The 5// constraint-solved layout is the intellectual core (their paper is about realistic arrangement). license_tier: ORIGINAL 6import "nx_syscalls.nx" 7const RM_MAGIC_6364136223846793005: i64 = 6364136223846793005 8const RM_MAGIC_1442695040888963407: i64 = 1442695040888963407 9const RM_MAGIC_2147483647: i64 = 2147483647 10const RM_MAGIC_2654435761: i64 = 2654435761 11const RM_MAGIC_1013904223: i64 = 1013904223 12const RM_MAGIC_65536: i64 = 65536 13const RM_MAGIC_1469598103934665603: i64 = 1469598103934665603 14const RM_MAGIC_1099511628211: i64 = 1099511628211 15const RM_MAGIC_2000000000: i64 = 2000000000 16const RM_MAGIC_1024: i64 = 1024 17 18const RM_W: i64 = 1000 // room x 19const RM_H: i64 = 700 // room y (height) 20const RM_D: i64 = 1200 // room z (depth) 21const IN_STR: i64 = 8 // per-box: x0,y0,z0,x1,y1,z1,color,kind (0 structure / 1 furniture) 22const IN_CAP: i64 = 64 23static IN_BOX: i64 // box list ptr 24static IN_N: i64 // box count 25static IN_NF: i64 // furniture count (subset) 26 27func in_isqrt(x: i64) -> i64 { if x<=0 {return 0} var a: i64=x; var b: i64=(a+1)/2; while b<a {a=b; b=(a+x/a)/2} return a } 28func in_iabs(v: i64) -> i64 { if v<0 {return 0-v} return v } 29func in_min(a: i64, b: i64) -> i64 { if a<b {return a} return b } 30func in_max(a: i64, b: i64) -> i64 { if a>b {return a} return b } 31func in_next(st: *i64) -> i64 { var h: i64=st[0]; h=h*RM_MAGIC_6364136223846793005+RM_MAGIC_1442695040888963407; st[0]=h; return (h>>33)&RM_MAGIC_2147483647 } 32func in_rng(st: *i64, lo: i64, hi: i64) -> i64 { return lo + in_next(st) % (hi-lo+1) } 33 34func in_addbox(x0: i64, y0: i64, z0: i64, x1: i64, y1: i64, z1: i64, col: i64, kind: i64) -> i64 { 35 let B: *i64 = IN_BOX as *i64 36 let i: i64 = IN_N*IN_STR 37 B[i]=x0; B[i+1]=y0; B[i+2]=z0; B[i+3]=x1; B[i+4]=y1; B[i+5]=z1; B[i+6]=col; B[i+7]=kind 38 IN_N = IN_N + 1 39 if kind == 1 { IN_NF = IN_NF + 1 } 40 return 0 41} 42// AABB overlap (with a small clearance margin) between box a and box b 43func in_overlap(ax0: i64, ay0: i64, az0: i64, ax1: i64, ay1: i64, az1: i64, bx0: i64, by0: i64, bz0: i64, bx1: i64, by1: i64, bz1: i64, marg: i64) -> i64 { 44 if ax1+marg <= bx0 { return 0 } 45 if bx1+marg <= ax0 { return 0 } 46 if az1+marg <= bz0 { return 0 } 47 if bz1+marg <= az0 { return 0 } 48 return 1 // overlap on x AND z (footprint) -- y ignored (stacking ok) 49} 50// try to place a furniture box: reject if it overlaps any existing FURNITURE box or leaves the room. 1=placed. 51func in_try_furniture(x0: i64, y0: i64, z0: i64, x1: i64, y1: i64, z1: i64, col: i64) -> i64 { 52 if x0 < 0 { return 0 } 53 if z0 < 0 { return 0 } 54 if x1 > RM_W { return 0 } 55 if z1 > RM_D { return 0 } 56 let B: *i64 = IN_BOX as *i64 57 var k: i64 = 0 58 while k < IN_N { 59 if B[k*IN_STR+7] == 1 { 60 if in_overlap(x0,y0,z0,x1,y1,z1, B[k*IN_STR],B[k*IN_STR+1],B[k*IN_STR+2],B[k*IN_STR+3],B[k*IN_STR+4],B[k*IN_STR+5], 6) == 1 { return 0 } 61 } 62 k = k + 1 63 } 64 in_addbox(x0,y0,z0,x1,y1,z1,col,1) 65 return 1 66} 67 68// ★build a furnished room from a seed: shell + constraint-placed furniture. 69func indoor_build(seed: i64) -> i64 { 70 if IN_BOX == 0 { IN_BOX = sys_mmap(IN_CAP*IN_STR*8) as i64 } 71 IN_N = 0; IN_NF = 0 72 let st: *i64 = sys_mmap(16) as *i64 73 st[0] = seed*RM_MAGIC_2654435761 + RM_MAGIC_1013904223; in_next(st); in_next(st) 74 // ---- shell (thin slabs, camera-outside each) ---- 75 in_addbox(0, 0-20, 0, RM_W, 0, RM_D, 92 + 70*256 + 48*RM_MAGIC_65536, 0) // floor (wood) 76 in_addbox(0, RM_H, 0, RM_W, RM_H+20, RM_D, 232 + 230*256 + 222*RM_MAGIC_65536, 0) // ceiling 77 in_addbox(0, 0, RM_D, RM_W, RM_H, RM_D+20, 206 + 198*256 + 180*RM_MAGIC_65536, 0) // back wall (cream) 78 in_addbox(0-20, 0, 0, 0, RM_H, RM_D, 198 + 190*256 + 172*RM_MAGIC_65536, 0) // left wall 79 in_addbox(RM_W, 0, 0, RM_W+20, RM_H, RM_D, 198 + 190*256 + 172*RM_MAGIC_65536, 0) // right wall 80 // rug (floor, seed-jittered center) -- placed first as a floor decal (kind 1 but overlap allowed under others? mark structure) 81 let rcx: i64 = 500 + in_rng(st, 0-60, 60) 82 let rcz: i64 = 560 + in_rng(st, 0-60, 60) 83 in_addbox(rcx-220, 0, rcz-220, rcx+220, 8, rcz+220, 150 + 60*256 + 54*RM_MAGIC_65536, 0) // rug = structure (no collide) 84 // ---- constraint-placed furniture (greedy: rule position + jitter, reject on overlap) ---- 85 // bed against back-left wall (slides along the back wall by seed) 86 let bx: i64 = 40 + in_rng(st, 0, 90) 87 let bw: i64 = in_rng(st, 420, 480) 88 in_try_furniture(bx, 0, RM_D-380, bx+bw, 170, RM_D-30, 74 + 96*256 + 150*RM_MAGIC_65536) 89 // nightstand beside the bed 90 in_try_furniture(bx+10+bw, 0, RM_D-150, bx+10+bw+90, 210, RM_D-60, 96 + 70*256 + 44*RM_MAGIC_65536) 91 // lamp on the nightstand 92 in_try_furniture(bx+20+bw, 210, RM_D-135, bx+20+bw+60, 330, RM_D-75, 230 + 210*256 + 120*RM_MAGIC_65536) 93 // dining table (center-front, seed-jittered -- wide jitter for layout variety) 94 let tcx: i64 = 400 + in_rng(st, 0, 170) 95 let tcz: i64 = 360 + in_rng(st, 0, 130) 96 in_try_furniture(tcx-130, 0, tcz-100, tcx+130, 150, tcz+100, 88 + 60*256 + 38*RM_MAGIC_65536) 97 // 4 chairs around the table (each collision-checked -> the solver keeps only the ones that fit) 98 in_try_furniture(tcx-190, 0, tcz-45, tcx-140, 200, tcz+45, 110 + 80*256 + 50*RM_MAGIC_65536) 99 in_try_furniture(tcx+140, 0, tcz-45, tcx+190, 200, tcz+45, 110 + 80*256 + 50*RM_MAGIC_65536) 100 in_try_furniture(tcx-45, 0, tcz-160, tcx+45, 200, tcz-110, 110 + 80*256 + 50*RM_MAGIC_65536) 101 in_try_furniture(tcx-45, 0, tcz+110, tcx+45, 200, tcz+160, 110 + 80*256 + 50*RM_MAGIC_65536) 102 // bookshelf against the right wall (z slides by seed) 103 let shz: i64 = 120 + in_rng(st, 0, 300) 104 in_try_furniture(RM_W-140, 0, shz, RM_W-20, 560, shz+160, 70 + 50*256 + 36*RM_MAGIC_65536) 105 // a plant in a corner 106 in_try_furniture(40, 0, 40, 150, 260, 150, 52 + 104*256 + 44*RM_MAGIC_65536) 107 return IN_NF 108} 109 110func in_n() -> i64 { return IN_N } 111func in_nf() -> i64 { return IN_NF } 112func in_box(i: i64, out: *i64) -> i64 { let B: *i64 = IN_BOX as *i64; var k: i64=0; while k<IN_STR { out[k]=B[i*IN_STR+k]; k=k+1 } return 0 } 113// count overlapping FURNITURE pairs (the constraint-validity metric; must be 0) 114func in_furniture_overlaps() -> i64 { 115 let B: *i64 = IN_BOX as *i64 116 var c: i64 = 0 117 var i: i64 = 0 118 while i < IN_N { 119 if B[i*IN_STR+7] == 1 { 120 var j: i64 = i+1 121 while j < IN_N { 122 if B[j*IN_STR+7] == 1 { 123 if in_overlap(B[i*IN_STR],B[i*IN_STR+1],B[i*IN_STR+2],B[i*IN_STR+3],B[i*IN_STR+4],B[i*IN_STR+5], B[j*IN_STR],B[j*IN_STR+1],B[j*IN_STR+2],B[j*IN_STR+3],B[j*IN_STR+4],B[j*IN_STR+5], 0) == 1 { c = c + 1 } 124 } 125 j = j + 1 126 } 127 } 128 i = i + 1 129 } 130 return c 131} 132// layout signature -- a rolling positional hash over the furniture boxes (order+position sensitive so 133// different arrangements never cancel the way a plain centroid sum would). Identical layout -> identical hash. 134func in_layout_sig() -> i64 { 135 let B: *i64 = IN_BOX as *i64 136 var s: i64 = RM_MAGIC_1469598103934665603 137 var i: i64 = 0 138 while i < IN_N { 139 if B[i*IN_STR+7] == 1 { 140 let cx: i64 = (B[i*IN_STR]+B[i*IN_STR+3])/2 141 let cz: i64 = (B[i*IN_STR+2]+B[i*IN_STR+5])/2 142 s = (s + cx) * RM_MAGIC_1099511628211 143 s = (s + cz) * RM_MAGIC_1099511628211 144 } 145 i = i + 1 146 } 147 if s < 0 { s = 0 - s } 148 return s & RM_MAGIC_2147483647 149} 150 151// ---- integer AABB interior raycaster ---- 152// ray vs one box (slab method). Returns nearest t>0 (or -1), fills nrm[0]=axis, nrm[1]=sign. 153func in_ray_box(ox: i64, oy: i64, oz: i64, dx: i64, dy: i64, dz: i64, bi: i64, nrm: *i64) -> i64 { 154 let B: *i64 = IN_BOX as *i64 155 let b0x: i64=B[bi*IN_STR]; let b0y: i64=B[bi*IN_STR+1]; let b0z: i64=B[bi*IN_STR+2] 156 let b1x: i64=B[bi*IN_STR+3]; let b1y: i64=B[bi*IN_STR+4]; let b1z: i64=B[bi*IN_STR+5] 157 var tmin: i64 = 0 - RM_MAGIC_2000000000 158 var tmax: i64 = RM_MAGIC_2000000000 159 var axmin: i64 = 0 160 // x slab 161 if dx == 0 { if ox < b0x { return 0-1 } if ox > b1x { return 0-1 } } 162 else { 163 var ta: i64 = (b0x-ox)*RM_MAGIC_1024/dx 164 var tb: i64 = (b1x-ox)*RM_MAGIC_1024/dx 165 if ta > tb { let t: i64=ta; ta=tb; tb=t } 166 if ta > tmin { tmin = ta; axmin = 0 } 167 if tb < tmax { tmax = tb } 168 } 169 if dy == 0 { if oy < b0y { return 0-1 } if oy > b1y { return 0-1 } } 170 else { 171 var ta: i64 = (b0y-oy)*RM_MAGIC_1024/dy 172 var tb: i64 = (b1y-oy)*RM_MAGIC_1024/dy 173 if ta > tb { let t: i64=ta; ta=tb; tb=t } 174 if ta > tmin { tmin = ta; axmin = 1 } 175 if tb < tmax { tmax = tb } 176 } 177 if dz == 0 { if oz < b0z { return 0-1 } if oz > b1z { return 0-1 } } 178 else { 179 var ta: i64 = (b0z-oz)*RM_MAGIC_1024/dz 180 var tb: i64 = (b1z-oz)*RM_MAGIC_1024/dz 181 if ta > tb { let t: i64=ta; ta=tb; tb=t } 182 if ta > tmin { tmin = ta; axmin = 2 } 183 if tb < tmax { tmax = tb } 184 } 185 if tmin > tmax { return 0-1 } 186 if tmin <= 0 { return 0-1 } 187 nrm[0] = axmin 188 var sgn: i64 = 1 189 if axmin == 0 { if dx > 0 { sgn = 0-1 } } 190 if axmin == 1 { if dy > 0 { sgn = 0-1 } } 191 if axmin == 2 { if dz > 0 { sgn = 0-1 } } 192 nrm[1] = sgn 193 return tmin 194} 195 196// render the furnished room from a camera inside it, looking toward +z. Writes fb (W*H). 197func indoor_render(fb: *i64, W: i64, H: i64) -> i64 { 198 let B: *i64 = IN_BOX as *i64 199 let ox: i64 = RM_W/2 200 let oy: i64 = 300 201 let oz: i64 = 0 - 250 // just outside the front (open) wall, looking in 202 let focal: i64 = 520 203 let nrm: *i64 = sys_mmap(16) as *i64 204 let bn: *i64 = sys_mmap(16) as *i64 205 var py: i64 = 0 206 while py < H { 207 var px: i64 = 0 208 while px < W { 209 var dx: i64 = px - W/2 210 var dy: i64 = H/2 - py - 40 211 var dz: i64 = focal 212 let dl: i64 = in_isqrt(dx*dx+dy*dy+dz*dz) 213 dx = dx*RM_MAGIC_1024/dl; dy = dy*RM_MAGIC_1024/dl; dz = dz*RM_MAGIC_1024/dl 214 var best: i64 = RM_MAGIC_2000000000 215 var bcol: i64 = 0 216 var bax: i64 = 1 217 var bsg: i64 = 1 218 var k: i64 = 0 219 while k < IN_N { 220 let t: i64 = in_ray_box(ox, oy, oz, dx, dy, dz, k, bn) 221 if t > 0 { if t < best { best = t; bcol = B[k*IN_STR+6]; bax = bn[0]; bsg = bn[1] } } 222 k = k + 1 223 } 224 var r: i64 = 40; var g: i64 = 42; var b: i64 = 52 // bg (shouldn't show -- room is closed) 225 if best < RM_MAGIC_2000000000 { 226 // face shading: ceiling light from above; top faces bright, side faces medium, floor gets bounce 227 var lit: i64 = 62 228 if bax == 1 { if bsg > 0 { lit = 100 } else { lit = 74 } } // up-facing bright, down-facing (ceiling underside) medium 229 if bax == 0 { lit = 78 } 230 if bax == 2 { lit = 70 } 231 // distance shading 232 let fog: i64 = in_min(best/40, 30) 233 lit = lit - fog 234 r = (bcol&255)*lit/100; g = ((bcol>>8)&255)*lit/100; b = ((bcol>>16)&255)*lit/100 235 if r>255{r=255} if g>255{g=255} if b>255{b=255} 236 } 237 fb[py*W+px] = r + g*256 + b*RM_MAGIC_65536 238 px = px + 1 239 } 240 py = py + 1 241 } 242 return 0 243} 244func in_rw() -> i64 { return RM_W }