render3d: ground_fill's candidate is a function of its own; solid layers with stable ids; the trample as clearing discs
ground_candidate answers (layer, chunk, band, cell) -> keep, x, z, scale, yaw, seed, wind from pure gf_* steps and the density read between them; ground_fill draws its answers with the same operations in the same order. A solid layer fills at step0 and band 0 whatever the camera, a far band drawing a stable subset (draw 7 under (step0/step_b)^2), each thing an int id from (layer, chunk, cell), listed per chunk into a caller's GroundSolids or answered by id. r3d_ground_clearing hands the trample over as discs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
740ac2a879
commit
e535879262
7 changed files with 259 additions and 19 deletions
68
packages/ludic.render3d/ground_cand.ludic
Normal file
68
packages/ludic.render3d/ground_cand.ludic
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# ground_cand.ludic — one candidate of a ground layer: (layer, chunk, band, cell) to where it stands and what it
|
||||
# draws with. The gf_* steps are pure (numbers in, a number out); ground_candidate reads the densities between
|
||||
# them, and nothing but the densities' tile cache changes. The studio's groundFill.ts is these steps.
|
||||
|
||||
# a candidate, filled by the caller's own record (made once, reused)
|
||||
export property GroundCand {
|
||||
x: float = 0.0,
|
||||
z: float = 0.0,
|
||||
scale: float = 1.0,
|
||||
yaw: float = 0.0,
|
||||
seed: float = 0.0,
|
||||
wind: float = 0.0,
|
||||
cell: int = 0, # i * 65536 + j: the hashes' fifth input
|
||||
id: int = -1 # a solid layer's stable id (ground_solid.ludic); -1 for cover
|
||||
}
|
||||
|
||||
export function gf_cell(i: int, j: int) -> int { return i * 65536 + j }
|
||||
|
||||
# a cell's corner o, moved by the jitter's draw h (k 0 for x, 1 for z)
|
||||
export function gf_along(o: float, i: int, h: float, jitter: float, step: float) -> float { return o + (float(i) + 0.5 + (h - 0.5) * jitter) * step }
|
||||
|
||||
# kept when draw 2 falls under the chance (the density, times the trample)
|
||||
export function gf_keeps(g: GroundFill, cx: int, cz: int, band: int, e: int, keep: float) -> bool { return not (gf_hash(g.layer, cx, cz, band, e, 2) >= keep) }
|
||||
|
||||
# its size from the density's G at its place, and its own draw 6
|
||||
export function gf_scale(g: GroundFill, cx: int, cz: int, band: int, e: int, gs: float) -> float {
|
||||
var sc = Math.lerp(g.scale_lo, g.scale_hi, gs)
|
||||
sc = sc * (1.0 + (gf_hash(g.layer, cx, cz, band, e, 6) * 2.0 - 1.0) * g.scale_var) * (1.0 + g.band_grow * float(band))
|
||||
return sc
|
||||
}
|
||||
|
||||
export function gf_yaw(g: GroundFill, cx: int, cz: int, band: int, e: int) -> float { return gf_hash(g.layer, cx, cz, band, e, 3) * 2.0 * PI }
|
||||
|
||||
export function gf_seed(g: GroundFill, cx: int, cz: int, band: int, e: int) -> float { return gf_hash(g.layer, cx, cz, band, e, 4) }
|
||||
|
||||
export function gf_wind(g: GroundFill, cx: int, cz: int, band: int, e: int) -> float { return Math.lerp(g.wind_lo, g.wind_hi, gf_hash(g.layer, cx, cz, band, e, 5)) }
|
||||
|
||||
# the chance at (x, z) after the trample: the game's callback, then the clearings it handed over as data
|
||||
function gf_trampled(render3d_st: mut Render3dState, keep: float, x: float, z: float) -> float {
|
||||
var k = keep
|
||||
if render3d_st.gd_trample_cb != null { k = k * render3d_st.gd_trample_cb(x, z) }
|
||||
if render3d_st.gd_clear_n > 0 { k = k * ground_clear_at(render3d_st, x, z) }
|
||||
return k
|
||||
}
|
||||
|
||||
# cell (i, j) of chunk (cx, cz) at `band` - the chunk's corner (x0, z0), its side `size` - into `out`: true when
|
||||
# one stands there
|
||||
export function ground_candidate(render3d_st: mut Render3dState, g: GroundFill, cx: int, cz: int, band: int, i: int, j: int, x0: float, z0: float, size: float, out: GroundCand) -> bool {
|
||||
let step = gf_step(g, band)
|
||||
if step <= 0.0 { return false }
|
||||
let e = gf_cell(i, j)
|
||||
let px = gf_along(x0, i, gf_hash(g.layer, cx, cz, band, e, 0), g.jitter, step)
|
||||
let pz = gf_along(z0, j, gf_hash(g.layer, cx, cz, band, e, 1), g.jitter, step)
|
||||
if px < x0 or px >= x0 + size or pz < z0 or pz >= z0 + size { return false }
|
||||
var keep = ground_density_at(render3d_st, g.layer, px, pz, 0)
|
||||
if keep <= 0.0 { return false }
|
||||
if g.trample { keep = gf_trampled(render3d_st, keep, px, pz) }
|
||||
if not gf_keeps(g, cx, cz, band, e, keep) { return false }
|
||||
out.x = px
|
||||
out.z = pz
|
||||
out.cell = e
|
||||
out.id = -1
|
||||
out.scale = gf_scale(g, cx, cz, band, e, ground_density_at(render3d_st, g.layer, px, pz, 1))
|
||||
out.yaw = gf_yaw(g, cx, cz, band, e)
|
||||
out.seed = gf_seed(g, cx, cz, band, e)
|
||||
out.wind = gf_wind(g, cx, cz, band, e)
|
||||
return true
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue