Generation

Cell filters & automata

The CellFilter algebra — composable per-cell scalar functions — plus cellular automata rules and distance fields over grid layers.

A CellFilter is a function (grid, x, y, rotation) → number. Every filter in the library extends this base class, has a static .from(...) factory, and must be initialize(grid, seed) before use. Filters compose — the output of one becomes the input of the next — so complex terrain masks, density fields, and probability functions are all built from the same small set of primitives.

Source: @woosh/meep-engine/src/generation/filtering/

Filter lifecycle

import { CellFilter } from "@woosh/meep-engine/src/generation/filtering/CellFilter.js";

// All filters share this interface:
filter.initialize(grid, seed);  // called once; sets __initialized = true
const v = filter.execute(grid, x, y, rotation);  // called per cell
filter.finalize();              // resets __initialized for re-use

ensureInitialized(grid, seed) is a safe guard that calls initialize only if not yet initialized; composable filters call this on their children before executing.

Complete filter catalog

The library groups into seven families. The map below is a quick index; the tables that follow give every class and its import path.

CellFilter algebraConstants and readsArithmeticRange and interpolationSpatial convolutionNoiseLookup and gradientBoolean logic

Constants and layer reads

ClassImport path (under filtering/)Description
CellFilterLiteralFloatnumeric/CellFilterLiteralFloat.jsReturns a constant. CellFilterLiteralFloat.ONE and .ZERO are pre-built singletons.
CellFilterSampleLayerLinearnumeric/sampling/CellFilterSampleLayerLinear.jsBilinear sample of a named GridDataLayer.
CellFilterSampleLayerCubicnumeric/sampling/CellFilterSampleLayerCubic.jsBicubic sample of a named GridDataLayer.
CellFilterLiteralBooleanboolean/CellFilterLiteralBoolean.jsReturns a constant boolean (as 0/1).

Arithmetic

ClassImport pathOperation
CellFilterAddnumeric/math/algebra/CellFilterAdd.jsleft + right
CellFilterSubtractnumeric/math/algebra/CellFilterSubtract.jsleft - right
CellFilterMultiplynumeric/math/algebra/CellFilterMultiply.jsleft * right
CellFilterDividenumeric/math/algebra/CellFilterDivide.jsleft / right
CellFilterNegatenumeric/math/algebra/CellFilterNegate.js-value
CellFilterAbsolutenumeric/math/CellFilterAbsolute.jsMath.abs(v)
CellFilterPowernumeric/math/CellFilterPower.jsMath.pow(value, power)
CellFilterMax2numeric/math/CellFilterMax2.jsmax(a, b)
CellFilterMin2numeric/math/CellFilterMin2.jsmin(a, b)
CellFilterOneMinusnumeric/math/CellFilterOneMinus.js1 - v

Range and interpolation

