# tosijs-3d — attribute index Every element attribute in one file, generated from source at build time. Search this before asking whether a capability exists: three separate adopter issues turned out to be features that already shipped and could not be found. Format: `module` / `tag` — then one line per attribute: `name default description` ## angle-field angle-field value = 0` / `arcOf(0, 90) — degrees, or an `Arc` label = — — drawn above the dial limits = full circle — `angle3d` only — the permitted sector; the handle CATCHES at a stop envelope = full circle — `arc3d` only — the arc may only lie within this minWidth = 0 — `arc3d` only maxWidth = 360 — `arc3d` only size = 0 — ring diameter; `0` fits the row to the panel width handleChange — live, every frame the pointer moves handleCommit — once per gesture — your undo step ## b3d-aircraft — b3d-aircraft x y z rx ry rz axes url = '' — GLB model URL (direct load — collapsed through the same canonical frame as a library load: author Blender-default, facing −Y, transforms applied) library = '' — Library type to source mesh from meshName = '' — Node name to instantiate from library player enterable = false — Whether a biped can enter ceiling hudChaseOff = false — Hide the HUD entirely in chase view. By default chase shows the HUD **without the artificial horizon** (which would contradict the real one behind the aircraft); cockpit shows everything, in-scene hudSize = 0.7 — In-cockpit HUD plane size (metres) hudForward = 1.6 — How far ahead of the pilot's eye the HUD floats (metres) maxSpeed = 50 — Normal top speed (m/s) — the cruise cap a released throttle settles at afterburnerSpeed = 75 — Speed ceiling while the throttle is held past `maxSpeed`; releasing bleeds back to `maxSpeed`. ≤ `maxSpeed` disables afterburner. acceleration = 12 — Throttle / lean authority (speed change rate) vtolSpeed = 6 — Forward ground speed splitting hover (below) from plane (above). 0 = pure aeroplane, no hover regime. reverseSpeed = 5 — How fast the craft may back up in a hover (m/s); nose up to reverse throttleRate = 0.8 — How fast the trigger moves the throttle LEVER (full travel per second) autoGear = 'on' — Find the model's gear-retract animations by NAME and run them from height above ground. `'off'` = manual (`setGear(up)`) gearAltitude = 40 — Height above ground (m) at which the gear retracts; it extends again at 60% of this (hysteresis) gearSound = '' — Optional URL played spatially at the airframe on each gear transition gearVolume = 0.6 — Volume for `gearSound` gearTime = 2.5 — Seconds for a full gear cycle lookRange = 120 — How far the right stick can swing the view (degrees each way) maxPitch = 35 — Max nose-UP attitude the stick commands (degrees) maxDive = 0 — Max nose-DOWN attitude (degrees); 0 = symmetric with `maxPitch` lookRate = 150 — Look slew rate (degrees/sec at full stick) lookReturn = 4 — How fast the view springs back to centre when released chasePitchFollow = 0 — How much airframe PITCH the chase inherits. `0` = level pivot (plane pitches within the frame); `1` = as if parented to the airframe (a climb aims the view up) chasePitchLag = 3 — How fast that inherited pitch catches up (per second) — the low-pass that keeps attitude jitter out of the chase hoverCeiling = 140 — Height above ground above which the trigger is forward thrust regardless of speed (take off vertically, then fly) and the brake can't stall you below `vtolSpeed`. Below it, slowing to a hover gives the vertical trigger back for a vertical landing. 0 = off. groundY = 0 — Assumed ground-plane height (a floor in addition to any terrain colliders) submersible = false — Pass THROUGH a water surface instead of treating it as ground. Off by default — a plane hitting the sea should crash waterDrag = 10 — Submersible only: how much thicker water is than air, as a drag multiplier. At ×10, full throttle settles at ~32% of `maxSpeed` underwater turbulence = 'on' — The weather reaches the airframe: wind makes it drift and crab, storms (storminess) and strong wind buffet it. Changes nothing in a calm scene; `'off'` ignores the weather turbulenceScale = 1 — Scales the buffeting waterTransition = 2 — Metres over which drag blends from air to water across the surface crashSpeed = 8 — Vertical impact speed (m/s) above which a ground contact is a crash weapons = 'on' — `'off'` disarms all weapons gunRate = 9 — Cannon shots/sec while `shoot` is held gunSpeed = 130 — Cannon muzzle speed (added to airspeed) gunDamage = 8 — Per-shell damage gunMode = 'direct' — `'direct'` damages what the shell passes through; `'blast'` is the old AOE gunFullRadius = 0.5 — Only for `gunMode="blast"` gunBlastRadius = 1.5 — Only for `gunMode="blast"` destroyable = 'off' — `'on'` gives the aircraft hit points and a death outcome capacity = 30 — Combat stats armor = 0 — Combat stats regenRate = 0 — Combat stats regenDelay = 0.5 — Combat stats explode = 'on' — Death outcome explodeForce = 8 — Death outcome blip = 'off' — `'on'` puts it on radar, so a missile can lock it blipProfile = 1 — Radar detectability and side faction = 'neutral' — Radar detectability and side missileSpeed = 55 — Guided-missile cruise speed missileAccel missileBoost missileTurnRate = 3 — Guided-missile agility (rad/sec) missileDamage = 30 — Missile warhead full damage bombDamage = 45 — Bomb warhead full damage lockRange = 140 — Max range to acquire a missile target lockConeDeg = 35 — Half-angle of the forward cone missiles lock within reticle reticleRange ## b3d-ambient — b3d-ambient preset = 'motes' — `motes` / `bubbles` / `rain` / `snow` / `dust` / `leaves` where = 'always' — `always` / `underwater` / `above` — emission ramps with depth, it doesn't switch count = auto — Capacity to ASK for (`auto` = what the preset's look needs). You may not get it — the scene divides a shared pool minCount = auto — Below this the effect is a lie, so it switches **off** instead. `auto` = the preset's floor (rain needs density; a few motes still read fine as motes) minTier = 'low' — Never run below this device tier, at any budget priority = 0 — Higher survives longer when the pool is squeezed. Shed lowest-first radius = 18 — Size of the box around the camera that particles spawn in lookAhead = 0.35 — Push the spawn box along the VIEW, in units of `radius` — a camera sees a frustum, not a sphere, so a centred box births most of its particles behind you (#18) lead = 0.25 — Push it along MOTION, in seconds of travel — at speed you outrun a centred box, which empties the view ahead exactly when you want it fullest (#17) speedCap = 40 — Speed (m/s) past which `lead` stops growing rate = 0 — Particles/sec (0 = derive from the preset) color = '' — Override the preset's colour size = 0 — Scale the preset's sprite size windX = 0 — World wind (rain slants, dust blows) windZ = 0 wind disabled = false — Stop emitting weather = 'off' — `'rain'` / `'snow'`: emission follows the PRECIPITATION where the viewer is (weather cells), so a storm brings its own rain; the local temperature splits rain from snow (sleet between). `'off'` = always on ## b3d-beacon — b3d-beacon x = 0 — position, used when `follow` is off or there is nothing to follow y = 0 — position, used when `follow` is off or there is nothing to follow z = 0 — position, used when `follow` is off or there is nothing to follow rx ry rz axes name = '' — what this beacon stands for, for a readout or a list size = 0.5 — cube edge, in metres width = 0 — per-axis extent; `0` means "use `size`" height = 0 — per-axis extent; `0` means "use `size`" depth = 0 — per-axis extent; `0` means "use `size`" shape = 'box' — `'box'` or `'sphere'` show = 'off' — `'on'` draws it as a wireframe — for debugging, not for play follow = 'on' — track the element this is nested in, rather than its own `x`/`y`/`z` ## b3d-biped — b3d-biped x y z rx ry rz axes url = '' — GLB model URL skin = '' — Optional albedo texture URL applied to the `skin` material (reskin) scale = 1 — Uniform scale applied to the loaded model player = false — Whether this biped receives input cameraType = 'none' — `'follow'`, `'xr'`, or `'none'` animation = '' — Current animation state name animationSpeed = 1 — Playback speed multiplier (0–2) initialState turnSpeed = 180 — Degrees per second forwardSpeed = 2 — Walk speed runSpeed = 5 — Sprint speed backwardSpeed = 1 — Backward speed cameraHeightOffset = 1 — Camera height above target cameraTargetHeight = 0.75 — Height of the point the camera looks at cameraMinFollowDistance = 2 — Closest follow distance cameraMaxFollowDistance = 5 — Furthest follow distance groundY eyeHeight lookRate aiming aimFreeYaw aimMaxYaw maxLookPitch eyeForward invertLookY cameraMinHeight jumpSpeed sneakSpeed strafeSpeed climbReach wadeDepth strafing buoyancy ## b3d-black-hole — b3d-black-hole radius = 10 — Event horizon radius diskInnerRadius = 1.5 — Inner edge of accretion disk (multiple of radius) diskOuterRadius = 4.0 — Outer edge of accretion disk (multiple of radius) diskBrightness = 1.5 — Accretion disk emissive brightness rotationSpeed = 0.3 — Disk rotation speed (rad/sec) lensing = 'on' — Show gravitational lensing ring photonRing = 'on' — Show photon ring at event horizon photonRingBrightness = 2.0 — Photon ring glow intensity wireframe = false — Debug wireframe seed = 12345 — Noise seed for disk turbulence subdivisions = 64 — Mesh detail level (lower = faster) ## b3d-button — caption textColor fontSize x y z ## b3d-car — b3d-car x y z rx ry rz axes url = '' — GLB model URL enterable = false — Whether a biped can enter this vehicle maxSpeed = 15 — Maximum forward speed acceleration = 8 — Acceleration rate braking = 15 — Braking rate turnRate = 90 — Degrees per second at full speed friction = 3 — Deceleration when coasting ## b3d-cloud-deck b3d-cloud-deck altitude = 140 — Height of the deck. Moving it is ONE number size = 14000 — World extent of the deck. Big enough to reach the horizon — a flat grid is nearly free subdivisions = 64 — Grid resolution — see "A grid, not a quad" coverage = 0.5 — Clear `0` → solid `1` → thickening to `2`. LIVE, and shared with the shadow thickenDepth = 900 — MAX thickening — how far the cloud TOP rises above `altitude` at `coverage: 2` cirrus = 0 — Rounded heaps `0` → long wispy streaks at `±1`: positive streaks ALONG the wind heading, negative ACROSS it. Rebakes the field wind = 8 — Metres per second the deck drifts. Nothing rebakes windHeadingDeg = 0 — Which way it drifts — and the direction cirrus streaks run evolve = 0.5 — How fast shapes change, `0` rigid → `1` restless follow = 'on' — Keep the deck centred under the camera. A deck is finite; the world is not ambientGloomBelow = 0.7 — `transmission` below which the AMBIENT fill starts to go. `0` disables ambientGloom = 0.45 — How far the ambient may be taken down sunGloomBelow = 0.25 — `transmission` below which the SUN starts to go — later than the ambient, on purpose sunGloom = 0.65 — How far the sun may be taken down at zero transmission localRise = 1200 — How far a local weather field can lift the cloud TOP, at `coverage: 2`. Large because the orographic field is attenuated at massif scale — see the attribute note stormRise = 0 — Opt-in STORM TOWER: how far the top skin rises over a cell whose coverage passes 1 (domed). Off by default: a storm is more cover and lightning, not geometry of its own — lightning lights the underside from below, the whiteout from inside, and the top from above localCoverage = 1 — How much a unit of local weather adds to `coverage`. What the field does BELOW an overcast orographic = 0 — Cloud gathers over high ground, `0…1`: most over RIDGES (ground above its surroundings), some over high plateaus, measured from the SEA (the scene's water surface), so a high sea does not make all land a mountain. Needs a terrain in the scene orographicPeak = 260 — Height ABOVE THE SEA at which `orographic` is at full strength shadows = 'on' — Cloud shadows on the ground shadowResolution = 0 — Shadow texture size. Deliberately coarser than the cloud — a soft cue does not need the detail shadowRange = 6000 — Width in metres of the shadow window, centred on the camera shadowStrength = 0.75 — Shadow darkness at zero transmission. Scaled down as `transmission` rises — a cloud you can see daylight through does not cast a hard shadow transmission = -1 — How much light comes THROUGH: `0` storm-dark underside, `1` glowing. `-1` = auto from `coverage` thickness = 180 — Whiteout depth at FULL coverage. Thinner skies scale it down — passing through always whites out, coverage decides for how long haze = 0.6 — How much the air under the deck takes the cloud's colour. Hides the rim seed = 1337 — Same seed, same weather frequency = 3 — Field repeats across its own width. Higher = smaller puffs octaves = 6 — Detail octaves. Billow needs more than fBm — folding eats fine structure fieldSize = 1024 — Texels per edge of the baked density field. More texels = finer cloud, 1 byte each period = 1800 — Metres per repeat of the field — the size of the CLOUDS, independent of the size of the deck edgeFade = 0.45 — Where the radial fade starts, as a fraction of the half-size. The deck has no visible rim at any coverage color = '#ffffff' — Lit top colour underColor = '#3a4350' — Shadowed underside fringe = 0.9 — Brightness of the lit edges seen from below. ADDED, so it can exceed 1, and it takes the scene light's colour and direction — brightest with the sun behind the cloud bump = 34 — Faux-bump strength. Higher = more pronounced relief underBump = 0.85 — How much relief the UNDERSIDE shows. Borrowed from the top's lighting, so both faces share one shape shade = 0.22 — How much of the top's brightness the lighting may take. Small on purpose — cloud is near-white, and a wide swing reads as water ## b3d-clouds — b3d-clouds count = 36 — Blob POOL size (fixed — they recycle, they don't grow). `coverage` decides how many are active model = '' — GLB whose mesh is the cloud LOBE (normalized to the blob radius, bottom-aligned). Empty = the procedural lobe altitude = 140 — Centre height of the layer thickness = 36 — Vertical spread of the layer spread = 1200 — Radius of the disc of cloud around you size = 70 — Blob radius — also the distance at which whiteout is total. Set at build color = '#ffffff' — Cloud (and whiteout) colour opacity = 1 — Blob alpha. Default OPAQUE — translucent clouds read badly. Set < 1 only for deliberate wisps fogDensity = 1.0 — Whiteout density (EXP2, the scene's mode). HIGH on purpose — inside a cloud you should see nothing but white within a few metres approach = 0.5 — Where the whiteout BEGINS, × `size` outside the blob. It's TOTAL well before the surface (you never see the geometry edge) and stays total until you leave selfIllum = 0.35 — Self-illumination 0…1 — `1` ≈ fully self-lit (old look), `0` = only sun-lit (dark undersides) coverage = 0.5 — Weather dial 0…1: wisps → overcast/thunderheads. LIVE. Gates active count + opacity + darkness + self-illum castShadows = false — Opt-in: project the field's shadows onto every shadow-receiving surface ([cloud-shadows](?cloud-shadows.ts)) shadowStrength = 0.65 — Darkness of those shadows 0…1, scaled further by `coverage` (≈50% darkening at typical coverage) seed = 1 — Deterministic layout — same seed, same sky windX windZ wind ## b3d-collisions — b3d-collisions debug ## b3d-controller — b3d-controller x y z rx ry rz axes mapping = 'biped' — Which control scheme maps the gamepad to `ControlInput`: `'biped'`, `'car'`, or `'aircraft'` player ## b3d-crowd — b3d-crowd count = 200 — How many figures. One draw call whatever it is spread = 60 — Metres across the field they scatter over bakeFps = 10 — Frames baked per second of clip — the memory knob interpolate = 'on' — `'off'` snaps to the nearest frame: cheaper, jerkier skinned = 0 — How many SKINNED clones to spawn alongside, as the baseline skinnedUrl = '/omnidude.glb' — The GLB the baseline clones url = a rigged GLB to bake from; empty = the synthetic figure clips = '' — Which of its clips to bake, comma-separated. Empty = all figureScale = 1 — Scale applied to the baked figure (omnidude is 0.88m) ## b3d-death — b3d-death title = 'DOWN' — Heading on the panel delay = 1.4 — Seconds between the bang and the panel (let the player watch it burn) orbitRadius = 14 — Camera distance from the wreck orbitHeight = 6 — Camera height above the wreck orbitSpeed = 6 — Degrees/sec — slow. This is a moment, not a ride spectate = 'orbit' — `orbit` circles the wreck; `chase` freezes the third-person shot you died in (static). Flat only wreckage = 'on' — Explode + leave burning wreckage (`'off'` = just the panel) blastRadius = 6 — Size of the fireball ## b3d-decorator — b3d-decorator budget = 2000 — How many things to place. Performance cares about this, not density radius = 900 — Metres around the camera to fill seed = 1 — Same seed, same forest url = '' — The model library; empty = Kenney's Nature Kit on the CDN scale = 1 — Multiplies every rule's scale range follow = 'on' — Re-scatter as the camera moves shadows = 'off' — Cast shadows — from the NEAR copies only (`shadowRange`, `shadowBudget`), through a shadow-only twin of each part. Copies always RECEIVE shadows. Live colliders = 'on' — The nearby collider pool colliderRange = 60 — Metres around the camera that get colliders colliderPool = 48 — How many colliders at most shadowRange = 200 — Metres around the camera whose copies cast shadows (with `shadows: 'on'`) shadowBudget = 600 — How many of the nearest copies cast, at most ## b3d-destroyable — b3d-destroyable x y z rx ry rz axes meshName library destroyable size scale color capacity armor regenRate regenDelay protectedBy protection remains sound soundVolume explode explodeForce deathBlast blastDamage blastFullRadius blastRadius blastDelay ## b3d-elevator b3d-elevator mode = 'cycle' — `'cycle'` runs forever; `'pressure'` moves while something stands on it; `'switch'` waits for `call()` travel = 3 — Metres between the bottom stop and the top stops = 2 — How many stops, evenly spaced. `2` is bottom and top speed = 1.2 — Metres per second pause = 1.5 — Seconds held at each stop width = 2 — Platform size depth = 2 — Platform size thickness = 0.2 — Platform thickness — it gets a collision proxy like any thin solid color = '#8a8f98' ## b3d-fog — b3d-fog mode = 'linear' — `'linear'`, `'exp'`, or `'exp2'` color = '#bfd9f2' — Fog color (hex, ignored when `syncSkybox` is true) start = 60 — Start distance (linear mode) end = 120 — End distance (linear mode) density = 0.01 — Density (exp/exp2 modes) syncSkybox = false — Automatically match fog color to skybox horizon ## b3d-galaxy — b3d-galaxy seed = 1234 — Galaxy seed starCount = 10000 — The galaxy's BRIGHT budget — the stars visible across it (±noise; counts round per voxel). The dim population is local and not loaded here yet dimBudget = 95000 — The DIM population's budget. Its interesting share (~5%, HI ≤ 2) is drawn globally; the boring rest only near a point (the baker's eye) radius = 100 — Galaxy radius in scene units spiralArms = 4 — Number of spiral arms spiralAngle = 240 — Spiral arm sweep in degrees thickness = 0.06 — Disk thickness (fraction of radius) particleSize = 1.0 — Base star particle diameter coreSize = 0.12 — Central black hole radius. Disk radii are multiples of it, so this scales the whole assembly distantGalaxies = 500 — External galaxies scattered isotropically outside the disc — what keeps the off-band sky from reading as empty distantStars = 3000 — Dim far-out stars scattered isotropically outside the disc — the same emptiness budget, but for POINTS. They carry no name or system; they exist so the sky outside the band has texture maxStarApparentSize = 0.01 — Cap on a star's apparent size as a fraction of its distance. `0` = off. Only affects the near end ## b3d-hud — b3d-hud url = '' — Empty = the built-in code HUD (fully wired); set to a designer SVG to load one size = 70 — HUD height as a % of the canvas's smaller dimension pxPerDeg = 8 — Pitch-ladder pixels per degree ## b3d-input-focus — b3d-input-focus enterDistance = 3 — Max distance to enter a vehicle ## b3d-interactive — b3d-interactive target = '' — Mesh or node name to make touchable. Empty = the mesh of the element this one is nested inside include = 'subtree' — `'subtree'` counts the named node and everything under it; `'self'` counts only the node itself reach = 0 — Max distance **from the player**, in world units; `0` means no limit disabled = false — Refuses hover, and drops a press already in flight highlight = '#ffcc44' — Hover outline colour; `'none'` for no highlight ## b3d-lamp (tosi-b3d-point-light) — Lamps x = 0 — Position y = 3 — Position z = 0 — Position intensity = 1 — Brightness. With `modulation`, this is the MAXIMUM diffuse = '#ffffff' — Colour specular = '#ffffff' — Specular colour range = 10 — Falloff distance (point / spot) on = true — `false` plays the DECAY region; it does not kill the light geometry = 'on' — `'off'` for no fixture geometryScale = 1 — Size multiplier for the default fixture url = — — GLB fixture, in place of the primitive shadows = 'off' — `'on'` for a shadow generator (point / spot only) timeSource shadowTextureSize = 0 — Resolves against the device budget ## b3d-lamp (tosi-b3d-spot-light) — Lamps x = 0 — Position y = 3 — Position z = 0 — Position intensity = 1 — Brightness. With `modulation`, this is the MAXIMUM diffuse = '#ffffff' — Colour specular = '#ffffff' — Specular colour range = 10 — Falloff distance (point / spot) on = true — `false` plays the DECAY region; it does not kill the light geometry = 'on' — `'off'` for no fixture geometryScale = 1 — Size multiplier for the default fixture url = — — GLB fixture, in place of the primitive shadows = 'off' — `'on'` for a shadow generator (point / spot only) timeSource shadowTextureSize = 0 — Resolves against the device budget angle = 60 — **spot** — cone angle in degrees exponent = 2 — **spot** — falloff sharpness (standard falloff) innerAngle = 0 — **spot** — inner cone in degrees; above `0` gives a true penumbra and switches to glTF falloff shape = 'circle' — **spot** — cone cross-section: `circle` / `square` / `none`. Projected as a gel, so an explicit `gel` wins shapeAspect = 1 — **spot** — width/height; `2` is an ellipse or letterbox shapeSoftness = 0.25 — **spot** — edge feather, as a fraction of the radius dirX dirY dirZ gel = — — **spot** — projection texture URL (bitmap or SVG file) gelSvg = — — **spot** — inline SVG source or an `SVGElement` ## b3d-lamp (tosi-b3d-area-light) — Lamps x = 0 — Position y = 3 — Position z = 0 — Position intensity = 1 — Brightness. With `modulation`, this is the MAXIMUM diffuse = '#ffffff' — Colour specular = '#ffffff' — Specular colour range = 10 — Falloff distance (point / spot) on = true — `false` plays the DECAY region; it does not kill the light geometry = 'on' — `'off'` for no fixture geometryScale = 1 — Size multiplier for the default fixture url = — — GLB fixture, in place of the primitive shadows = 'off' — `'on'` for a shadow generator (point / spot only) timeSource shadowTextureSize = 0 — Resolves against the device budget width = 2 — **area** — panel size height = 1 — **area** — panel size ## b3d-launcher — b3d-launcher x = 0 — Launcher position (muzzle offset forward from here) y = 0 — Launcher position (muzzle offset forward from here) z = 0 — Launcher position (muzzle offset forward from here) rx ry rz axes meshName library grip socket modelScale muzzleSpeed = 30 — Launch speed (units/sec) along the fire direction fireRate = 5 — Max shots per second (cadence gate) ammo = 40 — Magazine capacity (a `Resource`) reloadRate = 8 — Ammo regenerated per second (0 = no reload) reloadDelay = 1 — Seconds after firing before reload resumes gravity = -9.81 — Vertical acceleration on the shell drag = 0.01 — Quadratic drag coefficient (0 = vacuum) mass = 1 — Shell mass (higher flies flatter/further under drag) missileSpeed = 22 — Cruise speed of a guided shot (`fireAt`) turnRate = 3 — Guided-missile agility (rad/sec) projRadius = 0.12 — Shell visual radius missileTrail = 'off' — `'on'` leaves a smoke ribbon behind each guided missile (`fireAt`); see [b3d-trail](/b3d-trail/). For your own rounds, pass `trail` to `spawnProjectile`/`spawnMissile` projColor = '#ffdd55' — Shell emissive colour maxLifetime = 6 — Seconds before an un-impacted shell self-disposes damage = 20 — Warhead full damage (see b3d-warhead) fullRadius = 1 — Warhead full-damage radius blastRadius = 3 — Warhead falloff radius los = 'on' — Warhead line-of-sight gating ## b3d-library — b3d-library url = '' — GLB/glTF file URL type = '' — Library type for scene registry lookup ## b3d-light-shafts — b3d-light-shafts count = 14 — How many sky shafts at most (the budget). `0` = off radius = 3000 — How far from you (m) to look for gaps. Shafts read best from a distance width = 40 — The BROADEST sky shaft at the cloud (m), at the coverage threshold (0.5); narrower as the cover closes, down to 10% of this near 1. Kept SMALL on purpose: the wider a shaft, the more obvious any mismatch with the gap it comes from spread = 0 — Extra width per metre of length. `0`: RECTANGULAR shafts, so all the apparent widening is perspective, and they radiate from the sun because they are parallel to its light strength = 0.35 — Brightness at the edge the light comes through; it falls linearly to 0 rainBoost = 0.5 — How much precipitation where you are multiplies the strength color = '' — The light's colour; empty = the sun's (whitish by day) underwater = 'on' — Shafts under the water surface too underwaterCount = 12 — Their budget ## b3d-light — b3d-light x = 0 — Light direction X (the "up" direction) y = 1 — Light direction Y z = 0 — Light direction Z intensity = 1 — Brightness multiplier diffuse = '#ffffff' — Diffuse color (hex) specular = '#808080' — Specular color (hex) groundColor = '#000000' — Bounce from below (hex). Babylon's default is black, which is why vertical faces look unlit however high `intensity` goes — set a dim version of your ground colour ## b3d-lightning — b3d-lightning seed = 1 — Same seed, same storm bolts = 'on' — Draw the bolt for cloud-to-ground strikes sprites = 'on' — Red-pink sprites above strong storms thunder = 'on' — Procedural thunder, delayed by distance volume = 0.8 — Thunder loudness groundLight = 2.5 — How hard a ground strike's own light hits the scene: from the middle of the channel (halfway between the cloud base and the ground under the strike), the one that casts the shadows (the whole-sky fill is separate) darken = 0.5 — How much a storm near you takes from the sun AND the ambient light (half, at full storm, easing with distance), so the flashes stand out. Applied through the cloud deck, which owns those lights shadows = 'on' — Hard shadows from the strike. ONE shadow map, kept, re-rendered once per new brightest ground strike (never per frame) shadowSize = 1024 — Its resolution shadowRange = 600 — How far from you (m) things cast them: the shadows you can see, and a tight set keeps the map sharp flashLight = 'point' — The strike's shadowed light. `'point'`: shadows radiate from the bolt in every direction (a cube map: six shadow renders, once per new strike). `'directional'`: one render, correct looking toward the strike; the cheap choice for low-end devices color = '#dce4ff' — The flash's colour rate = 1 — How OFTEN, as a multiple of the natural rate (about 0.6 strikes a second over a storm at storminess 1; at most 4) brightness = 1 — How DRAMATIC a flash is: the whole landscape lit from above (falling off with the storm's distance), the cloud lit from inside, and the bolt's glow, together ## b3d-loader — b3d-loader url = '' — URL of the GLB/glTF file lightIntensityScale = 0.05 — Scale factor for imported lights destroyable = 'off' — `'on'` gives the model hit points + a death outcome capacity = 10 — Combat stats (when destroyable) armor = 0 — Combat stats (when destroyable) regenRate = 0 — Combat stats (when destroyable) regenDelay = 0.5 — Combat stats (when destroyable) explode = 'off' — Shatter on death (best for single-mesh models) explodeForce = 6 — Shatter on death (best for single-mesh models) deathBlast blastDamage blastFullRadius blastRadius blastDelay ## b3d-manipulator — b3d-manipulator target = '' — CSS selector for the element to manipulate. Or set `.node` in JS meshName = '' — a mesh in the scene, by name — for things that are not elements move = 'on' — `'on'`/`'off'` — arrows and plane pads turn = 'off' — `'on'`/`'off'` — rings scale = 'off' — `'on'`/`'off'` — cubes, plus the uniform centre cube gridSnap = 0 — position snap in metres. `0` is off angleSnap = 0 — angle snap in degrees. `0` is off size = 0.13 — apparent size — the widget is this fraction of its distance from the camera, so it stays constant on screen disabled = false — hide the handles and ignore input ## b3d-moon — b3d-moon azimuth = 0 — Degrees AROUND the star sphere. Like right ascension: the moon rides with the stars, rising and setting with them elevation = 20 — Degrees from the celestial equator (like declination) size = 0.5 — Angular DIAMETER in degrees (the real moon is about 0.5) color = '#dddddd' — Its colour where lit brightness = 1 — Multiplies the lit side ## b3d-panel — b3d-panel frame = eye — `eye` / `rig` / `world` / `body` / `neck` / `face` / `left-hand` / `right-hand` preset = '' — A named anchor (`waist`, `left-shoulder`, `right-shoulder`, `overhead`, `wrist`). Overrides the angular fields. azimuth = 0 — Degrees off the frame's eye: +az right, +el up elevation = 0 — Degrees off the frame's eye: +az right, +el up distance = 1.4 — Metres from the eye position = '' — Explicit `"x y z"` local position (overrides az/el/distance) roll = 0 — Roll about the panel normal (deg) reveal = gaze — `gaze` (look toward it) or `always` blend = composite — `composite` or `add` (additive HUD glyphs) view = both — `first` / `third` / `both` — restrict to a camera view title = '' — Placeholder card title (ignored if `url` set) url = '' — SVG URL (e.g. a reticle) width = 0.26 — Panel width (m); height follows aspect revealStart revealFull maxDistance presence = 'xr' — `'xr'` — only in an immersive session; `'both'` — also in the flat view, on frames derived from the flat camera flatFrame = '' — The frame to use in the FLAT view: required for a hand panel (a monitor has no hands); `'face'` measures elevation from the view instead of the horizon, so a menu stays centred under a pitched camera resolution = 0 — Texture size in px (square); `0` = 384. Raise it for a menu with text ## b3d-particles — b3d-particles x = 0 — Emitter X position y = 0 — Emitter Y position z = 0 — Emitter Z position capacity = 500 — Maximum particle count emitRate = 50 — Particles emitted per frame minLifeTime = 0.3 — Minimum particle lifetime (seconds) maxLifeTime = 1.5 — Maximum particle lifetime (seconds) minSize = 0.1 — Minimum particle size maxSize = 0.5 — Maximum particle size minEmitPower = 1 — Minimum emission speed maxEmitPower = 3 — Maximum emission speed gravityX = 0 — Gravity X component gravityY = -9.81 — Gravity Y component gravityZ = 0 — Gravity Z component color1 = '#ffff00' — Start color 1 color2 = '#ff6600' — Start color 2 colorDead = '#000000' — End-of-life color blendMode = 'standard' — `'standard'` or `'additive'` texture = '' — Particle texture URL (empty = default flare) emitterShape = 'point' — `'point'`, `'box'`, `'sphere'`, `'cone'` emitterRadius = 0.5 — Radius for sphere/cone emitters useSceneGravity = false — Use scene physics gravity instead of gravityX/Y/Z autoStart = false — Start emitting when scene is ready targetStopDuration = 0 — Auto-stop after N seconds (0 = forever) disposeOnStop = false — Dispose when stopped attachTo = '' — Mesh name to attach emitter to ## b3d-physics — b3d-physics gravityX = 0 — Gravity X component gravityY = -9.81 — Gravity Y component gravityZ = 0 — Gravity Z component debug = false — Show wireframe physics collider shapes wasmUrl ## b3d-planet — b3d-planet biome seed = 12345 — Noise seed radius = 50 — Base sphere radius subdivisions = 64 — Grid subdivisions per cube face grossScale = 0.005 — Gross noise frequency detailScale = 0.02 — Detail noise frequency grossAmplitude = 5 — Gross height multiplier detailAmplitude = 1 — Detail height multiplier atmosphere = 0.08 — Atmosphere thickness (fraction of radius, 0=none) atmosphereColor atmosphereTurbulence ocean = 0.6 — Ocean coverage (0=none, 0.6=60% of surface underwater) rings wireframe = false — Debug: render as wireframe rotationSpeed = 0 — Auto-rotation speed (radians/sec) ## b3d-primitives (tosi-b3d-sphere) — x y z rx ry rz axes meshName segments diameter color glow glowColor mirror solid solidProxy ## b3d-primitives (tosi-b3d-box) — x y z rx ry rz axes meshName size width height depth color mirror glow glowColor solid solidProxy ## b3d-primitives (tosi-b3d-ground) — x y z rx ry rz axes meshName size width height color texture textureTiles ## b3d-probe — b3d-probe force ttlDays ## b3d-prop — b3d-prop x = 0 — position y = 0 — position z = 0 — position rx = 0 — rotation, in DEGREES ry = 0 — rotation, in DEGREES rz = 0 — rotation, in DEGREES axes library = '' — `type` of a `` in the scene libraryUrl = '' — glb URL — mounts a library for you; use instead of `library` meshName = '' — model name within the library scale = 1 — uniform scale applied to the instance root ## b3d-radar-blip — b3d-radar-blip profile = 1 — Detectability: `1` = seen at the platform's nominal radar range, `2` = out to 2×, `0.05` = very stealthy; **negative = always detectable** (e.g. waypoints). faction = 'neutral' — `friendly` / `neutral` / `hostile` / `waypoint` — drives the radar-trace colour. x = 0 — World position when standalone (ignored while following a target's mesh). y = 0 — World position when standalone (ignored while following a target's mesh). z = 0 — World position when standalone (ignored while following a target's mesh). ## b3d-radar — b3d-radar range = 250 — Nominal range — a `profile 1` blip is detected within this. coneDeg = 90 — Detection cone HALF-angle (deg). `90` = front hemisphere. lockTime = 1.5 — Seconds of continuous detection to acquire a lock (`0` = instant). maxLocks = 2 — Max simultaneous locks (the nearest opposed contacts). acquireConeDeg acquireRange alignment = 'friendly' — This radar's own faction. It locks only **opposed** blips (friendly⇄hostile); neutrals/waypoints show but never lock. updateInterval = 100 — Radar refresh period (ms). Runs below frame-rate and is dithered across frames so many radars don't all recompute the same frame. ## b3d-reflections — b3d-reflections refreshRate = 5 — Frames between probe refreshes inside `farDistance` probeSize = auto — Cubemap resolution per face; `auto` = device tier maxDistance = 100 — Distance beyond which probes freeze entirely farDistance = 30 — Distance at which the rate starts ramping toward `farRefreshRate` farRefreshRate = 30 — Probe refresh rate at `maxDistance` distanceCheckInterval = 13 — Frames between camera-distance re-checks ## b3d-shadows — b3d-shadows shadowMaxZ = 100 — Far plane of the cascaded shadow frustum shadowDarkness = 0.1 — 0 = fully dark shadow, 1 = no shadow shadowNormalBias = 0.05 — Offset along the surface normal — **the shadow-acne knob**. Lower it if shadows detach from small casters shadowBias = 0.00005 — Depth-direction bias; peter-pans sooner than `shadowNormalBias`, so tune that one first shadowTextureSize = auto — Shadow map resolution (per cascade); `auto` = device tier activeDistance = 30 — Max camera-to-mesh distance a caster participates from numCascades = auto — Number of cascade splits (1–4); `auto` = device tier stabilizeCascades = 'on' — Reduce shadow-edge "swimming" under motion lambda = 0.8 — Cascade split blend (0 = uniform, 1 = logarithmic) cascadeBlendPercentage = 0.1 — Soft blend across cascade seams x = 0 — Sun direction X (overridden by skybox when present) y = -1 — Sun direction Y z = -0.5 — Sun direction Z intensity = 1 — Sun intensity (overridden by skybox when present) updateIntervalMs = 1000 — How often to re-evaluate active casters ## b3d-skybox — b3d-skybox x y z rx ry rz axes turbidity = 10 — Atmospheric haze spaceStart = 0 — Altitude (m) where the fade to space BEGINS spaceFull = 0 — Altitude (m) of full vacuum. Feature is off unless this exceeds `spaceStart` atmosphere = 1 — How much air this WORLD has: `1` Earth, `0` the Moon (black sky at noon, stars out, no haze, a hard sun). Deliberately steep — only the last stretch toward 0 thins the sky (vacuum is `(1 − atmosphere)⁴`) — and it multiplies with the space band dust = 0 — Suspended dust, 0…1: bright, coloured haze that is never blue. Independent of `atmosphere`, so Mars is almost no air and lots of dust, and the Moon is neither zenithTint = '#ffffff' — The sky's colour overhead — the scattered light's own brightness in this hue, by `tintStrength`. Stars and moon are behind the air and untinted horizonTint = '#ffffff' — The same at the horizon. `zenithTint: '#c8a070', horizonTint: '#e0b080', tintStrength: 1` is a butterscotch Mars tintStrength = 0 — How much the sky takes the tints, `0` (Earth, untouched) … `1` starfieldCube = '' — Root path of a baked cube (`_px.png` …). Replaces `starfield` starfieldData = '' — Root path of a DATA cube (`_px.png` …) encoded by `starfield-codec`. Not a picture of a starfield — a table of stars the shader decodes into points that stay sharp at any zoom. Composes with `starfieldCube` rather than replacing it starfieldDataSize = 1024 — Texels per face of `starfieldData`. Must match what encoded it. 1024 is the size to ship — at 512 a packed texel reads as a lattice through the dense band starfieldSharpness = 3 — How sharp a decoded point is — higher is tighter. 3 tucks the gaussian tail in so a star reads as a point starfieldGain = 0.9 — How bright the decoded stars are — the intensity cap on the whole point sky starfieldFloor = 0.4 — The faint mass's brightness — most stars sit on it; `starfieldGain` only moves the bright few above it starfieldTwinkle = 0.35 — Scintillation strength. Scaled by the gas (none in vacuum), strongest at the horizon starfieldSizeScale = 3 — How much bigger a full-size object (a distant galaxy) is than a star starfieldTilt = '0,0,0' — Degrees `rx,ry,rz` rotating the sampling direction — both cubes — where a galactic tilt belongs starfield = 0 — How many background stars to build. `0` = none nebulae = 0 — Soft emission clouds behind the stars. `0` = none nebulaBrightness = 1 — Nebula brightness 0…1 nebulaSize = 0.045 — Nebula size as a fraction of the sky radius nebulaTexture = '' — Black-backed image stamped per nebula; empty = a plain procedural falloff spaceColor = '#05070f' — What is behind the stars in vacuum. Just north of black, so a black hole still has somewhere darker to go starfieldSeed = 12345 — Seed for the starfield — same seed, same constellations starDistance = 0 — Park a `` child this far along the sun vector. `0` = leave it alone luminance = 1 — Sky brightness azimuth = 0 — **Ignored** — the sun is placed by `latitude` and `timeOfDay`, and the sky material accepts this and discards it. Kept so old markup doesn't break; not in `skyboxSchema()` (tosijs-3d#86) latitude = 40 — Geographic latitude in DEGREES (affects the sun's arc) realtimeScale = 10 — Realtime speed multiplier updateFrequencyMs sunColor = '#eeeeff' — Midday sun color duskColor = '#ffaa22' — Dawn/dusk sun color moonColor = '#6688cc' — Night light color moonIntensity = 0.15 — Night light intensity sunSize = 1 — The sun's apparent size, 1 = as seen from Earth. Mars 0.66, Venus 1.39, Io 0.19, Titan 0.11 (it goes as 1/distance from the star) sunBrightness = 1 — Multiplies the sun's light. A distant world gets less light, but the eye adapts, so set it by how it looks rather than by the inverse square timeOfDay = 6.5 — 0-24 hours rayleigh = 2 — Rayleigh scattering mieDirectionalG mieCoefficient skyboxSize applyFog = false — Whether scene fog affects the skybox ## b3d-sound — b3d-sound url = '' — Audio file URL volume = 1 — Volume (0-1) loop = false — Loop playback autoplay = false — Auto-start on connect spatialSound = false — Enable 3D positional audio x = 0 — Position X (spatial mode) y = 0 — Position Y (spatial mode) z = 0 — Position Z (spatial mode) refDistance = 1 — Distance at full volume rolloffFactor = 1 — Attenuation rate maxDistance = 100 — Cutoff distance distanceModel = 'linear' — `'linear'`, `'inverse'`, `'exponential'` attachTo = '' — Mesh name to follow playbackRate = 1 — Playback speed ## b3d-spawner — b3d-spawner prefab = '' — Prefab name to spawn (usually an encounter) maxAlive = 2 — How many groups may exist at once interval = 8 — Seconds between spawn attempts minDistance = 600 — Nearest a group may appear (from the player) maxDistance = 1400 — Furthest a group may appear anchor = 'player' — `'player'` = a ring around the player (an encounter); `'place'` = exactly at `x`/`y`/`z` (a launchpad) x = 0 — Spawn point, when `anchor="place"`. Ignored otherwise y = 0 — Base height for the spawn point (the prefab places its own members) z = 0 — Spawn point, when `anchor="place"`. Ignored otherwise facingDeg = 0 — Facing for a placed spawn, degrees about Y — reaches the prefab as `rotation` seed = 1 — Deterministic placement — same seed, same battles disabled = false — Stop spawning (a boolean can't default to true — see CLAUDE.md) ## b3d-star-system — b3d-star-system galaxySeed = 1234 — Galaxy seed for deterministic generation starCount = 10000 — The galaxy's bright budget (needed to regenerate the same galaxy) starIndex = 0 — Which star to render, by position in the galaxy's view (moves if `starCount` does) star = '' — A star's ADDRESS (`1234:bright:5021:0`, the `id` on every star). Stable, and wins over `starIndex` scale = 5 — Visual scale factor for star/planet sizes orbitScale = 3 — Multiplier for orbital distances animate = 'on' — Animate planet orbital motion showOrbits = 'on' — Show orbital path lines x y z ## b3d-star — b3d-star seed = 12345 — Noise seed for surface features radius = 20 — Star radius subdivisions = 32 — Grid subdivisions per cube face spectralClass = 'G' — Spectral class: O, B, A, F, G, K, M surfaceDetail = 0.5 — Surface noise intensity (0=uniform, 1=strong spots) coronaSize = 0.15 — Corona thickness as fraction of radius (0=none) rotationSpeed = 0.02 — Auto-rotation (radians/sec) wireframe = false — Debug wireframe glowIntensity = 2.0 — Emissive brightness multiplier pointLight = false — Create a point light at star center lightIntensity = 1.0 — Point light intensity lightRange = 500 — Point light range ## b3d-svg-plane — b3d-svg-plane x y z rx ry rz axes castShadow receiveShadows width = 1 — Plane width in scene units height = 1 — Plane height resolution = 512 — Texture resolution (square, px) url = '' — SVG URL — fetched and rendered once updateInterval = 30 — Re-render interval in ms (dynamic mode) materialChannel = 'emissive' — `'emissive'` (unlit) or `'diffuse'` (lit) cameraRelative = false — Parent plane to active camera (HUD mode) placement xrFrame = '' — In a headset with `cameraRelative`, parent to this XR reference frame instead of the head camera. `'body'` (torso, damped yaw) keeps a panel in front of you without jittering on every head movement; leave unset for a HUD that should stay head-locked pointerEvents = 'on' — Map 3D pick hits → SVG pointer events doubleSided = 'on' — Render both faces cornerRadius = 0 — Corner radius in WORLD units. `0` = a plain rectangle. Rounds the MESH, so corners cost triangles instead of alpha — see **Opaque panels** below transparent = 'on' — `'off'` drops the opacity texture so the plane writes depth. Pair with `cornerRadius` ## b3d-terrain — b3d-terrain biome biomeSeaLevel = 0 — Sea level for the biome classifier (`biome="on"`) — keep it equal to your water plane's `y` biomeLapseRate = 0 — Height→temperature lapse. ⚠️ Must be scaled to your vertical range: `≈ baseTemperature / relief`. The 0.004 default is a small-world number and renders a 340m world entirely as snow biomeTemperature = -1 — Sea-level temperature, `0…1` cold → warm. LIVE biomeMoisture = -1 — Land moisture, `0…1`: dead → dry (dune) → medium (steppe) → **wet (forest, ≈0.75)**. The default is steppe; a green world wants ~0.7. LIVE biomeVolcanicScale = -1 — Volcanic plate frequency, 1/m. Scale to the volcano: 0.09 suits a ~50 m cone; a 400 m one wants ~0.02. LIVE normalSmoothing = 0.6 — Low-pass the NORMALS' height field (positions stay crisp) — kills cliff-face zigzag seed = 12345 — Noise seed surfaceType = 'cylinder' — `'cylinder'`, `'torus'`, or `'sphere'` majorRadius = 100 — Torus major radius minorRadius = 40 — Torus minor radius radius = 200 — Sphere/cylinder radius cylinderHeight = 200 — Cylinder height (v range before reflection) tileSize = 10 — World-space size of a level-0 (finest) tile hiResSubdivisions = auto — Vertices per tile edge (same at every level); `auto` = device tier lodLevels = 5 — Number of LOD levels; level k tiles are `tileSize × 2^k` poolSize = auto — Shared tile budget; the pool renders the top-priority cells (`auto` = device tier) fillBudget = auto — Max tiles (re)built per frame — a churn backstop (`auto` = device tier) splitFactor = 2 — LOD falloff: subdivide a cell when nearer than `splitFactor × tileSize` reach = 0 — Terrain radius (0 = auto from the coarsest tile). Clamped against `tileSize` — the product is the footgun. Import `budgetedReach` from `tosijs-3d/terrain-grid` to clamp a slider against the same limit grossScale = 0.015 — Gross noise frequency — a RECIPROCAL wavelength, so SMALL numbers make BIG landforms (0.015 ≈ 65m features before `horizScale`) detailScale = 0.09 — Detail noise frequency, same units horizScale = 1 — Horizontal world scale — scales every tile's size AND the sampling together (>1 = bigger terrain that reaches further; a clean zoom, not just a frequency change) grossAmplitude = 8 — Gross height multiplier. ⚠️ Meaningless on its own: it's spread over `grossScale`/`horizScale`, so the same number is a mountain range at one scale and a plain at another detailAmplitude = 3 — Detail height multiplier. Landscape reads best when this does REAL work rather than 5% — big gross features, small gross amplitude, busy detail baseHeight = 0 — Flat vertical offset (m). The noise is 0..amplitude; `-grossAmplitude/2` centres the terrain on 0 so a water plane at 0 floods the valleys into a sea center debugColor = false — Debug: tint each tile a distinct hashed colour to expose the tile/LOD layout tileBuildMs = auto — **Milliseconds of tile building allowed per frame** — the cap that actually bounds the worst frame. A tile COUNT bounds it only by accident (a tile's cost swings with subdivisions, octaves, device and JS engine); a time cap bounds it by construction everywhere, and self-corrects when you raise detail. Always builds ≥1 tile. (`auto` = device tier) profile = false — Debug: time tile building and report it on `debugState` (see below). Off = zero cost originResetThreshold = 500 — Distance before origin rebase maxTravelDistance = 5000 — Distance before firing recenter-needed event wireframe = false — Debug: render terrain as wireframe ## b3d-trail — b3d-trail x = 0 — Where the ribbon starts, in the HOST's local space (an engine pod, a nozzle) y = 0 — Where the ribbon starts, in the HOST's local space (an engine pod, a nozzle) z = 0 — Where the ribbon starts, in the HOST's local space (an engine pod, a nozzle) diameter = 0.06 — Ribbon width (m) length = 45 — Ribbon length, in segments (one a frame, so length ≈ how many frames of history) color = '#ffffff' — Its colour (emissive, unlit) underwaterColor = '' — The colour below a `` surface; empty = same as `color` alpha = 0.16 — Opacity. Low on purpose: you should see through a contrail minSpeed = 8 — Below this speed (m/s, measured at the emitter) the ribbon fades out, so a hover does not smear ## b3d-trigger — b3d-trigger x = 0 — Center X y = 0 — Center Y z = 0 — Center Z radius = 5 — Trigger sphere radius disabled = false — Disable the trigger (default: active) target = 'camera' — `'camera'` or a mesh name to watch debug = false — Show wireframe sphere once = false — Fire `whenEnter` once then deactivate ## b3d-turret — b3d-turret x = 0 — Turret base position y = 0 — Turret base position z = 0 — Turret base position rx ry rz axes meshName library muzzleSpeed = 35 — Shell launch speed (also the lead-solver's projectile speed) fireRate = 2 — Max shots per second range = 30 — Won't fire beyond this distance traverseRate = 2.5 — Max barrel slew rate (rad/sec) smart = 0 — Skill curve 0..1: **lead** ramps to full by **0.5**, **drop** compensation to full by **1** (0 = aim at the target's current spot). 0.5–1 reserved for acceleration/turn-rate prediction later aimTolerance = 6 — Fires only when the barrel is within this many degrees of the solution gravity = -9.81 — Shell ballistics (see b3d-launcher) drag = 0.01 — Shell ballistics (see b3d-launcher) mass = 1 — Shell ballistics (see b3d-launcher) damage = 20 — Warhead payload (see b3d-warhead) fullRadius = 1 — Warhead payload (see b3d-warhead) blastRadius = 2.5 — Warhead payload (see b3d-warhead) los = 'on' — Warhead payload (see b3d-warhead) idleColor = '#4a5560' — Barrel colour with no firing solution armedColor = '#e04030' — Barrel colour when it can bear (has a solution, in range) ## b3d-warhead — b3d-warhead x = 0 — Detonation point when `detonate()` is called with no argument y = 0 — Detonation point when `detonate()` is called with no argument z = 0 — Detonation point when `detonate()` is called with no argument rx ry rz axes damage = 20 — Full damage `D` (direct hit + within `fullRadius`) fullRadius = 1.5 — Within this distance the blast deals full `D` blastRadius = 5 — Falloff from `D` (at `fullRadius`) to 1 here; 0 beyond los = 'on' — Line-of-sight occlusion (a wall between blast + target spares it) by ## b3d-water — b3d-water x y z rx ry rz axes underwaterFog fogColor = '#00264d' — The colour of the water you are IN (the underwater fog). Sea blue by default; a methane sea (Titan) is dark amber underwaterMurk fogTransition underside = 'auto' — Snell's window from below: straight up, a bright window onto the sky; toward grazing angles, a mirror of the depths. `'auto'` = on whenever `twoSided`; `'on'`/`'off'` force it. Fades in with the underwater fog undersideColor = '#9fdcf0' — The window: the sky's light, looking up undersideDepthColor = '#06283a' — The mirror: the dark water, at grazing angles undersideSky = 1 — From below, the window REFRACTS THE REAL SKY (the sun included), distorted by the ripples — clearest in the shallows, fading with depth, giving way to the dark mirror toward grazing angles. `0` = the flat `undersideColor` only caustics = 'auto' — Light through the moving surface, dancing on everything beneath it (terrain, hulls, the player). `'auto'` = on whenever `twoSided`. Fades with depth and fog; follows the sun causticsStrength = 0.6 — How bright the web gets causticsScale = 6 — Metres per caustic cell: bigger is coarser and calmer spherical = false — Use a sphere instead of a plane waterSize = 128 — Size of the water plane subdivisions = 32 — Mesh subdivisions textureSize twoSided = false — Render both sides follow = false — Ride the camera in x/z (endless sea): the plane snaps to a coarse grid under you, ripples stay anchored in world space normalMap windForce = -5 — Wind strength waveHeight = 0 — Wave amplitude bumpHeight = 0.1 — Normal map bump intensity waveLength waterColor = '#0066cc' — Water tint color colorBlendFactor = 0.1 — How much color tints the water windDirectionX windDirectionY wind ## b3d-weather-cell — b3d-weather-cell x = 0 — Centre, world XZ z = 0 — Centre, world XZ radius = 200 — Reach (m); influence eases to nothing at the rim windSpeed = 0 — Wind this cell ADDS at its centre (bearing: where it goes, north-up, clockwise). A lee adds the opposite of the scene's windBearingDeg = 0 — Wind this cell ADDS at its centre (bearing: where it goes, north-up, clockwise). A lee adds the opposite of the scene's coverage = 0 — Cloud cover it adds (summed, clamped 0–2). A storm counts IN FULL, so a cell past 1 closes the sky over its inner part; past 1 it is also darker underneath. (A tower rising out of the deck is opt-in, the deck's `stormRise`.) `0` = no opinion precipitation = 0 — Rain/snow 0–1 (the max of overlapping cells wins) storminess = 0 — Lightning likelihood 0–1 (max wins) temperature = 0 — Temperature offset in degrees (summed) drift = 'off' — `'wind'` = a weather system: it travels with the scene's wind lifetime = 0 — Seconds; grows, holds and dies over it (`0` = permanent). An ended cell does nothing and fires `ended` grow = 0 — Seconds to GATHER from nothing to full (`0` = at once). Independent of `lifetime`, so a permanent storm can still build; with both, it gathers and then ends on its lifetime ## control-input control-input forward = -1..1 — Forward/backward movement strafe = -1..1 — Left/right strafe lookX = -1..1 — Camera look — swings the view, springs back on release lookY = -1..1 — Camera look — swings the view, springs back on release turn = -1..1 — Turning pitch = -1..1 — Pitch (aircraft) throttle = 0..1 — Continuous throttle jump = 0..1 — Jump shoot = 0..1 — Fire weapon sprint = 0..1 — Sprint modifier interact = 0..1 — Enter vehicle / pick up / use aim = 0..1 — Aim down sights weapon = 0..1 — Raise/lower the weapon — edge-detected by consumers, so it TOGGLES cameraZoom = -1..1 — Camera zoom sneak = 0\ — 1 ## game-controller — game-controller wheelSensitivity updateIntervalMs mouseLook mouseSensitivity ## gamepad-svg gamepad-svg strokeColor = #000000 — All stroked elements strokeWidth = 16 — All stroked elements widgetColor = #ffffff — Bumpers, triggers, dpad, sticks, menu, view controllerColor = #aaaaaa — Controller body stickTravelColor = #505050 — Stick travel circles fillA = #ff1d25 — A button (red) fillB = #fcee22 — B button (yellow) fillX = #8cc63f — X button (green) fillY = #3ea9f5 — Y button (blue) ## glass-gamepad — glass-gamepad (b3dGamepad) controls = '' — **Comma**-separated piece list, e.g. `'a,b,right_stick(40,0),menu'`. Empty (the default) shows everything. `a/b/x/y` map to `A/B/X/Y`; `dpad` expands to the four directions; `name(dx,dy)` nudges one piece scale deadzone maxZone idleSeconds = 10 — Seconds of silence before a faded pad comes back fade = 'on' — Hide the pad once a real input device is in use. `'off'` pins it visible — what you want on a page where the pad itself is the subject fadedOpacity = 0 — How faded is faded. `0` is invisible; a low value like `0.15` leaves a hint that the fallback exists ## gradient-editor — width height ## icon-name icon-name r = rotate N° — `chevron90r` f = flip (`0f` = H, `1f` = V) — `chevron0f` s = scale N% — `star75s` x = translateX N% — `plus20x` y = translateY N% — `plus_10y` o = opacity N% — `camera50o` ## key-layout key-layout alpha = shift symbols = punctuation and symbols dial = a telephone keypad — `*` `0` `#`, `+` for international ## keyboard-gamepad — keyboard-gamepad wheelSensitivity updateIntervalMs ## light-modulation Light programs brightness = **multiplies** the base intensity — `0` off, `1` as declared — "off" has to be reachable; it is the value you flicker to range = **multiplies** the base range — a range of zero is a light that lights nothing saturation = **multiplies** saturation — `0` is white, `saturationScale` sets what `1` means — saturation has a meaningful zero and reaching it is the point hue = **shifts** the base hue, `0.5` = unchanged, scaled by `hueShiftDeg — hue is circular with no meaningful zero, so an absolute mapping would discard the colour you chose ## lightning lightning ground = cloud to ground: a bolt, the brightest flash, thunder — most cloud = inside the cloud: the tower lit from within, no bolt — many sprite = ABOVE the storm, 50–90 km up in reality: brief red-pink crowns and tendrils, only over strong storms — rare ## manipulator manipulator translate = the point on the axis closest to the pointer's ray rotate = the angle around the axis where the ray crosses its plane ## picker picker options — `string[]`, or `{value, label?, group?}[]` value = '' — the current selection label = — — drawn to the left of the closed control filter = 'auto' — `'auto'` shows the query field above `filterAbove` options filterAbove = 12 — where `'auto'` starts showing it groups = 'auto' — `'auto'` shows the group chooser when there is more than one group placeholder = 'choose…' — shown when nothing is selected handleChange — the chosen value; fires on pick, and the popup closes ## rocket-ascent Rocket Ascent cloudAltitude = 140 — Centre of the cloud deck (m) spaceStart = 500 — Where the sky begins to fade (m) spaceFull = 2400 — Full vacuum (m) apogee = 3200 — Where it stops and resets (m) accel = 9 — Net acceleration (m/s²) — thrust already minus gravity holdSeconds = 2.5 — Pause on the pad, and again at apogee starfield = 2500 — Background stars (see [b3d-skybox](?b3d-skybox.ts)) nebulae = 0 — Sprite nebulae, OFF — superseded by baking the galaxy rocketScale = 4 — Uniform scale on the Kenney parts timeOfDay = 14 — Broad daylight — so the stars appear because the AIR ran out, not because night fell ## slope-profile slope-profile cliffProfile = flat low shelf → sharp riser → flat top — sea cliffs (Dover) beachProfile = wide gentle low shelf, easing rise — beaches, coastal plain rollingProfile = contrast-compressed midtones — rolling hills mesaProfile = plateauFilter — mesas, mid-level plateaus terraceProfile = steps with sloped risers — terraced hills ## tosi-b3d — b3d glowLayerIntensity = 0 — Glow effect intensity (0 = off) clearColor frameRate = 30 — Target frame rate minElevation = 5 — Default orbit-camera elevation limits (degrees above the horizon) maxElevation = 70 — Default orbit-camera elevation limits (degrees above the horizon) minDistance = 2 — Default orbit-camera zoom limits maxDistance = 50 — Default orbit-camera zoom limits noXr xrGrid xrReticle scenePanelOpen panelSections gamepadScale = 1 — Scale factor for the glass gamepad clusters gamepadFade = 'on' — `'off'` keeps the glass gamepad visible instead of fading it once a mouse/keyboard/hardware pad is used quality pixelRatio stats pauseWhenHidden startPaused reseatFreeze timeScale windSpeed windBearingDeg windGust enterXrOnResume ## voxel-galaxy voxel-galaxy seed = — — Galaxy seed: shapes the density AND derives every voxel's seeds brightBudget = 5000 — Stars in the global pass dimBudget = 95000 — Stars across all voxels' dim passes — most are never generated samples = 100000 — Positions drawn from the spiral model (`sampleSpiral`) to impute the density galaxyOptions = {} — Passed to the sampler (`spiralArms`, `thickness`, …) nx = 64 — Grid resolution across the disc (x) ny = 64 — Grid resolution across the disc (y) nz = 60 — Grid resolution through the disc (z). Must resolve the disc's thickness: at 20 a layer (0.03) was as thick as the disc itself, so stars sat in flat slabs with hard edges, read as columns at 1M stars halfXY = 1.05 — Grid half-extent across the disc halfZ = 0.3 — Grid half-extent through the disc — room for a halo smoothPasses = 1 — Blur passes over the sampled histogram (calms sparse voxels) fringeShare = 0.02 — Share of the budget spread across EMPTY voxels fringeFalloff = 3 — Falloff length for the fringe, in voxels brightMix = O–G5 — The bright population's spectral mix — the bright/dim cut is here dimMix = G6–M — The dim population's spectral mix — underweight late M freely ## weather weather wind = vector SUM — a lee subtracts, a gust adds temperature = signed SUM — a cold cell beside a warm one cancels coverage = SUM, clamped 0–2 — a storm thickens the sky, a clear cell thins it; past 1 is THICKNESS (a storm tower), as on the deck's own dial precipitation = MAX — two storms overlapping do not rain twice as hard storminess = MAX — like volcanism: the worst one wins ## widgets3d widgets3d panel3d = width — `360` label3d = collapsible — `false` row3d = weights — equal slider3d = min` / `max — `0` / `1` toggle3d = label` / `value select3d = options inputField = type — `'text'` list3d = items` / `onSelect button3d = label` / `onClick menu3d = items` / `handleSelect iconBar3d = items tabs3d = tabs` / `active` / `handleSelect — `0` spinner3d = label` / `size progress3d = label` / `value` / `showValue ## xr-frames xr-frames world = the play space — a hologram on a table rig = the locomotion rig (vehicle) — a piloting HUD that flies with you body = your torso (head x/z + **damped** yaw) — waist inventory, over-shoulder backpack neck = your neck pivot — UI you can look *past* face = your eyes (head-locked) — a reticle, a vignette, sunglasses ## xr-gamepad xr-gamepad leftBumper = xr-standard-squeeze` (grip) rightBumper = xr-standard-squeeze` (grip)