ludic/packages/ludic.render3d/ground_clear.ludic
Orkuncakilkaya e535879262 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>
2026-09-30 15:23:53 +03:00

44 lines
1.9 KiB
Text

# ground_clear.ludic — the trample as data: clearings the game hands over (a camp's ring, a town's yard), each a
# disc trodden to `floor` inside r_in and back to full at r_out on a smoothstep. A layer with `trample` multiplies
# its chance by every clearing's; the editor draws the same discs, where it cannot see a callback.
const GD_CLEAR_MAX: int = 32
# no clearings (a map being opened, before the game hands its own)
export function r3d_ground_clearings_reset(render3d_st: mut Render3dState) -> void { render3d_st.gd_clear_n = 0 }
# a clearing at (x, z): false when GD_CLEAR_MAX are already held, or the disc is not r_in < r_out
export function r3d_ground_clearing(render3d_st: mut Render3dState, x: float, z: float, r_in: float, r_out: float, floor: float) -> bool {
if render3d_st.gd_clear_n >= GD_CLEAR_MAX or not (r_in < r_out) { return false }
let o = render3d_st.gd_clear_n * 5
render3d_st.gd_clear[o] = x
render3d_st.gd_clear[o + 1] = z
render3d_st.gd_clear[o + 2] = r_in
render3d_st.gd_clear[o + 3] = r_out
render3d_st.gd_clear[o + 4] = Math.clamp(floor, 0.0, 1.0)
render3d_st.gd_clear_n += 1
return true
}
# one clearing's share at (x, z), 0..1: `floor` inside r_in, 1 past r_out
export function gf_clear_one(cx: float, cz: float, r_in: float, r_out: float, floor: float, x: float, z: float) -> float {
let dx = x - cx
let dz = z - cz
let d2 = dx * dx + dz * dz
if d2 > r_out * r_out { return 1.0 }
let d = Math.sqrt(d2)
var t = Math.clamp((d - r_in) / (r_out - r_in), 0.0, 1.0)
t = t * t * (3.0 - 2.0 * t)
return floor + (1.0 - floor) * t
}
# every clearing's share at (x, z), multiplied in the order they were handed over
export function ground_clear_at(render3d_st: Render3dState, x: float, z: float) -> float {
var k = 1.0
for c in 0 .. render3d_st.gd_clear_n {
let o = c * 5
let cl = render3d_st.gd_clear
k = k * gf_clear_one(cl[o], cl[o + 1], cl[o + 2], cl[o + 3], cl[o + 4], x, z)
}
return k
}