[Bf-blender-cvs] [392855ce502] master: GPencil: Improve Fill Tool Extend lines

Antonio Vazquez noreply at git.blender.org
Fri Sep 23 19:29:05 CEST 2022


Commit: 392855ce5022ccfeaa52efc04b13a7208ed0dc3f
Author: Antonio Vazquez
Date:   Fri Sep 23 18:49:54 2022 +0200
Branches: master
https://developer.blender.org/rB392855ce5022ccfeaa52efc04b13a7208ed0dc3f

GPencil: Improve Fill Tool Extend lines

* Improve how the extend lines collision is calculated.
* Added `S` key to switch between modes.
*  Now extend factor does not disable visual aids (thi sis done with checkbox).
* Reduce the use of linked list and now memory array is used.
* Refactor Radius functions.
* Fixed bug of Radius mode when object is rotated.
* Cleanup code.

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

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

M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/editors/gpencil/gpencil_fill.c
M	source/blender/makesdna/DNA_brush_enums.h
M	source/blender/makesrna/intern/rna_brush.c

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

diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index ecc72e1bbb8..95185c2a2f5 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1889,10 +1889,8 @@ class VIEW3D_PT_tools_grease_pencil_brush_gap_closure(View3DPanel, Panel):
 
         col.prop(gp_settings, "extend_stroke_factor", text="Size")
         row = col.row(align=True)
-        row.enabled = gp_settings.extend_stroke_factor > 0
         row.prop(gp_settings, "fill_extend_mode", text="Mode")
         row = col.row(align=True)
-        row.enabled = gp_settings.extend_stroke_factor > 0
         row.prop(gp_settings, "show_fill_extend", text="Visual Aids")
 
 
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 775c17e1c98..c173a30a736 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -79,6 +79,20 @@ enum {
   GP_DRAWFILLS_ONLY3D = (1 << 1),   /* only draw 3d-strokes */
 };
 
