Runs after the main updateView() commits LOD 0, loading additional
LODs one pass at a time with a requestAnimationFrame yield between
each pass — each LOD level is painted as a separate frame, giving
visible progressive refinement.
The refinement loop does NOT go through SceneLoader's updateView()
entry point (which has the serialization lock). It directly calls
loader.updateView() + process + commit for GSplats loaders only.
Cancellation: if the view-state queue has pending state (the user
navigated), the loop aborts and re-triggers updateView via the
normal serialization path. The serialization lock is held by the
caller; on cancellation, the loop calls the supplied retriggerUpdate
callback which is responsible for releasing the lock and re-entering
updateView at the next rAF (or synchronously in test environments).
Timing is load-bearing: every iteration starts with a rAF yield so
each LOD pass paints separately. Test environments without rAF fall
through synchronously.
Progressive GSplats LOD refinement loop.
Runs after the main updateView() commits LOD 0, loading additional LODs one pass at a time with a requestAnimationFrame yield between each pass — each LOD level is painted as a separate frame, giving visible progressive refinement.
The refinement loop does NOT go through SceneLoader's updateView() entry point (which has the serialization lock). It directly calls loader.updateView() + process + commit for GSplats loaders only.
Cancellation: if the view-state queue has pending state (the user navigated), the loop aborts and re-triggers updateView via the normal serialization path. The serialization lock is held by the caller; on cancellation, the loop calls the supplied retriggerUpdate callback which is responsible for releasing the lock and re-entering updateView at the next rAF (or synchronously in test environments).
Timing is load-bearing: every iteration starts with a rAF yield so each LOD pass paints separately. Test environments without rAF fall through synchronously.