try_export_glb_streaming_bounded

Function try_export_glb_streaming_bounded 

Source
pub fn try_export_glb_streaming_bounded(
    content: &[u8],
    opts: &GltfOptions,
) -> Result<(Vec<u8>, GltfStats), ExportError>
Expand description

Bounded-memory single-GLB export: two passes over the deterministic mesh stream (retain_emitted_meshes: false, peak input = one batch).

Pass 1 ([plan_bounded_glb]) records per-mesh METADATA only (counts, local bbox, colour, ids, content-hash) plus the world AABB; the complete glTF JSON is then built and the final GLB Vec is preallocated at its exact container size. Pass 2 ([write_bounded_glb]) re-streams the same meshes and bakes their bytes straight into the output at precomputed offsets. Peak memory = the final artifact + one batch + metadata — never the whole model’s MeshData, never a growing three-run scratch, and never a second full copy from a final concatenation.

Fail-closed on both ends, decided after pass 1 so neither costs the second meshing pass or the output allocation: an empty visible set returns ExportError::NoRenderGeometry (see try_export_glb for why a zero-mesh GLB is not a valid artifact, #4685), and a projected GLB over the glTF 4 GiB limit returns ExportError::TooLarge carrying the projected byte size (#1516). project_glb_size decides the size question up front.

Tradeoffs vs the in-memory assembler (build_gltf):

  • rep-identity instancing is done here too, under the same policy collate_refs applies. The vertex data needs every occurrence co-resident; the grouping decision does not, so it is made from the plan. Quantized, the dequant rides a child node under the placement node, as in build_gltf.
  • content-hash dedup is kept (the hash is computed batch-locally on pass 1).
  • the model is meshed twice (the price of bounded memory).
  • the #3666 reconstruction check does not run here. The in-memory assembler reconstructs each exact-tier occurrence from its template and relative transform and compares it against that occurrence’s own baked vertices, so a rep_identity COLLISION between unrelated geometry falls back to flat. This path holds a plan, not geometry, so it has no occurrence vertices to compare; its guard remains vertex/index counts, which a same-shaped colliding pair passes. The returned GltfStats::unverified_instance_groups counts the groups shipped on that weaker guard (always 0 from the in-memory path).

Supports both the f32 and the KHR_mesh_quantization layouts; the quantized accessor min/max come from the local bbox in closed form (the quantize map is monotone per axis). Caveat: a NaN vertex coordinate quantizes to 0 in the byte stream on both paths, but only the in-memory fold lets that 0 into the accessor min/max hint; clean meshes are byte-identical.