stream_capture(s, cx, cz, band) points the stream at a chunk of its own (made on the first capture), calls the registered r3d_stream_fill for that cell and band, and returns how many instances it emitted; stream_captured(i, k) reads them from stream_scratch. Build-time only; nothing in a frame calls it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
46 lines
2.6 KiB
Text
46 lines
2.6 KiB
Text
# stream_baked.ludic — a stream filled from baked chunks instead of generated ones (plan 26 of
|
|
# maroon-lake). The bake stores every instance of a kind once per 64 m chunk, at full density and in a
|
|
# shuffled order, so a distance band draws a PREFIX of it: a nearer band holds everything a farther one
|
|
# does. A record's layout is place_rec.ludic's.
|
|
|
|
# the stream's cells laid on the baked chunks' grid: `size` metres from the corner (ox, oz)
|
|
export function stream_set_grid(s: Stream, ox: float, oz: float) -> void {
|
|
s.ox = ox
|
|
s.oz = oz
|
|
}
|
|
|
|
# the first `keep` of a chunk's `count` records (format fmt, place_rec.ludic) at byte `at` of recs
|
|
# emitted into the chunk being filled
|
|
export function stream_emit_baked(render3d_st: mut Render3dState, s: Stream, recs: []byte, at: int, fmt: int, count: int, keep: int, x0: float, z0: float, y_base: float, lo: float, hi: float) -> void {
|
|
let v = render3d_st.sb_rec
|
|
for i in 0 .. min(keep, count) {
|
|
prec_get(fmt, recs, at, i, x0, z0, s.size, y_base, lo, hi, v)
|
|
stream_emit(render3d_st, s, v[0], v[1], v[2], v[3], Math.atan2(v[4], v[5]), v[6], v[7])
|
|
}
|
|
}
|
|
|
|
# how many of a chunk's records a band keeps: all at band 0, then the share each band out had of the
|
|
# generated density (the caller's table), rounded so a band is never empty where the chunk is not
|
|
export function stream_band_keep(count: int, share: float) -> int {
|
|
if count == 0 { return 0 }
|
|
return max(1, min(count, int(float(count) * share + 0.5)))
|
|
}
|
|
|
|
# ---- the bake's capture -----------------------------------------------------------------------
|
|
# The game's own fill for chunk (cx, cz) at a band, run outside any frame into a chunk of its own: what
|
|
# the bake records. The instances are left in stream_scratch (INST_FLOATS each: x, y, z, scale, sin yaw,
|
|
# cos yaw, seed, wind; stream_captured reads them) and their count is returned. Build-time only.
|
|
@alloc_ok("a bake's capture chunk, made on the first capture")
|
|
export function stream_capture(render3d_st: mut Render3dState, s: Stream, cx: int, cz: int, band: int) -> int {
|
|
if render3d_st.stream_scratch == null { render3d_st.stream_scratch = floats(STREAM_CHUNK_MAX * INST_FLOATS) }
|
|
if render3d_st.stream_capture_c == null { render3d_st.stream_capture_c = new Chunk }
|
|
let c = render3d_st.stream_capture_c
|
|
c.key = stream_key(cx, cz, band); c.count = 0; c.off = -1; c.used = 0
|
|
s.cur = c
|
|
r3d_stream_fill(render3d_st, s, cx, cz, band)
|
|
s.cur = null
|
|
return c.count
|
|
}
|
|
|
|
# field k (0 .. INST_FLOATS - 1) of captured instance i
|
|
export function stream_captured(render3d_st: Render3dState, i: int, k: int) -> float { return render3d_st.stream_scratch[i * INST_FLOATS + k] }
|