[Bf-blender-cvs] [7c9b6cc3802] master: LineArt: Better behavior of smooth tolerance.

YimingWu noreply at git.blender.org
Fri May 13 18:56:54 CEST 2022


Commit: 7c9b6cc3802982bfb7a13aed37d4a032d9166fbc
Author: YimingWu
Date:   Sat May 14 00:55:18 2022 +0800
Branches: master
https://developer.blender.org/rB7c9b6cc3802982bfb7a13aed37d4a032d9166fbc

LineArt: Better behavior of smooth tolerance.

This fixes the smooth tolerance feature in master where sometimes you could
get over simplified chains and lose the shape it's supposed to be originally.

Reviewed By: Sebastian Parborg (zeddb)

Differential Revision: https://developer.blender.org/D14929

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

M	source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c

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

diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
index b666eb677eb..d7b370ef5e5 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_chain.c
@@ -971,27 +971,67 @@ void MOD_lineart_chain_clear_picked_flag(LineartCache *lc)
 void MOD_lineart_smooth_chains(LineartRenderBuffer *rb, float tolerance)
 {
   LISTBASE_FOREACH (LineartEdgeChain *, ec, &rb->chains) {
-    LineartEdgeChainItem *next_eci;
-    for (LineartEdgeChainItem *eci = ec->chain.first; eci; eci = next_eci) {
-      next_eci = eci->next;
-      LineartEdgeChainItem *eci2, *eci3, *eci4;
-
-      /* Not enough point to do simplify. */
-      if ((!(eci2 = eci->next)) || (!(eci3 = eci2->next))) {
-        continue;
-      }
-
-      /* No need to care for different line types/occlusion and so on, because at this stage they
-       * are all the same within a chain. */
-
-      /* If p3 is within the p1-p2 segment of a width of "tolerance". */
-      if (dist_to_line_segment_v2(eci3->pos, eci->pos, eci2->pos) < tolerance) {
-        /* And if p4 is on the extension of p1-p2 , we remove p3. */
-        if ((eci4 = eci3->next) && (dist_to_line_v2(eci4->pos, eci->pos, eci2->pos) < tolerance)) {
-          BLI_remlink(&ec->chain, eci3);
-          next_eci = eci;
+    /* Go through the chain two times, once from each direction. */
+    for (int times = 0; times < 2; times++) {
+      for (LineartEdgeChainItem *eci = ec->chain.first, *next_eci = eci->next; eci;
+           eci = next_eci) {
+        LineartEdgeChainItem *eci2, *eci3, *eci4;
+
+        if ((!(eci2 = eci->next)) || (!(eci3 = eci2->next))) {
+          /* Not enough points to simplify. */
+          next_eci = eci->next;
+          continue;
         }
+        /* No need to care for different line types/occlusion and so on, because at this stage they
+         * are all the same within a chain.
+         *
+         * We need to simplify a chain from this:
+         * 1-----------2
+         *        3-----------4
+         * to this:
+         * 1-----------2--_
+         *                 `--4 */
+
+        /* If p3 is within the p1-p2 segment of a width of "tolerance", in other words, p3 is
+         * approximately on the segment of p1-p2. */
+        if (dist_to_line_segment_v2(eci3->pos, eci->pos, eci2->pos) < tolerance) {
+          float vec2[2], vec3[2], v2n[2], ratio, len2;
+          sub_v2_v2v2(vec2, eci2->pos, eci->pos);
+          sub_v2_v2v2(vec3, eci3->pos, eci->pos);
+          normalize_v2_v2(v2n, vec2);
+          ratio = dot_v2v2(v2n, vec3);
+          len2 = len_v2(vec2);
+          /* Because this smoothing applies on geometries of different scales in the same scene,
+           * some small scale features (e.g. the "tails" on the inner ring of a torus geometry)
+           * could be completely erased if the tolerance value is set for accomondating the entire
+           * scene. Those situations typically result in (ratio << 0), looks like this:
+           *                         1---2
+           * 3-------------------------------4
+           * (this sort of long zig zag obviously are "features" that can't be erased)
+           * setting a ratio of -10 turned out to be a reasonabe threshold in tests. */
+          if (ratio < len2 && ratio > -len2 * 10) {
+            /* We only remove p3 if p4 is on the extension of p1->p2. */
+            if ((eci4 = eci3->next) &&
+                (dist_to_line_v2(eci4->pos, eci->pos, eci2->pos) < tolerance)) {
+              BLI_remlink(&ec->chain, eci3);
+              next_eci = eci;
+              continue;
+            }
+            if (!eci4) {
+              /* See if the last segment's direction is reversed, if so remove that.
+               * Basically we don't need to preserve p3 if the entire chain looked like this:
+               * ...----1----3===2 */
+              if (len_v2(vec2) > len_v2(vec3)) {
+                BLI_remlink(&ec->chain, eci3);
+              }
+              next_eci = NULL;
+              continue;
+            }
+          }
+        }
+        next_eci = eci->next;
       }
+      BLI_listbase_reverse(&ec->chain);
     }
   }
 }



More information about the Bf-blender-cvs mailing list