Builtin Library
README.md
sceneProxy
The public surface: build, refresh, destroy, built, building,
settings, sampleAt, distanceAt, gridParams, and — for a field that keeps
itself current — track, untrack, tracking, maintain, trackingStats,
claim, release, claimed.
It owns the grid and drives the passes. Geometry reaches the GPU through
compute.buildBvh, whose triangle buffer the voxelize pass reads directly, so
scene geometry never passes through the scripting heap. The BVH's root node
also bounds every triangle it was built from, which is where the grid's default
extent comes from — exact, and cheaper than re-deriving it from instance
transforms, which carry a centre rather than a size.
refresh reallocates the occupancy volume rather than clearing it. The scatter
only ever sets voxels, so a stale mark left by a surface that has since moved
would never be cleared by the pass itself.
sampleAt and distanceAt answer through the proxy_probe pass, which reads
the field with the entry points scene_proxy.shaderModule publishes — so a
script and a consuming pass get their answers from one piece of code. They yield
while the GPU answers. A consuming shader includes the module and samples the
volume directly instead.
Following the scene
track records what to follow and returns at once; maintain is the tick that
does the work, and it never yields, so a component update can drive it.
A walk over the scene reads each entity's placement through
Baking.entityWorldMatrix, which is where gatherMeshInstances gets the
transform it puts in the instance record too, so the tick and the build derive
what they compare the same way. A refresh is started when one placement moved
further than motion voxels from where the landed field put it. Because the
comparison is against the landed field rather than the previous frame, a surface
drifting below the threshold never accumulates into a refresh.
Every entity has to be looked at to find the few that carry geometry, so the walk is spent a slice at a time: the interval decides when a walk starts, a tick steps it for a bounded couple of milliseconds, and the walk decides nothing until it has seen the scene through. A tick's cost is therefore bounded by the slice rather than by how many entities the scene holds.
A tick with nothing built yet builds the grid, which is what lets a scene say
only what it wants followed, and one whose grid stands at a resolution nobody is
asking for any more rebuilds it. Geometry that has left the extent the grid
covers rebuilds it around the scene's new size while refit is on.
claim and release are track for something whose own presence is the
request — a component, a system. Tracking is on while at least one claim stands,
the settings in force are the newest claim's, and the grid goes when the last
claim does, so two of them share one grid instead of one turning the other's
off. claimed is what a claimant asks to find out whether a release elsewhere
took its claim with it.
A build runs inside a task and holds a lock while it does. The lock carries both
a deadline and the identity of its holder: past the deadline the next caller
takes it, and a holder can only release the lock it took, so a build that
overran cannot release its successor's. destroy releases the work in flight
along with the grid — what it was making is a grid nothing asked for any more —
rather than letting it land afterwards over torn-down volumes.