`model_wires_for_viewport` previously passed `view_aabb: None` and
`wpp: None` to `tessellate_entity` — the assumption that paper-space
viewports were too small for culling to matter falls over the moment
the document carries 100k+ entities. Each frame re-tessellated the
full model through every floating viewport.
`wires_for_block_culled` grows two optional parameters
(`frozen_layers`, `anno_scale_override`) and now flips its
`world_offset` / `bg` / `anno` selection on `is_model_block` rather
than `current_layout`, so a paper-layout caller asking for the model
block still gets WCS-subtracted coordinates and the right annotation
scale.
`model_wires_for_viewport`:
- derives the viewport's frustum AABB from its (paper-zoom-invariant)
camera + entity aspect — 25 % margin to match `view_world_aabb`,
- derives `wpp` from the on-paper pixel height the viewport currently
occupies, so LOD stubs and zoom-adaptive curve sampling track the
paper-zoom state,
- delegates everything else to `wires_for_block_culled` so block /
layer / frozen-layer / curve-tolerance handling stays in one place.
`model_wires_for_viewport_arc` keys on `(geometry_epoch,
round(screen_height_px))` — sub-pixel jitter still hits the cache,
real paper-zoom steps invalidate. Hit-test / CPU-projection callers
pass `screen_height_px = 0.0` to get the no-LOD (full-fidelity) wire
list in their own cache slot.