scatter3dplugin
Trees, grass and boulders, where each stands a pure function of its cell.
Putting it in a scene
List it after terrain3d, whose ground it stands on, and before render3d. scatter3d has no row: where every instance stands is worked out from its cell, the same on the server and every seat, and a child scene inherits world.scatter3d from the manager scene. Until the land has loaded nothing is drawn.
"plugins": ["loader", "scenemanager", "player", "terrain3d", "scatter3d", "render3d"],
"world": {
"loader": { "assets": { "firs": { "type": "model", "url": "/games/mygame/assets/firs.glb", "preload": true } } },
"scatter3d": {
"mods": { "ground": "terrain3d", "land": "terrain3d" },
"cutout": 0.5,
"coverage": 0.3,
"budget": 3,
"remember": 50000,
"packs": {
"firs": {
"asset": "firs",
"rows": { "tall": { "weight": 3, "solid": 0.4, "tall": 14 }, "short": { "weight": 1, "solid": 0.3, "tall": 8 } },
"cell": 10, "reach": 400, "seed": 11, "lods": [60, 160], "shadow": 120, "leaf": 0.6,
"density": 0.4,
"rules": [{ "q": "height", "lo": 105, "hi": 28 }, { "q": "slope", "lo": 0.5, "hi": 0.3 }],
"clearing": 30, "size": [0.8, 0.5], "vary": 0.15
},
"rocks": {
"shape": { "detail": 2, "lumpy": [0.8, 0.4], "squash": 0.6 },
"colour": "#7d7a72",
"rows": { "a": { "weight": 1, "solid": 0.9, "tall": 0.6 }, "b": { "weight": 1, "solid": 0.9, "tall": 0.6 } },
"cell": 14, "reach": 300, "seed": 4, "lods": [120], "shadow": 80, "leaf": 0,
"density": 0.15, "rules": [{ "q": "slope", "lo": 0.1, "hi": 0.3 }], "biomes": { "tundra": 1, "forest": 0.4 },
"clearing": 20, "size": [0.6, 1.4], "vary": 0.1
}
}
},
"terrain3d": { "mods": { "ready": ["scatter3d"] } }
}
Properties
Read from world.scatter3d. A change to any number rebuilds the field.
.mods : { ground, land, hollows? }
The plugins whose ground the server and the page place on, and the plugins whose boxes clear instances (see Mods).
.cutout : number
The alpha at which a model's blended materials are cut, 0 to 1. Every blended material becomes an alpha-tested card, written to depth. A masked material keeps its own cutoff.
.coverage : number
How much a card's alpha gains per mip level its texture is read at, so far leaves do not thin to sticks as the texture shrinks: alpha × (1 + level × coverage).
.budget : number
Milliseconds a frame the page may spend placing cells newly in reach, at least one cell a frame. Cells nearest the camera go first. Where terrain3d lends its workers, cells are placed there and the budget bounds nothing.
.remember : number
How many cells the server keeps per scene for solids, a whole number above 0. Past it, the one placed longest ago is dropped and placed again, the same, when asked for.
.hollows : number
With a hollows mod, the most boxes cleared at once, the ones nearest the camera. A whole number above 0.
.packs : { [name]: pack }
Each pack is a grid of square cells, at most one instance a cell, drawn round the camera out to its reach.
Packs
What is drawn
| Key | Meaning |
|---|---|
asset or shape | Exactly one. asset is a loader model entry; shape makes boulders (below). |
rows | Name to { weight, solid?, tall? }: a row of the model, or a variant of the shape. Rows are picked by weight; a row of weight 0 is never drawn. |
rows.solid | Makes each instance a circle of radius solid × size metres that bodies walk round and cover hides behind. |
rows.tall | How high that solid stands over the ground, tall × size metres, for shots along a line. A solid with none stands without end. |
colour, surface | A shape pack's sRGB colour, and its optional rock surface (below). |
A model pack's meshes are named <row>-<lod>, or <row>-<lod>-<part> for a LOD in several parts, such as tall-0 and tall-1-leaves. A row that is drawn needs a mesh for every LOD. Every LOD of a row is moved so LOD 0's lowest point is on the ground and its middle on the instance's point.
Where it grows
Cell (i, j) covers [i·cell, (i + 1)·cell) across x and z. The instance's point is jittered over the whole cell. It is kept when a random value for the cell falls under the keep: density × the painted surface's cover × every rule's ramp × the biomes' weight.
| Key | Meaning |
|---|---|
cell | Metres: the width of a cell, above 0. |
seed | The seed of the pack's random values. Two packs with one seed and one cell size stand on the same points. |
density | The share of cells kept on open ground, 0 to 1. |
rules | [{ q, lo, hi }], ramps over terrain3d's land record, each multiplying the keep. An inverted ramp (lo > hi) on height is a treeline. layer:<name> is the weight terrain3d's ground draws that texture layer at, so { "q": "layer:meadow", "lo": 0.5, "hi": 0.85 } places on the meadow that is drawn, and surface:<name> is that surface's painted weight. A surface whose cover is 0, such as a road, keeps nothing. |
biomes | Optional, biome name to a weight: the pack grows at its weight in each biome it names, none in one it leaves out, and thins across their borders. |
clearing | Metres from the origin inside which nothing is kept. |
Each instance
| Key | Meaning |
|---|---|
size | [base, spread]: an instance's scale is base plus a random share of spread. |
vary | How far an instance's grey tint strays from 1, either way. |
Each instance is turned to a random yaw, tilted toward the ground's slope and sunk until it touches. How far it leans is its foot's width over its height, at most 1: a tussock lies along the slope and a fir stands up straight.
How it is drawn
| Key | Meaning |
|---|---|
reach | Metres from the camera the pack is drawn out to. |
lods | Metres, rising from above 0 to under reach: the pack is drawn in lods.length + 1 square shells round the camera's cell. Shell k reaches ⌈lods[k] / cell⌉ cells and the last ⌈reach / cell⌉, and LOD k is drawn in shell k. An instance changes LOD only when the camera crosses into another cell. |
shadow | Metres: a shell that ends within this casts shadows. Every shell receives them. |
leaf | 0 to 1: how far a card's normal is bent toward the sky, so a crown of cards is lit, and takes snow, as one mass. |
Boulders
shape: { detail, lumpy: [base, range], squash }. Each row is a variant: a sphere of radius 1 subdivided detail times, each vertex pushed out to between base and base + range of itself, then its height multiplied by squash, shaded face by face. Its middle is at the ground, so half of it is buried.
Without a surface, it is drawn in colour. A surface mixes two noises, n = a × noise at broad + b × noise at fine, with mix [a, b] and the frequencies in cycles a metre:
| Key | Meaning |
|---|---|
lift, range | The colour is multiplied by 1 + range × (n − 0.5), mixed in by lift. |
bump | The normal bent as by a height of n × bump / fine metres, so a bump looks the same at any fine. |
moss | { from, to, amount, up: [lo, hi], colour }: moss of that colour where the noise rises from from to to, times amount, only on faces whose normal points up between lo and hi. |
rough | The roughness. |
Methods
Rules
From #plugins/scatter3d/scatter3d.sim.ts.
solids( w, x, z, r, ground ) : { x, z, radius, tall? }[]
Every kept instance of a row with solid whose circle reaches within r metres of (x, z). tall is given when the row gives one. A stroke on the ground drops the cells it reaches, so they are placed again on the new ground.
placed( w ) : ground
The ground mods.ground names, to hand to solids or place. Throws when the scene names none.
place( pack, i, j, ground ) : { i, j, x, z, row, size, yaw, tint } | undefined
Cell (i, j)'s instance, its point in metres and its yaw in radians, or undefined when the cell is refused.
On the page
Through plugins.scatter3d.
solids( x, z, r ) : { x, z, radius, tall? }[]
The same as the rule's, over this page's land.
ready( ) : boolean
Whether every cell in reach of terrain3d's prepared place is placed. True with no place in hand.
packs( ) : { [name]: object }
Each built pack: at, the camera's cell; held, its cells; pending, the cells waiting to be placed; looks, its instanced meshes by "<row> <shell>"; models, each drawn row's LODs with its foot, edge, rise and lean; and ahead, the prepared place's cells.
cellKey( i, j ) : number
The key a cell is held under in held.
Mods
Name them in world.scatter3d.mods.
- terrain3d
groundon the server andlandon the page: the height, the painted cover, the record ramps and what has changed. List terrain3d before scatter3d. - box3dvehicle
hollows: a car's body and wheels, so grass it stands in is not drawn through it.
Used by
- terrain3dWaits for scatter3d's
readybefore a prepared place is done. - cover3dFinds cover behind its solid instances.
- walkerWalks bodies round its solid instances.
- hitscan3dStops shots at its solid instances, up to their
tall.