code wiki / (root) / nx_indoor.nx

nx_indoor.nx source

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