30 lines
1.5 KiB
Go
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
|
|
}
|