Vertex count, <= MAX_MESH_VERTICES
Triangle count, >= 1
Coordinate dimensionality; equals the vertices declared width
OptionalcolorChannels per color entry, when colors is present. Observation only — see above.
OptionalnormalThe validated normal_dims, when normals is present. Observation only — see above.
The node's total accounted bytes (stored + decoded + largest chunk) — the
exact quantity this function compares against MESH_DECODE_BUDGET_BYTES.
HAS a production consumer, unlike colorComponents/normalDims above: the
mesh reveal ladder sums this across every level to charge the ladder once
against one budget, IN ADDITION TO each level's own per-level check here
against that same budget — not instead of it.
OptionaltextureThe validated texture declaration, when the node has a texture.
A production consumer, like accountedBytes and unlike the two
observation-only fields above: the loader decodes and Stage-2-checks against
THESE numbers rather than re-reading attrs.texture_*. Re-reading would put a
second, unvalidated copy of the load-bearing dimensions in the one place that
allocates from them — the same "re-deriving the accounting" mistake that
bypassed the byte budget four times.
What Stage 1 established.
The first three fields are the ones Stage 2 reads: the loader destructures
{ nVertices, nFaces, ndim }and everyvalidateMaterializedLengthcall derives its expected length from them.The last two are deliberately NOT a source of truth, and it matters that this is stated, because the codebase's own rule is that a field no consumer reads is indistinguishable from a field that is wrong (see
scene-loader/geometry-descriptors.ts). Both are byproducts of Stage 1 VALIDATION — the checks are the point, the values are how a test can observe that the checks ran. Their real consumers read elsewhere on purpose:colorComponents— the loader calls the sharedcolorComponentsOf, the same helper the three sibling loaders use, rather than threading this through. The two agree because Stage 1 has already rejected anything but 3 or 4, which is the strictnesscolorComponentsOf(non-4 ⇒ 3) does not have on its own.normalDims— the winding frame reachesprojectMeshTo3Dfrom the node'sattrs.normal_dimsvia the handler, since the projection runs per slice move and does not hold a preflight.So: read these two in tests, not in production code.
accountedBytesis different — unlike the two above, it HAS a production consumer. It is the samepeakBytesfigure this function's own byte-budget check compares againstMESH_DECODE_BUDGET_BYTES(stored bytes, decoded bytes and the largest single chunk buffer, summed), returned so a caller charging several preflights against ONE ceiling —mesh-progressive-loader.ts'sMeshProgressiveLoader.assertWithinByteBudget, for a reveal ladder's levels — never has to re-derive the accounting itself. Re-deriving it is exactly how the budget was bypassed four times before (seeENCODING_BUDGET_KIND's docstring); returning the number this function already computed keeps there being exactly one place that does the arithmetic.