From eb8de8cab2ab154e50214c3d673da3eb7118549f Mon Sep 17 00:00:00 2001 From: YimingWu Date: Wed, 24 Jul 2024 15:45:33 +0200 Subject: [PATCH] Fix #125340: Div by zero in LineArt shadow stage There could be a rare case where a div by zero situation would take place in LineArt shadow stage where the silhouette and shadows are calculated, which would cause infinite shadow edge cutting. Now will return a non-cutting state for those edge cases. Pull Request: https://projects.blender.org/blender/blender/pulls/125361 --- .../intern/lineart/lineart_shadow.cc | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_shadow.cc b/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_shadow.cc index b007d866eff..d89e17367e0 100644 --- a/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_shadow.cc +++ b/source/blender/gpencil_modifiers_legacy/intern/lineart/lineart_shadow.cc @@ -185,7 +185,14 @@ static void lineart_shadow_segment_slice_get(double *fb_co_1, double *r_gloc) { double real_at = ((at_2 - at_1) == 0) ? 0 : ((ratio - at_1) / (at_2 - at_1)); - double ga = fb_co_1[3] * real_at / (fb_co_2[3] * (1.0f - real_at) + fb_co_1[3] * real_at); + double ga_div = (fb_co_2[3] * (1.0f - real_at) + fb_co_1[3] * real_at); + double ga; + if (ga_div == 0) { + ga = 0; + } + else { + ga = fb_co_1[3] * real_at / ga_div; + } interp_v3_v3v3_db(r_fb_co, fb_co_1, fb_co_2, real_at); r_fb_co[3] = interpd(fb_co_2[3], fb_co_1[3], ga); interp_v3_v3v3_db(r_gloc, gloc_1, gloc_2, ga); @@ -283,8 +290,14 @@ static bool lineart_do_closest_segment(bool is_persp, double dl = s1_fb_co_1[z_index] - s2_fb_co_1[z_index]; double dr = s1_fb_co_2[z_index] - s2_fb_co_2[z_index]; double ga = ratiod(dl, dr, 0); - *r_new_at = is_persp ? s2_fb_co_2[3] * ga / (s2_fb_co_1[3] * (1.0f - ga) + s2_fb_co_2[3] * ga) : - ga; + double ga_div = s2_fb_co_1[3] * (1.0f - ga) + s2_fb_co_2[3] * ga; + if (ga_div == 0) { + *r_new_at = 0; + return false; + } + else { + *r_new_at = is_persp ? s2_fb_co_2[3] * ga / ga_div : ga; + } interp_v3_v3v3_db(r_new_in_the_middle, s2_fb_co_1, s2_fb_co_2, *r_new_at); r_new_in_the_middle[3] = interpd(s2_fb_co_2[3], s2_fb_co_1[3], ga); interp_v3_v3v3_db(r_new_in_the_middle_global, s1_gloc_1, s1_gloc_2, ga);