Files
2026-09-25 17:02:24 +03:00

30 lines
1.5 KiB
Go

package detail
import "salty/terrain/internal/manifest"
// MarginCells is the overlap a tile must carry for the particle pass, in detail cells.
//
// Rule 2 of the tiling plan says to size a margin by how far the pass can move material, and for droplets
// that is not simply the lifetime. Within one round a droplet travels at most its lifetime, plus one cell for
// the cut brush. Across rounds the error compounds: a droplet in round two reads heights the round-one
// droplets moved, so the cut edge's influence walks a lifetime further in with every round.
//
// Taking that literally would make the margin `rounds * lifetime`, which at the defaults is 640 cells against
// a 2500-cell tile. Measured instead, at lifetime 12 and 8 rounds (TestHowFarTheCutEdgeReachesIn), the worst
// difference between a tile and the same ground in one whole run falls off much faster than that:
//
// cells in from the cut edge: 0 4 8 12 16 20 24 32 40
// worst difference, metres: 7.97 2.53 0.72 0.49 0.44 0.18 0.03 0.00 0.00
//
// It is the first lifetime that carries almost all of it, and by three the error is gone - a droplet has to be
// unlucky in the same way several rounds running for it to keep propagating, and that stops happening. Three
// lifetimes plus the brush is the margin, which at the default lifetime of 40 is 122 detail cells, 244 m, or
// about five per cent of a 5 km tile on each side.
func MarginCells(cfg manifest.Particle) int {
life := cfg.Lifetime
if life < 1 {
life = 1
}
return 3*life + 2
}