Display-space positions (vertexCount * 3)
Vertex indices of the visible triangles (visibleFaceCount * 3), in the
ORIGINAL (un-remapped) vertex numbering.
Triangles that survived the cull
Vertices that passed the slab test (diagnostic; not a draw bound)
The material side this epoch requires.
'front' only when the node asked for single-sided AND projected winding is
decidable (see resolveWinding); 'double' otherwise.
Whether this epoch's displayed axes are the frame the stored normals were authored in — see storedNormalsUsable.
Sits next to side because it is the same kind of quantity: a per-epoch
consequence of displayDims that the material must be told about, not a
property of the node. side decides which faces draw; this decides which
normal the shade term reads.
false on a node with no stored normals at all, so a consumer needs only this
one flag (plus the view-independent shading) to pick the shader variant.
True when the cull was skipped because there are no hidden dimensions
True when position was (re)extracted this epoch — i.e. displayDims changed,
or this is the first projection.
Reported explicitly because the position buffer is REUSED across epochs
(LoadedMeshData.projection), so its array identity can no longer signal a
change. Consumers must gate the re-upload and the bounds recompute on this
rather than on identity; using identity with a reused buffer silently stops
re-uploading after an axis permutation, and using it with a freshly allocated
buffer re-uploads the whole mesh on every slice move (#1245).
The displayDims.join() these positions were extracted for. The commit stamps it
on the geometry and re-uploads whenever it differs from the geometry's last-uploaded
key — so an aborted commit (which advanced the loader's displayDimsKey but never
uploaded) is still repaired by the next commit at that displayDims.
positionChanged alone cannot: it is a projection-time signal and reads false on
the epoch after a superseded re-extraction.
Display-space AABB over the vertices the emitted index references, or null when
nothing is drawn.
Same role as LinesProjectionBounds / GSplatsProjectionBounds: the projection
computes it and computeMeshBounds sets the geometry's box and sphere from it.
Bounding the INDEXED vertices rather than the whole position buffer is the point —
under no-compaction position holds every vertex of the whole nD mesh, so a 4D
surface that translates over time would otherwise frame its entire trajectory
(#1252).
OptionalundecidableSet when the node asked for single-sided rendering but winding could not be decided, carrying the reason. Threaded out to the caller rather than logged here so resolveWinding and projectMeshTo3D stay free of side effects — the projection runs on every slice move, so a warning emitted at this depth would flood the console during a scrub.
Everything the geometry builder needs for one projection epoch.