+/* Temporary stroke data including stroke extensions. */
+typedef struct tStroke {
+  /* Referenced layer. */
+  bGPDlayer *gpl;
+  /** Referenced frame. */
+  bGPDframe *gpf;
+  /** Referenced stroke. */
+  bGPDstroke *gps;
+  /** Extreme Stroke A. */
+  bGPDstroke *gps_ext_a;
+  /** Extreme Stroke B. */
+  bGPDstroke *gps_ext_b;
+} tStroke;
+
 /* Temporary fill operation data `op->customdata`. */
 typedef struct tGPDfill {
   bContext *C;
@@ -115,7 +129,7 @@ typedef struct tGPDfill {
   /** For operations that require occlusion testing. */
   struct ViewDepths *depths;
   /** flags */
-  short flag;
+  int flag;
   /** avoid too fast events */
   short oldkey;
   /** send to back stroke */
@@ -160,7 +174,7 @@ typedef struct tGPDfill {
   Image *ima;
   /** temp points data */
   BLI_Stack *stack;
-  /** handle for drawing strokes while operator is running 3d stuff */
+  /** handle for drawing strokes while operator is running 3d stuff. */
   void *draw_handle_3d;
 
   /* Temporary size x. */
@@ -177,12 +191,28 @@ typedef struct tGPDfill {
 
   /** Factor of extension. */
   float fill_extend_fac;
-
+  /** Size of stroke_array. */
+  int stroke_array_num;
+  /** Temp strokes array to handle strokes and stroke extensions. */
+  tStroke **stroke_array;
 } tGPDfill;
 
 bool skip_layer_check(short fill_layer_mode, int gpl_active_index, int gpl_index);
 static void gpencil_draw_boundary_lines(const struct bContext *UNUSED(C), struct tGPDfill *tgpf);
 
+/* Free temp stroke array. */
+static void stroke_array_free(tGPDfill *tgpf)
+{
+  if (tgpf->stroke_array) {
+    for (int i = 0; i < tgpf->stroke_array_num; i++) {
+      tStroke *stroke = tgpf->stroke_array[i];
+      MEM_freeN(stroke);
+    }
+    MEM_SAFE_FREE(tgpf->stroke_array);
+  }
+  tgpf->stroke_array_num = 0;
+}
+
 /* Delete any temporary stroke. */
 static void gpencil_delete_temp_stroke_extension(tGPDfill *tgpf, const bool all_frames)
 {
@@ -243,7 +273,8 @@ static void add_stroke_extension(bGPDframe *gpf, bGPDstroke *gps, float p1[3], f
   pt->pressure = 1.0f;
 }
 
-static void add_endpoint_radius_help(bGPDframe *gpf,
+static void add_endpoint_radius_help(tGPDfill *tgpf,
+                                     bGPDframe *gpf,
                                      bGPDstroke *gps,
                                      const float endpoint[3],
                                      const float radius,
@@ -268,6 +299,11 @@ static void add_endpoint_radius_help(bGPDframe *gpf,
     pt->z = endpoint[2] + radius * sinf(angle);
     pt->strength = 1.0f;
     pt->pressure = 1.0f;
+
+    /* Rotate to object rotation. */
+    sub_v3_v3(&pt->x, endpoint);
+    mul_mat3_m4_v3(tgpf->ob->obmat, &pt->x);
+    add_v3_v3(&pt->x, endpoint);
   }
 }
 
@@ -283,13 +319,20 @@ static void extrapolate_points_by_length(bGPDspoint *a,
   add_v3_v3v3(r_point, &b->x, ab);
 }
 
-/* Cut the extended lines if collide. */
-static void gpencil_cut_extensions(tGPDfill *tgpf, const int gpl_active_index)
+/* Calculate the size of the array for strokes. */
+static void gpencil_strokes_array_size(tGPDfill *tgpf)
 {
   bGPdata *gpd = tgpf->gpd;
   Brush *brush = tgpf->brush;
   BrushGpencilSettings *brush_settings = brush->gpencil_settings;
 
+  bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
+  BLI_assert(gpl_active != NULL);
+
+  const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active);
+  BLI_assert(gpl_active_index >= 0);
+
+  tgpf->stroke_array_num = 0;
   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
     if (gpl->flag & GP_LAYER_HIDE) {
       continue;
@@ -306,78 +349,12 @@ static void gpencil_cut_extensions(tGPDfill *tgpf, const int gpl_active_index)
     if (gpf == NULL) {
       continue;
     }
-    int size = BLI_listbase_count(&gpf->strokes);
-    if (size == 0) {
-      continue;
-    }
-
-    float diff_mat[4][4];
-    BKE_gpencil_layer_transform_matrix_get(tgpf->depsgraph, tgpf->ob, gpl, diff_mat);
-    /* Save all extend strokes in array.*/
-    int tot_idx = 0;
-    bGPDstroke **gps_array = MEM_callocN(sizeof(bGPDstroke *) * size, __func__);
-
-    LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
-      if ((gps->flag & (GP_STROKE_NOFILL | GP_STROKE_TAG)) == 0) {
-        continue;
-      }
-      gps_array[tot_idx] = gps;
-      tot_idx++;
-    }
-
-    /* Compare all strokes. */
-    for (int i = 0; i < tot_idx; i++) {
-      bGPDstroke *gps_a = gps_array[i];
-
-      bGPDspoint pt2;
-      float a1xy[2], a2xy[2];
-      float b1xy[2], b2xy[2];
-
-      /* First stroke. */
-      bGPDspoint *pt = &gps_a->points[0];
-      gpencil_point_to_parent_space(pt, diff_mat, &pt2);
-      gpencil_point_to_xy_fl(&tgpf->gsc, gps_a, &pt2, &a1xy[0], &a1xy[1]);
-
-      pt = &gps_a->points[1];
-      gpencil_point_to_parent_space(pt, diff_mat, &pt2);
-      gpencil_point_to_xy_fl(&tgpf->gsc, gps_a, &pt2, &a2xy[0], &a2xy[1]);
-      bGPDspoint *extreme_a = &gps_a->points[1];
-
-      /* Loop all strokes. */
-      for (int z = 0; z < tot_idx; z++) {
-        bGPDstroke *gps_b = gps_array[z];
-        if (i == z) {
-          continue;
-        }
-        pt = &gps_b->points[0];
-        gpencil_point_to_parent_space(pt, diff_mat, &pt2);
-        gpencil_point_to_xy_fl(&tgpf->gsc, gps_b, &pt2, &b1xy[0], &b1xy[1]);
-
-        pt = &gps_b->points[1];
-        gpencil_point_to_parent_space(pt, diff_mat, &pt2);
-        gpencil_point_to_xy_fl(&tgpf->gsc, gps_b, &pt2, &b2xy[0], &b2xy[1]);
-        bGPDspoint *extreme_b = &gps_b->points[1];
-
-        /* Check if extensions collide and cut the overlength. */
-        if (isect_seg_seg_v2_simple(a1xy, a2xy, b1xy, b2xy)) {
-          float intersection[2];
-          isect_line_line_v2_point(a1xy, a2xy, b1xy, b2xy, intersection);
-          float intersection3D[3];
-          gpencil_point_xy_to_3d(&tgpf->gsc, tgpf->scene, intersection, intersection3D);
-          copy_v3_v3(&extreme_a->x, intersection3D);
-          copy_v3_v3(&extreme_b->x, intersection3D);
-          gps_a->flag |= GP_STROKE_COLLIDE;
-          gps_b->flag |= GP_STROKE_COLLIDE;
-        }
-      }
-    }
-
-    MEM_SAFE_FREE(gps_array);
+    tgpf->stroke_array_num += BLI_listbase_count(&gpf->strokes);
   }
 }
 
-/* Loop all layers create stroke extensions. */
-static void gpencil_create_extensions(tGPDfill *tgpf)
+/* Load all strokes to be procesed by extend lines. */
+static void gpencil_load_array_strokes(tGPDfill *tgpf)
 {
   Object *ob = tgpf->ob;
   bGPdata *gpd = tgpf->gpd;
@@ -390,9 +367,14 @@ static void gpencil_create_extensions(tGPDfill *tgpf)
   const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active);
   BLI_assert(gpl_active_index >= 0);
 
-  float connection_dist = tgpf->fill_extend_fac * 0.1f;
-  GSet *connected_endpoints = BLI_gset_ptr_new(__func__);
+  /* Create array of strokes. */
+  gpencil_strokes_array_size(tgpf);
+  if (tgpf->stroke_array_num == 0) {
+    return;
+  }
 
+  tgpf->stroke_array = MEM_callocN(sizeof(tStroke *) * tgpf->stroke_array_num, __func__);
+  int idx = 0;
   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
     if (gpl->flag & GP_LAYER_HIDE) {
       continue;
@@ -415,180 +397,379 @@ static void gpencil_create_extensions(tGPDfill *tgpf)
       if ((gps->points == NULL) || (gps->totpoints < 2)) {
         continue;
       }
-      if (gps->flag & (GP_STROKE_NOFILL | GP_STROKE_TAG)) {
-        continue;
-      }
       /* Check if the color is visible. */
       MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
       if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE)) {
         continue;
       }
-
-      /* Find points of high curvature. */
-      float tan1[3];
-      float tan2[3];
-      float d1;
-      float d2;
-      float total_length = 0.0f;
-      for (int i = 1; i < gps->totpoints; i++) {
-        if (i > 1) {
-          copy_v3_v3(tan1, tan2);
-          d1 = d2;
-        }
-        bGPDspoint *pt1 = &gps->points[i - 1];
-        bGPDspoint *pt2 = &gps->points[i];
-        sub_v3_v3v3(tan2, &pt2->x, &pt1->x);
-        d2 = normalize_v3(tan2);
-        total_length += d2;
-        if (i > 1) {
-          if (tgpf->fill_extend_mode == GP_FILL_EMODE_RADIUS) {
-            continue;
-          }
-          float curvature[3];
-          sub_v3_v3v3(curvature, tan2, tan1);
-          float k = normalize_v3(curvature);
-          k /= min_ff(d1, d2);
-          float radius = 1.0f / k;
-          /*
-           * The smaller the radius of curvature, the sharper the corner.
-           * The thicker the line, the larger the radius of curvature it
-           * takes to be visually indistinguishable from an endpoint.
-           */
-          float min_radius = gps->thickness * 0.0001f;
-
-          if (radius < min_radius) {
-            /* Extend along direction of curvature. */
-            bGPDstroke *gps_new = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness);
-            gps_new->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG;
-            BLI_addtail(&gpf->strokes, gps_new);
-
-            bGPDspoint *pt = &gps_new->points[0];
-            copy_v3_v3(&pt->x, &pt1->

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list