map_scatter
Rule-based object scattering library with field-graph evaluation and sampling.

What is it?
map_scatter helps you fill 2D worlds (or a 2D projection of 3D) with lots of small things - vegetation, props, resources, decals, spawn points - quickly and reproducibly.
How it works (short)
Three parts:
- Fields (where things may appear): numbers per position built from textures, distances, and simple operations like thresholds or masks.
- Sampling (how candidates are spread): Poisson disk/blue‑noise, jittered grid, low‑discrepancy (Halton), best‑candidate, clustered, etc.
- Layers (in what order categories are placed): later layers can avoid or reuse earlier results via overlays/masks.
Field graphs compile to a program and run in chunks with caching for stable results.
Links:
- Examples: https://github.com/morgenthum/map_scatter/blob/main/crates/map_scatter_examples/README.md
- Architecture: ./ARCHITECTURE.md
Highlights
- Field graph authoring and compilation into an efficient program
- Chunked evaluation with raster caching for speed
- Multiple sampling strategies for candidate generation
- Per-layer selection strategies (weighted random, highest probability)
- Optional overlay generation to feed subsequent layers
- Event stream for inspection, logging, and tooling
Use cases
Use map_scatter when you need to place many small items in a 2D domain (or a 2D projection of 3D) and still control:
- placement rules (masks, thresholds, gradients)
- density and spacing per kind
- layer ordering and interaction
- determinism and runtime cost
Examples:
- Open-world vegetation: trees first, bushes avoid trees, herbs fill gaps; tweak textures or thresholds and rerun with the same seed.
- City dressing: lamps along roads, planters in lit areas, clutter where space remains; overlays keep layers from colliding.
- Dungeon population: camps in large rooms, enemies avoid camps, rare loot in dead ends with minimum spacing.
Examples
See the example crate for curated demos you can run locally.
Architecture
For a high-level architecture overview, see ARCHITECTURE.md.
Status
Active development; API may evolve between minor releases.
Quick Start
Add the dependency:
[]
= "0.3"
= "0.9"
= { = "0.30", = ["mint"] }
= "0.5"
Hello, scatter:
use Vec2;
use ;
use *;
Observing events:
use ;
use *;
Performance Notes
- Chunked evaluation: Keeps working sets small and cache-friendly.
- Raster cell size and chunk extent control performance/quality trade-offs.
- Field programs are cached and reused per (Kind, Chunk).
- Overlays are generated only when configured on the layer.
API Tips
- Bring common types into scope with:
use *; - Start simple: one kind with a constant Probability field, then introduce gates/overlays.
- Tune
RunConfig:domain_center: shift the evaluated window in world space (useful for streaming chunks)chunk_extent: larger chunks reduce overhead but can increase evaluation costraster_cell_size: smaller cells improve accuracy at higher costgrid_halo: extra cells for filters/EDT at chunk borders
- Overlays: bridge layers by enabling
with_overlay, then refer to the registered texturemask_<layer_id>in subsequent field graphs.
Compatibility
- 2D domains (Vec2 positions); usable for 3D by feeding height/slope textures and augmenting the 2D placement with a height component in your engine
- No engine lock-in; pair with your renderer/tooling of choice
- Integrates well with
tracingfor diagnostics - Use
randRNGs; examples commonly useStdRng
Benchmarks
Some micro-benchmarks are included: