Builtin Library
README.md
Wind
Air moving through the world, placed as an entity and saved with its scene: a breeze over the whole map, a gale on a cliff top, a fan, an updraft over a vent, a wind tunnel, the gap between two buildings. Every body carrying FluidForces or a LiftSurface feels it inside each physics step, and Physics.wind(point) reads it, so a flag, a tree or a particle system that bends to it matches what the bodies feel.
Public fields:
kind(default"steady"): what the wind blows."steady"blowsvelocity."grid"blows a velocity per texel over thesizebox (above 0 along every axis), read smoothly between the texels' centres: air flowing around a building, a valley channelling it, a storm front painted over a map.columnstexels along X,rowsalong Z andlayersalong Y (each default1; one layer is a map, read the same at every height of the box);velocitieslists x, y, z per texel in m/s, in the world's frame, along X first, then Z, then Y (the texel at column c, row r, layer y, counted from 0, starts at number 3 * ((y * rows + r) * columns + c) + 1). Ortexturenames a float (rgba32f) texture asset whose texels are the velocities: red, green and blue are x, y and z in m/s, its width the columns and its height the rows, its first row at the box's -Z face; it is read when the component starts, is enabled or has a field changed (moving the entity carries the texels already read), and an 8-bit texture is refused with the format it holds.scroll(m/s, default{0, 0, 0}) moves the pattern through its box, wrapping around it;wrap = truerepeats the grid past its box, where otherwise it blows within its box alone."vortex"turns the air about this entity's up axis through its position, like a solid body inside a core ofradiusmetres (default5), whose edge turns atspeedm/s (default10, by the right-hand rule about the axis, negative the other way; the core turns atspeed / radiusrad/s), slowing asradius / distanceoutside it;inflow(m/s, default0) draws the air in toward the axis andupdraft(m/s, default0) lifts it on the axis, fading to nothing atupdraftRadiusmetres from it (default0: the core's edge; wider, a column that carries up what the vortex swings around outside its core): a tornado, a dust devil."radial"blows out of this entity's position atspeedm/s atradiusmetres (negative draws the air in), rising from nothing at the centre: out in every direction withspread = "point"(the default, slowing by the square of the distance: a blast), or out across its up axis withspread = "line"(slowing by the distance: a rotor's downwash).
velocity(m/s, default{5, 0, 0}) inspace, added on top of every kind (set it to{0, 0, 0}for a vortex or a radial wind standing still in the air):"local"(default: this entity's own frame, so a fan blows along its own axis however it is turned, and a vortex turns about its own up) or"world".gust(m/s, default0): how far the speed rises and falls along the wind's direction, overgustPeriodseconds (default4), the gusts travelling downwind and differing across the wind overgustSizemetres (default20).size(m, default all0): with all 0 the wind blows everywhere; otherwise within a world-aligned box of that size centred on the entity, which follows the entity as it moves.falloff(m, default0): how far inside the box's faces the wind reaches full strength. Every face fades it, the floor and the top included, so a wind meant to blow at full strength along the ground puts the box's floor at leastfalloffbelow it.
Several winds covering a point add up. Disabling the component stills its wind. A wind is the field Physics.defineWind defines, kept in step with the component: Physics.winds() lists it, and a script defines a wind of its own the same way, including a field stated in an entity's own space (space = "entity").
-- a gusting breeze over the whole level
level.component.add("Wind", { velocity = { 6, 0, 2 }, gust = 3, space = "world" })
-- an updraft 6 m across and 20 m high over a vent, soft at its edges
vent.component.add("Wind", { velocity = { 0, 9, 0 }, size = { 6, 20, 6 }, falloff = 1 })
-- a fan blowing along its own +Z, turning with it
fan.component.add("Wind", { velocity = { 0, 0, 12 }, size = { 3, 3, 10 }, falloff = 0.5 })
-- a tornado 40 m across, drawing the air in and lifting it over a column 12 m from its axis, that goes where its entity goes
twister.component.add("Wind", { kind = "vortex", velocity = { 0, 0, 0 }, radius = 5, speed = 30, inflow = 4, updraft = 10, updraftRadius = 12, size = { 40, 60, 40 }, falloff = 8 })
-- a 40 m square map of 2 x 2 texels: calm in one corner, 4 m/s along +X in the next two and 8 m/s in the far one
pass.component.add("Wind", { kind = "grid", velocity = { 0, 0, 0 }, size = { 40, 20, 40 }, columns = 2, rows = 2,
velocities = { 0, 0, 0, 4, 0, 0, 4, 0, 0, 8, 0, 0 } })
-- the same kind of map baked into a float texture: red, green, blue are the wind's x, y, z
local map = asset.create("texture", "valleyWind", { rgba = texels, width = 64, height = 64, settings = { compression = "rgba32f" } })
valley.component.add("Wind", { kind = "grid", velocity = { 0, 0, 0 }, size = { 400, 60, 400 }, texture = map })
-- a blast pushing everything out of a 20 m box
bomb.component.add("Wind", { kind = "radial", velocity = { 0, 0, 0 }, radius = 2, speed = 40, size = { 20, 20, 20 } })