ludic/packages/ludic.render3d/terrain_height_file.ludic

59 lines
2.8 KiB
Text

# terrain_height_file.ludic — the file scratch the terrain's questions read a tile through when it is not
# resident (ter_h, ter_o), so a question never takes a slot: who asks and in what order leaves the cache
# as the loaders put it. terrain_height_file stays as the name callers wrote against; it is terrain_height.
const TF_KEEP: int = 4 # tiles the scratch keeps: a texel square at a corner spans four
export function terrain_height_file(render3d_st: mut Render3dState, x: float, z: float) -> float { return terrain_height(render3d_st, x, z) }
# the scratch entry holding tile t's heights, read from the file (as tt_decode reads them) when none does
function tf_entry(render3d_st: mut Render3dState, t: int) -> int {
for e in 0 .. TF_KEEP { if render3d_st.tf_tile[e] == t + 1 { return e } }
let e = render3d_st.tf_next
render3d_st.tf_next = (e + 1) % TF_KEEP
let n2 = TT_TEX * TT_TEX
let raw = render3d_st.tf_raw
file_seek(render3d_st.tt_file, render3d_st.tt_hoff + t * n2 * 2, 0)
file_read(render3d_st.tt_file, data_of(raw), n2 * 2)
let lo = render3d_st.tt_tab[t * 2]
let step = render3d_st.tt_tab[t * 2 + 1]
for i in 0 .. n2 { render3d_st.tf_h[e * n2 + i] = lo + float(raw[i * 2] | (raw[i * 2 + 1] << 8)) * step }
render3d_st.tf_tile[e] = t + 1
return e
}
# ... and of its photograph (the scratch sized to the map's tiles when they were opened, tf_size)
function tfo_entry(render3d_st: mut Render3dState, t: int) -> int {
for e in 0 .. TF_KEEP { if render3d_st.tfo_tile[e] == t + 1 { return e } }
let e = render3d_st.tfo_next
render3d_st.tfo_next = (e + 1) % TF_KEEP
let o2 = render3d_st.tt_oside * render3d_st.tt_oside
let raw = render3d_st.tf_raw
file_seek(render3d_st.tt_file, render3d_st.tt_ooff + t * o2 * 3, 0)
file_read(render3d_st.tt_file, data_of(raw), o2 * 3)
for i in 0 .. o2 { render3d_st.tfo_px[e * o2 + i] = (raw[i * 3] << 16) | (raw[i * 3 + 1] << 8) | raw[i * 3 + 2] }
render3d_st.tfo_tile[e] = t + 1
return e
}
# the photograph's scratch and the read buffer made for `side` texels a tile, once a size
@alloc_ok("a map being loaded: the questions' photograph scratch, once a size")
function tf_size(render3d_st: mut Render3dState, side: int) -> void {
if len(render3d_st.tfo_px) < TF_KEEP * side * side {
free(render3d_st.tfo_px)
render3d_st.tfo_px = words(TF_KEEP * side * side)
}
if len(render3d_st.tf_raw) < side * side * 3 {
free(render3d_st.tf_raw)
render3d_st.tf_raw = buffer(side * side * 3)
}
}
# the scratch forgotten: the tiles' file closed or replaced (another map's tile t is another tile)
function tf_forget(render3d_st: mut Render3dState) -> void {
for e in 0 .. TF_KEEP {
render3d_st.tf_tile[e] = 0
render3d_st.tfo_tile[e] = 0
}
render3d_st.tf_next = 0
render3d_st.tfo_next = 0
}