[Bf-blender-cvs] [6a9b09a5e93] temp-lineart-contained: LineArt: Better handling of boundary cases.

YimingWu noreply at git.blender.org
Sun Nov 7 15:41:34 CET 2021


Commit: 6a9b09a5e93626a102c6c391d452aaddafc45f48
Author: YimingWu
Date:   Sun Nov 7 22:37:37 2021 +0800
Branches: temp-lineart-contained
https://developer.blender.org/rB6a9b09a5e93626a102c6c391d452aaddafc45f48

LineArt: Better handling of boundary cases.

For lineart_LineIntersectTest2d, it fixes the output to 0 or 1 when it's
close enough, gives correct range for point_on_triangle identification.

Then it gives more information through aAligned, which will be true if
two lines completely align, this helps later identification.

Finally: it handles complex cases where one point is on the edge of
a triangle while another point is on the outside.

===================================================================

M	source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
M	source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
M	source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c

===================================================================

diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
index a5860698cba..f8ecb4bdff5 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
@@ -492,11 +492,18 @@ typedef struct LineartBoundingArea {
 #define LRT_MIN3_INDEX_ABC(x, y, z) (x < y ? (x < z ? a : (y < z ? b : c)) : (y < z ? b : c))
 
 #define LRT_ABC(index) (index == 0 ? a : (index == 1 ? b : c))
+#define LRT_PABC(index) (index == 0 ? pa : (index == 1 ? pb : pc))
 
 #define LRT_DOUBLE_CLOSE_ENOUGH(a, b) (((a) + DBL_EDGE_LIM) >= (b) && ((a)-DBL_EDGE_LIM) <= (b))
-
-BLI_INLINE int lineart_LineIntersectTest2d(
-    const double *a1, const double *a2, const double *b1, const double *b2, double *aRatio)
+#define LRT_DOUBLE_CLOSE_ENOUGH_TRI(a, b) \
+  (((a) + DBL_TRIANGLE_LIM) >= (b) && ((a)-DBL_TRIANGLE_LIM) <= (b))
+
+BLI_INLINE int lineart_LineIntersectTest2d(const double *a1,
+                                           const double *a2,
+                                           const double *b1,
+                                           const double *b2,
+                                           double *aRatio,
+                                           bool *aAligned)
 {
 /* Legacy intersection math aligns better with occlusion function quirks. */
 /* #define USE_VECTOR_LINE_INTERSECTION */
@@ -555,9 +562,20 @@ BLI_INLINE int lineart_LineIntersectTest2d(
   double x_diff = (a2[0] - a1[0]);
   double x_diff2 = (b2[0] - b1[0]);
 
+  *aAligned = false;
+
   if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff, 0)) {
     if (LRT_DOUBLE_CLOSE_ENOUGH(x_diff2, 0)) {
-      *aRatio = 0;
+      if ((LRT_DOUBLE_CLOSE_ENOUGH(a2[0], b1[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a2[1], b1[1])) ||
+          (LRT_DOUBLE_CLOSE_ENOUGH(a2[0], b2[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a2[1], b2[1]))) {
+        *aAligned = true;
+        *aRatio = 1;
+      }
+      else if ((LRT_DOUBLE_CLOSE_ENOUGH(a1[0], b1[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a1[1], b1[1])) ||
+               (LRT_DOUBLE_CLOSE_ENOUGH(a1[0], b2[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a1[1], b2[1]))) {
+        *aAligned = true;
+        *aRatio = 0;
+      }
       return 0;
     }
     double r2 = ratiod(b1[0], b2[0], a1[0]);
@@ -575,8 +593,21 @@ BLI_INLINE int lineart_LineIntersectTest2d(
       k1 = (a2[1] - a1[1]) / x_diff;
       k2 = (b2[1] - b1[1]) / x_diff2;
 
-      if (k1 == k2)
+      if (LRT_DOUBLE_CLOSE_ENOUGH(k2, k1)) {
+        if ((LRT_DOUBLE_CLOSE_ENOUGH(a2[0], b1[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a2[1], b1[1])) ||
+            (LRT_DOUBLE_CLOSE_ENOUGH(a2[0], b2[0]) && LRT_DOUBLE_CLOSE_ENOUGH(a2[1], b2[1]))) {
+          *aAligned = true;
+          *aRatio = 1;
+        }
+        else if ((LRT_DOUBLE_CLOSE_ENOUGH(a1[0], b1[0]) &&
+                  LRT_DOUBLE_CLOSE_ENOUGH(a1[1], b1[1])) ||
+                 (LRT_DOUBLE_CLOSE_ENOUGH(a1[0], b2[0]) &&
+                  LRT_DOUBLE_CLOSE_ENOUGH(a1[1], b2[1]))) {
+          *aAligned = true;
+          *aRatio = 0;
+        }
         return 0;
+      }
 
       x = (a1[1] - b1[1] - k1 * a1[0] + k2 * b1[0]) / (k2 - k1);
 
@@ -596,6 +627,13 @@ BLI_INLINE int lineart_LineIntersectTest2d(
            (b2[0] < b1[0] && x < b2[0]))
     return 0;
 
+  if (LRT_DOUBLE_CLOSE_ENOUGH_TRI(*aRatio, 1)) {
+    *aRatio = 1;
+  }
+  else if (LRT_DOUBLE_CLOSE_ENOUGH_TRI(*aRatio, 0)) {
+    *aRatio = 0;
+  }
+
   return 1;
 #endif
 }
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
index 6c66fcaabd0..20a50717485 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
@@ -640,6 +640,8 @@ void MOD_lineart_chain_split_for_fixed_occlusion(LineartRenderBuffer *rb)
       }
     }
   }
+  /* Get rid of those very short "zig-zag" lines that jumps around visibility. */
+  MOD_lineart_chain_discard_short(rb, DBL_EDGE_LIM);
   LISTBASE_FOREACH (LineartEdgeChain *, iec, &rb->chains) {
     lineart_bounding_area_link_chain(rb, iec);
   }
@@ -920,6 +922,9 @@ float MOD_lineart_chain_compute_length(LineartEdgeChain *ec)
   float last_point[2];
 
   eci = ec->chain.first;
+  if (!eci) {
+    return 0;
+  }
   copy_v2_v2(last_point, eci->pos);
   for (eci = ec->chain.first; eci; eci = eci->next) {
     dist = len_v2v2(eci->pos, last_point);
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index 31310b46b1c..b2a8881a98b 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -2426,7 +2426,7 @@ static bool lineart_edge_from_triangle(const LineartTriangle *tri,
   { \
     index = (num < is[order[0]] ? \
                  order[0] : \
-                 (num < is[order[1]] ? order[1] : (num < is[order[2]] ? order[2] : order[2]))); \
+                 (num < is[order[1]] ? order[1] : (num < is[order[2]] ? order[2] : -1))); \
   }
 
 /* `ia ib ic` are ordered. */
@@ -2434,7 +2434,7 @@ static bool lineart_edge_from_triangle(const LineartTriangle *tri,
   { \
     index = (num > is[order[2]] ? \
                  order[2] : \
-                 (num > is[order[1]] ? order[1] : (num > is[order[0]] ? order[0] : order[0]))); \
+                 (num > is[order[1]] ? order[1] : (num > is[order[0]] ? order[0] : -1))); \
   }
 
 /**
@@ -2459,7 +2459,8 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
   double is[3] = {0};
   int order[3];
   int LCross = -1, RCross = -1;
-  int a, b, c;
+  int a, b, c;     /* Crossing info. */
+  bool pa, pb, pc; /* Parallel info. */
   int st_l = 0, st_r = 0;
 
   double Lv[3];
@@ -2489,9 +2490,9 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
   }
 
   /* Check if the line visually crosses one of the edge in the triangle. */
-  a = lineart_LineIntersectTest2d(LFBC, RFBC, FBC0, FBC1, &is[0]);
-  b = lineart_LineIntersectTest2d(LFBC, RFBC, FBC1, FBC2, &is[1]);
-  c = lineart_LineIntersectTest2d(LFBC, RFBC, FBC2, FBC0, &is[2]);
+  a = lineart_LineIntersectTest2d(LFBC, RFBC, FBC0, FBC1, &is[0], &pa);
+  b = lineart_LineIntersectTest2d(LFBC, RFBC, FBC1, FBC2, &is[1], &pb);
+  c = lineart_LineIntersectTest2d(LFBC, RFBC, FBC2, FBC0, &is[2], &pc);
 
   /* Sort the intersection distance. */
   INTERSECT_SORT_MIN_TO_MAX_3(is[0], is[1], is[2], order);
@@ -2576,6 +2577,11 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
     cut = ratiod(e->v1->fbcoord[1], e->v2->fbcoord[1], trans[1]);
   }
 
+#define LRT_GUARD_NOT_FOUND \
+  if (LCross < 0 || RCross < 0) { \
+    return false; \
+  }
+
   /* Determine the pair of edges that the line has crossed. */
 
   if (st_l == 2) {
@@ -2603,12 +2609,18 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
     }
     else if (st_r == 0) {
       INTERSECT_JUST_GREATER(is, order, DBL_TRIANGLE_LIM, RCross);
-      if (LRT_ABC(RCross) && is[RCross] > (DBL_TRIANGLE_LIM)) {
+      if (RCross >= 0 && LRT_ABC(RCross) && is[RCross] > (DBL_TRIANGLE_LIM)) {
         INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, LCross);
       }
       else {
-        INTERSECT_JUST_SMALLER(is, order, -DBL_TRIANGLE_LIM, LCross);
-        INTERSECT_JUST_GREATER(is, order, -DBL_TRIANGLE_LIM, RCross);
+        INTERSECT_JUST_SMALLER(is, order, DBL_TRIANGLE_LIM, RCross);
+        if (RCross > 0) {
+          INTERSECT_JUST_SMALLER(is, order, is[RCross], LCross);
+        }
+      }
+      LRT_GUARD_NOT_FOUND
+      if ((LRT_PABC(LCross) && !LRT_ABC(LCross)) || (LRT_PABC(RCross) && !LRT_ABC(RCross))) {
+        return false;
       }
     }
   }
@@ -2619,17 +2631,23 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
     }
     else if (st_r == 1) {
       INTERSECT_JUST_SMALLER(is, order, 1 - DBL_TRIANGLE_LIM, LCross);
-      if (LRT_ABC(LCross) && is[LCross] < (1 - DBL_TRIANGLE_LIM)) {
+      if (LCross >= 0 && LRT_ABC(LCross) && is[LCross] < (1 - DBL_TRIANGLE_LIM)) {
         INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, RCross);
       }
       else {
-        INTERSECT_JUST_SMALLER(is, order, 1 + DBL_TRIANGLE_LIM, LCross);
-        INTERSECT_JUST_GREATER(is, order, 1 + DBL_TRIANGLE_LIM, RCross);
+        INTERSECT_JUST_GREATER(is, order, 1 - DBL_TRIANGLE_LIM, LCross);
+        if (LCross > 0) {
+          INTERSECT_JUST_GREATER(is, order, is[LCross], RCross);
+        }
+      }
+      LRT_GUARD_NOT_FOUND
+      if ((LRT_PABC(LCross) && !LRT_ABC(LCross)) || (LRT_PABC(RCross) && !LRT_ABC(RCross))) {
+        return false;
       }
     }
     else if (st_r == 0) {
-      INTERSECT_JUST_GREATER(is, order, DBL_TRIANGLE_LIM, LCross);
-      if (LRT_ABC(LCross) && is[LCross] > DBL_TRIANGLE_LIM) {
+      INTERSECT_JUST_GREATER(is, order, -DBL_TRIANGLE_LIM, LCross);
+      if (LCross >= 0 && LRT_ABC(LCross)) {
         INTERSECT_JUST_GREATER(is, order, is[LCross], RCross);
       }
       else {
@@ -2639,6 +2657,8 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *UNUSED(spl),
     }
   }
 
+  LRT_GUARD_NOT_FOUND
+
   double LF = dot_l * dot_f, RF = dot_r * dot_f;
 
   /* Determine the start and end point of image space cut on a line. */
@@ -4082,25 +4102,26 @@ static LineartBoundingArea *lineart_edge_first_bounding_area(LineartRenderBuffer
   double data[2] = {e->v1->fbcoord[0], e->v1->fbcoord[1]};
   double LU[2] = {-1, 1}, RU[2] = {1, 1}, LB[2] = {-1, -1}, RB[2] = {1, -1};
   double r = 1, sr = 1;
+  bool p_unused;
 
   if (data[0] > -1 && data[0] < 1 && data[1] > -1 && data[1] < 1) {
     return lineart_get_bounding_area(rb, data[0], data[1]);
   }
 
-  if (lineart_LineIntersectTest2d(e->v1->fbcoord, e->v2->fbcoord, LU, RU, &sr) && sr < r &&
-      sr > 0) {
+  if (lineart_LineIntersectTest2d(e->v1->fbcoord, e->v2->fbcoord, LU, RU, &sr, &p_unused) &&
+      sr < r && sr > 0) {
     r = sr;
   }
-  if (lineart_LineIntersectTest2d(e->v1->fbcoord, e->v2->fbcoord, LB, RB, &sr) && sr < r &&
-      sr > 0) {
+  if (linea

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list