# layer_chunks.ludic — a fixed layer (trees, boulders, stones) held as the baked chunks that are in, not # the whole map: a slab per chunk in the layer's instance list, put when the ring brings the chunk in # and dropped when it goes, the list re-uploaded at most once a frame. A record's layout is place_rec.ludic's. # the layer made ready for chunks of an n x n grid: its slab index, once at map load, and nothing in it @alloc_ok("a map being loaded: a layer's chunk index, once") export function layer_chunks_begin(l: Layer, n: int) -> void { if l.ck_off == null or len(l.ck_off) != n * n { if l.ck_off != null { free(l.ck_off); free(l.ck_cnt) } l.ck_off = words(n * n); l.ck_cnt = words(n * n) } if l.lc_rec == null { l.lc_rec = floats(INST_FLOATS) } for i in 0 .. n * n { l.ck_off[i] = -1; l.ck_cnt[i] = 0 } l.count = 0 layer_chunks_changed(l) } # chunk `id`'s `count` records (format fmt, place_rec.ludic) at byte `at` of recs put into the layer, # replacing what it had; as many as the layer has room for export function layer_chunk_put(l: Layer, id: int, recs: []byte, at: int, fmt: int, count: int, size: float, x0: float, z0: float, y_base: float, lo: float, hi: float) -> void { if l.ck_off == null or id < 0 or id >= len(l.ck_off) { return } if l.ck_off[id] >= 0 { layer_chunk_drop(l, id) } let n = min(count, l.cap - l.count) if n <= 0 { return } layer_room(l, l.count + n) for i in 0 .. n { prec_get(fmt, recs, at, i, x0, z0, size, y_base, lo, hi, l.lc_rec) for k in 0 .. INST_FLOATS { l.inst[(l.count + i) * INST_FLOATS + k] = l.lc_rec[k] } } l.ck_off[id] = l.count l.ck_cnt[id] = n l.count += n layer_chunks_changed(l) } # chunk `id`'s slab taken out: the instances after it move down, and the slabs after it with them export function layer_chunk_drop(l: Layer, id: int) -> void { if l.ck_off == null or id < 0 or id >= len(l.ck_off) or l.ck_off[id] < 0 { return } let off = l.ck_off[id] let n = l.ck_cnt[id] for k in (off + n) * INST_FLOATS .. l.count * INST_FLOATS { l.inst[k - n * INST_FLOATS] = l.inst[k] } for c in 0 .. len(l.ck_off) { if l.ck_off[c] > off { l.ck_off[c] = l.ck_off[c] - n } } l.ck_off[id] = -1 l.ck_cnt[id] = 0 l.count -= n layer_chunks_changed(l) } # the layer's list changed: the GPU cull's buffers and the view's partition are made again next frame. # A layer on the CPU path keeps the grid it had (a baked layer is meant for the GPU cull). function layer_chunks_changed(l: Layer) -> void { l.g_on = false l.g_n = -1 l.view_gen = -1 }