[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