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

51 lines
2.3 KiB
Go

package detail
// Classes is what the painted class asks of the detail passes, per cell, already blended.
//
// It exists because two classes can have the same uplift rate and the same erodibility - which is everything
// the geology grid knows about them - and still be completely different ground. A desert and a wet lowland
// are both "low, slowly rising"; what separates them is at two metres, in how much running water crosses
// them, how sharp their ledges stay and how much of them is dune.
//
// **Four fields rather than a class index and a lookup table**, which is what this was. The index is the
// right thing to carry - a class is a name, and a name is never interpolated - but the *numbers* it stands
// for are quantities, and quantities interpolate. Kept as a lookup, a desert meeting a lowland changed from
// seven metres of dune amplitude to two in the width of one cell, along a line the painter drew with a mouse,
// and it read exactly as what it was: a boundary in a picture rather than a change in the ground. Blended,
// the same boundary is a few hundred metres of one becoming the other, which is what the edge of a sand sea
// looks like from the ground.
//
// The blending happens where the fields are built (see planet.blendedClasses), because that is where the
// class raster and the tile's margin both are; by the time a pass reads one it is just a number per cell.
//
// Nil means every cell uses the pipeline's own numbers, which is what happens on a template whose legend
// overrides nothing.
type Classes struct {
Droplets []float32 // per cell: droplets a cell spawns
AmpLo []float32 // per cell: detail noise amplitude on flat ground
AmpHi []float32 // per cell: and on steep ground
Contrast []float32 // per cell: strata hardness contrast
}
// droplets, amp and contrast read a cell, falling back to the uniform value when there is no table.
func (c *Classes) droplets(i int, def float64) float64 {
if c == nil || c.Droplets == nil {
return def
}
return float64(c.Droplets[i])
}
func (c *Classes) amp(i int, defLo, defHi float64) (float64, float64) {
if c == nil || c.AmpLo == nil {
return defLo, defHi
}
return float64(c.AmpLo[i]), float64(c.AmpHi[i])
}
func (c *Classes) contrast(i int, def float64) float64 {
if c == nil || c.Contrast == nil {
return def
}
return float64(c.Contrast[i])
}