ClassImport pathDescription
CellFilterClampnumeric/math/CellFilterClamp.jsclamp(value, min, max)
CellFilterSaturatenumeric/math/CellFilterSaturate.jsclamp(v, 0, 1)
CellFilterStepnumeric/math/CellFilterStep.jsReturns 0 if x < edge, else 1
CellFilterLerpnumeric/math/CellFilterLerp.jslerp(a, b, f) — linear interpolation
CellFilterInverseLerpnumeric/math/CellFilterInverseLerp.jsInverse of lerp: given a, b, value, returns f
CellFilterSmoothStepnumeric/math/CellFilterSmoothStep.jsGLSL smoothstep(edge0, edge1, x) — smooth Hermite interpolation
CellFilterMembershipGeneralizedBellnumeric/math/CellFilterMembershipGeneralizedBell.jsGeneralized bell membership function `1 / (1 +
CellFilterCubicFunctionnumeric/math/poly/CellFilterCubicFunction.jsEvaluates a cubic polynomial

Spatial / convolution

ClassImport pathDescription
CellFilterDilatenumeric/complex/CellFilterDilate.js3×3 morphological dilation — returns max of the 3×3 neighborhood
CellFilterSobelnumeric/complex/CellFilterSobel.jsSobel edge-detection: magnitude of the gradient vector from the 3×3 Sobel kernel
CellFilterGaussianBlurnumeric/complex/CellFilterGaussianBlur.jsGaussian blur with configurable sigma and sample count
CellFilterFXAAnumeric/complex/CellFilterFXAA.jsFXAA anti-aliasing filter adapted from the NVIDIA algorithm
CellFilterCurvaturenumeric/complex/CellFilterCurvature.jsApproximate surface curvature at a cell, based on cross-products of neighbouring normals
CellFilterAngleToNormalnumeric/complex/CellFilterAngleToNormal.jsBuilds the surface normal of another filter and returns the angle to a fixed 3D reference vector
CellFilterDisplacednumeric/util/CellFilterDisplaced.jsSamples another filter at a position offset by two displacement filters

Noise

ClassImport pathDescription
CellFilterSimplexNoisenumeric/complex/CellFilterSimplexNoise.js2D simplex noise in [0, 1], seeded. .fractal(octaves, scale, seed, persistence, lacunarity) builds an fBm chain automatically.

Lookup and gradient

ClassImport pathDescription
CellFilterLookupTablenumeric/complex/CellFilterLookupTable.jsRemaps the source filter through a ParameterLookupTable (1-channel LUT)
computeCellFilterGradientnumeric/process/computeCellFilterGradient.jsUtility function: computes the normalized gradient vector [dx, dy] at (x, y) using the Sobel kernel; returns false when magnitude is zero

Boolean / logic filters

ClassImport pathDescription
CellFilterAndboolean/logic/CellFilterAnd.jsleft && right (Boolean data type)

Composing filters

All binary filters have left / right children; ternary filters have a, b, c; unary filters have source. Use the static factories — they assert isCellFilter on every argument:

import { CellFilterSimplexNoise } from "@woosh/meep-engine/src/generation/filtering/numeric/complex/CellFilterSimplexNoise.js";
import { CellFilterSaturate }     from "@woosh/meep-engine/src/generation/filtering/numeric/math/CellFilterSaturate.js";
import { CellFilterLerp }         from "@woosh/meep-engine/src/generation/filtering/numeric/math/CellFilterLerp.js";
import { CellFilterLiteralFloat } from "@woosh/meep-engine/src/generation/filtering/numeric/CellFilterLiteralFloat.js";
import { CellFilterGaussianBlur } from "@woosh/meep-engine/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js";

// Fractal noise, blurred, saturated — a smooth terrain mask
const noise  = CellFilterSimplexNoise.fractal(4, 32);
const blurred = CellFilterGaussianBlur.from(noise, 3, 3);
const mask   = CellFilterSaturate.from(blurred);

// Blend two noise fields
const noiseLow  = CellFilterSimplexNoise.from(64, 64);
const noiseHigh = CellFilterSimplexNoise.from(8, 8);
const blend     = CellFilterLerp.from(noiseLow, noiseHigh, mask);

Cellular automata

CellularAutomata is the base class; subclasses override step(data, width, height) where data is a Uint8Array of the grid cells. The supplied concrete implementation is CaveGeneratorCellularAutomata:

import { CaveGeneratorCellularAutomata } from "@woosh/meep-engine/src/generation/automata/CaveGeneratorCellularAutomata.js";

const ca = new CaveGeneratorCellularAutomata();
ca.random = seededRandom(42);

// data is a Uint8Array of width*height cells, pre-filled with 0/1
for (let i = 0; i < 5; i++) {
    ca.step(data, width, height);
}

CaveGeneratorCellularAutomata applies a survival/birth rule: a live cell dies if it has fewer than 4 live neighbours (8-connected); a dead cell is born if it has more than 5 live neighbours. Running 4–6 iterations on randomly seeded data produces cave-like open regions. The GridTaskCellularAutomata generator wraps this as a task stage.

Distance fields

AreaMask computes a per-pixel unsigned distance field over a binary Sampler2D:

import { AreaMask } from "@woosh/meep-engine/src/generation/theme/AreaMask.js";

const mask = new AreaMask();
mask.resize(128, 128);

// fill mask.mask.data with 0/1 painted regions …
mask.updateDistanceField();  // fills mask.distanceField via computeUnsignedDistanceField
mask.updateBounds();         // computes the AABB2 of all set pixels

ThemeEngine uses the distance fields on AreaTheme masks to blend terrain weights at biome boundaries: when multiple themes overlap a cell, each theme’s influence is proportional to its distance-field value divided by the overlap count. See Themes, matchers & rules.

Caching

CellFilterCache wraps any filter and memoizes its output at every (x, y) for the lifetime of one initialization. Use it around expensive multi-sample filters (Gaussian blur, simplex noise chains) that are evaluated many times per cell from multiple downstream consumers.