diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-07-19 14:27:13 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-07-19 14:27:13 +0300 |
commit | 8c90910dcc3ac56ecaa3f0d0ed1a43a423ff687f (patch) | |
tree | 713ac786e3470efe7f3e04625e5b4945d274f042 | |
parent | ccd2af43b3ab83dc873010faade1b2916553291a (diff) |
Fix T66937: Blank view on navigation with auto-deph & large clip-end
-rw-r--r-- | source/blender/blenlib/BLI_math_geom.h | 7 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_geom.c | 31 | ||||
-rw-r--r-- | source/blender/gpu/GPU_matrix.h | 12 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_matrix.c | 14 |
4 files changed, 53 insertions, 11 deletions
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index f51486c5e7b..64b0dcccda1 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -671,6 +671,13 @@ void projmat_dimensions(const float projmat[4][4], float *r_top, float *r_near, float *r_far); +void projmat_dimensions_db(const float projmat[4][4], + double *r_left, + double *r_right, + double *r_bottom, + double *r_top, + double *r_near, + double *r_far); void projmat_from_subregion(const float projmat[4][4], const int win_size[2], diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index d3dc4729617..2891279bb63 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -4880,6 +4880,37 @@ void projmat_dimensions(const float projmat[4][4], } } +void projmat_dimensions_db(const float projmat_fl[4][4], + double *r_left, + double *r_right, + double *r_bottom, + double *r_top, + double *r_near, + double *r_far) +{ + double projmat[4][4]; + copy_m4d_m4(projmat, projmat_fl); + + bool is_persp = projmat[3][3] == 0.0f; + + if (is_persp) { + *r_left = (projmat[2][0] - 1.0) / projmat[0][0]; + *r_right = (projmat[2][0] + 1.0) / projmat[0][0]; + *r_bottom = (projmat[2][1] - 1.0) / projmat[1][1]; + *r_top = (projmat[2][1] + 1.0) / projmat[1][1]; + *r_near = projmat[3][2] / (projmat[2][2] - 1.0); + *r_far = projmat[3][2] / (projmat[2][2] + 1.0); + } + else { + *r_left = (-projmat[3][0] - 1.0) / projmat[0][0]; + *r_right = (-projmat[3][0] + 1.0) / projmat[0][0]; + *r_bottom = (-projmat[3][1] - 1.0) / projmat[1][1]; + *r_top = (-projmat[3][1] + 1.0) / projmat[1][1]; + *r_near = (projmat[3][2] + 1.0) / projmat[2][2]; + *r_far = (projmat[3][2] - 1.0) / projmat[2][2]; + } +} + /** * Creates a projection matrix for a small region of the viewport. * diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h index 56d640ea0e4..eabfb5d2dc3 100644 --- a/source/blender/gpu/GPU_matrix.h +++ b/source/blender/gpu/GPU_matrix.h @@ -102,11 +102,15 @@ struct GPUMatrixUnproject_Precalc { float model_inverted[4][4]; float view[4]; bool is_persp; - /** Result of 'projmat_dimensions'. */ + /** + * Result of #projmat_dimensions_db. + * Using double precision here is important as far clipping ranges + * can cause divide-by-zero when using float, see: T66937. + */ struct { - float xmin, xmax; - float ymin, ymax; - float zmin, zmax; + double xmin, xmax; + double ymin, ymax; + double zmin, zmax; } dims; }; diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c index d0f7eab32a3..669bf56b726 100644 --- a/source/blender/gpu/intern/gpu_matrix.c +++ b/source/blender/gpu/intern/gpu_matrix.c @@ -536,13 +536,13 @@ bool GPU_matrix_unproject_precalc(struct GPUMatrixUnproject_Precalc *precalc, const int view[4]) { precalc->is_persp = proj[3][3] == 0.0f; - projmat_dimensions(proj, - &precalc->dims.xmin, - &precalc->dims.xmax, - &precalc->dims.ymin, - &precalc->dims.ymax, - &precalc->dims.zmin, - &precalc->dims.zmax); + projmat_dimensions_db(proj, + &precalc->dims.xmin, + &precalc->dims.xmax, + &precalc->dims.ymin, + &precalc->dims.ymax, + &precalc->dims.zmin, + &precalc->dims.zmax); if (isinf(precalc->dims.zmax)) { /* We cannot retrieve the actual value of the clip_end. * Use `FLT_MAX` to avoid nans. */ |