controlMath
The small maths the two swarm-control components share.
controlMath
The small maths the two swarm-control components share.
It exists mostly for one reason: the flight model and the camera have to agree on what an orientation is. Two files each writing their own quaternion is how a camera ends up banking the opposite way from the thing it is watching, so the convention lives here once — yaw about world +Y, then the flight-path pitch, then the roll.
local M = require("locust.control.controlMath")
| Call | What it is for |
|---|---|
M.approach(v, target, rate) | Rate limiting, in units per call — real acceleration, not an ease that never arrives |
M.lag(dt, seconds) | Frame-rate independent blend factor for a time constant |
M.angleTo(from, to) | Shortest signed angle, in (-pi, pi] |
M.qmul(...) | Hamilton product of two {x,y,z,w} quaternions |
M.yawPitchRoll(yaw, pitch, roll) | The slice's orientation convention, as a rotation |
M.lookRotation(dx, dy, dz, roll) | The rotation that makes a camera look along a direction |
M.rotate(q, x, y, z) | Rotate a vector by a quaternion |
M.framing(camEntity, fovDeg, x, y, z, radius) | Where a sphere is sitting in a camera's frame |
Two of those are worth a sentence.
lookRotation carries the half-turn. A camera's own forward is -Z, so a
yaw derived from a +Z-forward aim vector points it exactly backwards; the
+ pi is what makes it look at the subject instead of away from it.
framing answers "is the swarm still readable?" as numbers rather than a
screenshot: screenY is 0 at dead centre and ±1 at the frame edge, fill is
the share of the frame height the sphere's diameter covers, and behind is
true when no camera placement can save it. It is reachable live as
require("locust.locustCore").systems.control.framing()
which is the check to run after touching anything about how the camera is placed — and the way another slice can ask whether what it drew is actually on screen.
Scoped to this part · feeds back into the world's score.