Builtin Library
README.md
frame_bounds
Bounds union and exact frustum fitting — the math behind "put this subject in frame".
fit solves for the camera distance that keeps every corner of a box inside
the frustum at a given orbit angle. That is exact for any shape at any angle,
which a circumscribed sphere is not: a sphere frames the DIAGONAL of the box
from every direction, so a 14 x 0.5 x 14 plate backs the camera off nearly
1.4x further than its silhouette needs.
Two consumers share this one implementation: the capture toolbox's framed shots and editor frame-selection. Toolboxes are self-contained and never cross-require, so the math lives here as a module rather than inside either.
local FrameBounds = require("@builtin::modules.frame_bounds")
local box = FrameBounds.union({
FrameBounds.ofEntity(entity.find("player")),
FrameBounds.ofEntity(entity.find("prop")),
})
local framed = FrameBounds.fit(box, { fov = 60, aspect = 16 / 9, angle = { 0, 20 } })
-- framed.px/py/pz is where the camera goes, framed.cx/cy/cz is what it looks at.
Exports
FrameBounds.union(boxes) -> Aabb?— the AABB enclosing every box in the list.nilwhen the list is empty (or holds nothing withmin/max), which is the signal that there is nothing to frame.FrameBounds.ofEntity(target) -> Aabb?— world-space bounds of an entity and its descendants (hierarchyBounds, covering a character root plus its skinned mesh and bones), falling back to the entity's own meshbounds.nilwhen the target has no renderable geometry.FrameBounds.fit(box, opts?) -> Framed— a camera pose that framesbox.optsis{ fov = 60, aspect = 16/9, margin = 1.15, angle = { yawDeg, pitchDeg } };anglealso accepts{ yaw = , pitch = }. Returns{ px, py, pz, cx, cy, cz, distance, radius, fov, near, far, center, size }— camera position, look-at point (the box centre), the fitted distance, the bounding-sphere radius, geometry-derived near/far clip planes, and the box's centre and full size. A degenerate (point) box gets a short fixed distance so the camera is not sitting inside the subject.FrameBounds.fitDistance(hx, hy, hz, dx, dy, dz, tanH, tanV) -> number— the corner projection itself: the smallest distance along the orbit direction(dx, dy, dz)(subject toward camera, unit length) that keeps all eight corners of the half-extent box inside a frustum with half-angle tangentstanH/tanV.fitappliesmarginto this; call it directly when you already have a direction and want the raw fit.