From 836e7269f6055bd01e5d7df258190d403a726b6e Mon Sep 17 00:00:00 2001 From: Quinn Elara <128988672+Quinn-Elara@users.noreply.github.com> Date: Sat, 5 Sep 2026 18:41:39 +0100 Subject: [PATCH] render: guard generateImpostor against degenerate fov/aspect When an avatar's spatial extents project to zero in the camera's up axis (collapsed bounding box, extreme distance, or a lookAt singularity when the avatar is directly above or below the camera), tdim.mV[1] is zero. This produces fov=0 and aspect=NaN, which assert-crash inside glm::perspectiveRH_NO before the perspective matrix is written. Add a finite/positive check on fov and aspect before the GL matrix push. On failure, restore pushRenderTypeMask, sUseOcclusion, sShadowRender and sImpostorRender and return early. Move the MM_PROJECTION pushMatrix to after the guard so no pop is needed on the early-out path and the normal path has exactly one push. Fixes a reproducible crash when impostoring a distant avatar (>3km) while the viewer window is in the background. --- indra/newview/pipeline.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f24b2ad60a5..3d8aa4ed20b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -12546,13 +12546,32 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool tdim.mV[0] = half_height.dot3(left).getF32(); tdim.mV[1] = half_height.dot3(up).getF32(); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); F32 distance = (pos-camera.getOrigin()).length(); F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG; F32 aspect = tdim.mV[0]/tdim.mV[1]; + // Guard against degenerate geometry: the avatar's bounding box can project + // to zero in one or both axes (collapsed extents, extreme distance, or a + // lookAt singularity when the avatar is directly above/below the camera). + // fov==0 or non-finite aspect both produce an unusable projection matrix + // and assert-crash inside glm::perspectiveRH_NO. + if (fov <= 0.f || !std::isfinite(aspect) || aspect <= 0.f) + { + LL_WARNS_ONCE("AvatarRenderPipeline") << "generateImpostor: degenerate fov/aspect for avatar " + << avatar->getID() << " (fov=" << fov << " aspect=" << aspect + << " distance=" << distance << " tdim=" << tdim.mV[0] << "," << tdim.mV[1] + << ") -- skipping impostor bake this frame" << LL_ENDL; + popRenderTypeMask(); + sUseOcclusion = occlusion; + sShadowRender = saved_shadow_render; + sImpostorRender = saved_impostor_render; + return; + } + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + // Clip planes bracketing the subject instead of a hardcoded 1..256. // // Impostoring is chosen by rank, not distance (LLVOAvatar::shouldImpostor), so an