Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

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" blows velocity.
    • "grid" blows a velocity per texel over the size box (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. columns texels along X, rows along Z and layers along Y (each default 1; one layer is a map, read the same at every height of the box); velocities lists 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). Or texture names 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 = true repeats 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 of radius metres (default 5), whose edge turns at speed m/s (default 10, by the right-hand rule about the axis, negative the other way; the core turns at speed / radius rad/s), slowing as radius / distance outside it; inflow (m/s, default 0) draws the air in toward the axis and updraft (m/s, default 0) lifts it on the axis, fading to nothing at updraftRadius metres from it (default 0: 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 at speed m/s at radius metres (negative draws the air in), rising from nothing at the centre: out in every direction with spread = "point" (the default, slowing by the square of the distance: a blast), or out across its up axis with spread = "line" (slowing by the distance: a rotor's downwash).
  • velocity (m/s, default {5, 0, 0}) in space, 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, default 0): how far the speed rises and falls along the wind's direction, over gustPeriod seconds (default 4), the gusts travelling downwind and differing across the wind over gustSize metres (default 20).
  • size (m, default all 0): 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, default 0): 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 least falloff below 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 } })