Fix #143857: View3D smooth interpolation produces invalid rv3d.dist values

In the particular case of the report it creates a rv3d with `dist == 0`.

This causes EEVEE to create an invalid projection matrix when
calling `RE_GetWindowMatrixWithOverscan` with a zero `viewplane`.

To avoid this, we check if `rv3d->dist == 0` and don't compute overscan
in this case. This avoid many issues down the line.

Candidate for backporting to 4.5 LTS.

Pull Request: https://projects.blender.org/blender/blender/pulls/143946
This commit is contained in:
Clément Foucault
2025-08-05 11:01:03 +02:00
committed by Clément Foucault
parent d3f6523536
commit 83c5e81a8b
2 changed files with 15 additions and 11 deletions

View File

@@ -145,19 +145,23 @@ void Camera::sync()
BKE_camera_params_from_view3d(&params, inst_.depsgraph, inst_.v3d, inst_.rv3d);
}
BKE_camera_params_compute_viewplane(&params, UNPACK2(display_extent), 1.0f, 1.0f);
if (inst_.rv3d->dist > 0.0f && params.lens > 0.0f) {
BKE_camera_params_compute_viewplane(&params, UNPACK2(display_extent), 1.0f, 1.0f);
BKE_camera_params_crop_viewplane(&params.viewplane, UNPACK2(display_extent), &film_rect);
BLI_assert(BLI_rctf_size_x(&params.viewplane) > 0.0f);
BLI_assert(BLI_rctf_size_y(&params.viewplane) > 0.0f);
RE_GetWindowMatrixWithOverscan(params.is_ortho,
params.clip_start,
params.clip_end,
params.viewplane,
overscan_,
data.winmat.ptr());
BKE_camera_params_crop_viewplane(&params.viewplane, UNPACK2(display_extent), &film_rect);
if (params.lens == 0.0f) {
/* Can happen for the case of XR.
RE_GetWindowMatrixWithOverscan(params.is_ortho,
params.clip_start,
params.clip_end,
params.viewplane,
overscan_,
data.winmat.ptr());
}
else {
/* Can happen for the case of XR or if `rv3d->dist == 0`.
* In this case the produced winmat is degenerate. So just revert to the input matrix. */
data.winmat = inst_.drw_view->winmat();
}

View File

@@ -304,7 +304,7 @@ void ED_view3d_smooth_view_ex(
Object *ob_camera_old_eval = DEG_get_evaluated(depsgraph, sview->camera_old);
if (sview->ofs != nullptr) {
sms.src.dist = ED_view3d_offset_distance(
ob_camera_old_eval->object_to_world().ptr(), sview->ofs, 0.0f);
ob_camera_old_eval->object_to_world().ptr(), sview->ofs, 0);
}
ED_view3d_from_object(
ob_camera_old_eval, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);