Commit: 4ca90c7a990cdaa0e0655533e0f988d520d35880 Author: Antonioya Date: Thu Dec 28 19:45:48 2017 +0100 Branches: greasepencil-object https://developer.blender.org/rB4ca90c7a990cdaa0e0655533e0f988d520d35880
WIP: Create stroke for fill First step to create strokes =================================================================== M source/blender/editors/gpencil/gpencil_fill.c M source/blender/editors/include/ED_gpencil.h =================================================================== diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index ee77397f5d1..65dd16c108d 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -64,6 +64,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "gpencil_intern.h" + /* draw a given stroke using same thickness and color for all points */ static void gp_draw_basic_stroke(const bGPDspoint *points, int totpoints, const float diff_mat[4][4], bool cyclic, float ink[4]) @@ -347,8 +349,40 @@ static void gpencil_boundaryfill_area(tGPDfill *tgpf) BLI_stack_free(stack); } +/* clean external border of image to avoid infinite loops */ +static void gpencil_clean_borders(tGPDfill *tgpf) +{ + ImBuf *ibuf; + void *lock; + const float fill_col[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock); + int idx; + + /* horizontal lines */ + for (idx = 0; idx < ibuf->x; idx++) { + /* bottom line */ + set_pixel(ibuf, idx, fill_col); + /* top line */ + set_pixel(ibuf, idx + (ibuf->x * (ibuf->y - 1)), fill_col); + } + /* vertical lines */ + for (idx = 0; idx < ibuf->y; idx++) { + /* left line */ + set_pixel(ibuf, ibuf->x * idx, fill_col); + /* right line */ + set_pixel(ibuf, ibuf->x * idx + (ibuf->x - 1), fill_col); + } + + /* release ibuf */ + if (ibuf) { + BKE_image_release_ibuf(tgpf->ima, ibuf, lock); + } + + tgpf->ima->id.tag |= LIB_TAG_DOIT; +} + /* helper to copy points 2D */ -MINLINE void copyint_v2_v2(int r[2], const int a[2]) +static void copyint_v2_v2(int r[2], const int a[2]) { r[0] = a[0]; r[1] = a[1]; @@ -359,7 +393,7 @@ MINLINE void copyint_v2_v2(int r[2], const int a[2]) * This is a Blender customized version of the general algorithm described * in https://en.wikipedia.org/wiki/Moore_neighborhood */ -static void gpencil_get_outline_points(tGPDfill *tgpf) +static void gpencil_get_outline_points(tGPDfill *tgpf) { ImBuf *ibuf; float rgba[4]; @@ -386,7 +420,7 @@ static void gpencil_get_outline_points(tGPDfill *tgpf) { -1, 0 } }; - BLI_Stack *stack = BLI_stack_new(sizeof(int[2]), __func__); + tgpf->stack = BLI_stack_new(sizeof(int[2]), __func__); ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock); int imagesize = ibuf->x * ibuf->y; @@ -404,7 +438,7 @@ static void gpencil_get_outline_points(tGPDfill *tgpf) backtracked_offset[0][1] = backtracked_co[1] - boundary_co[1]; copyint_v2_v2(prev_check_co, start_co); - BLI_stack_push(stack, &boundary_co); + BLI_stack_push(tgpf->stack, &boundary_co); start_found = true; break; } @@ -439,7 +473,7 @@ static void gpencil_get_outline_points(tGPDfill *tgpf) backtracked_offset[0][0] = backtracked_co[0] - boundary_co[0]; backtracked_offset[0][1] = backtracked_co[1] - boundary_co[1]; - BLI_stack_push(stack, &boundary_co); + BLI_stack_push(tgpf->stack, &boundary_co); break; } @@ -451,7 +485,7 @@ static void gpencil_get_outline_points(tGPDfill *tgpf) if (boundary_co[0] == start_co[0] && boundary_co[1] == start_co[1]) { - BLI_stack_pop(stack, &v); + BLI_stack_pop(tgpf->stack, &v); boundary_found = true; break; } @@ -462,18 +496,111 @@ static void gpencil_get_outline_points(tGPDfill *tgpf) BKE_image_release_ibuf(tgpf->ima, ibuf, lock); } - /* debug code */ +#if 0 /* debug code (paint in blue outline in debug image) */ const float outline_col[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; - while (!BLI_stack_is_empty(stack)) { - BLI_stack_pop(stack, &v); - printf("(%d, %d)\n", v[0], v[1]); + while (!BLI_stack_is_empty(tgpf->stack)) { + BLI_stack_pop(tgpf->stack, &v); int idx = ibuf->x * v[1] + v[0]; set_pixel(ibuf, idx, outline_col); } +#endif - /* free temp stack data*/ - BLI_stack_free(stack); } + +/* create a grease pencil stroke using points in stack */ +static void gpencil_stroke_from_stack(tGPDfill *tgpf) +{ + Scene *scene = tgpf->scene; + ToolSettings *ts = tgpf->scene->toolsettings; + bGPDspoint *pt; + tGPspoint point2D; + float r_out[3]; + int totpoints = BLI_stack_count(tgpf->stack); + if (totpoints == 0) { + return; + } + + /* get frame or create a new one */ + tgpf->gpf = BKE_gpencil_layer_getframe(tgpf->gpl, CFRA, GP_GETFRAME_ADD_NEW); + + /* create new stroke */ + bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke"); + gps->thickness = 1.0f; + gps->inittime = 0.0f; + + /* the polygon must be closed, so enabled cyclic */ + gps->flag |= GP_STROKE_CYCLIC; + gps->flag |= GP_STROKE_3DSPACE; + + gps->palette = tgpf->palette; + gps->palcolor = tgpf->palcolor; + + /* allocate memory for storage points */ + gps->totpoints = totpoints; + gps->points = MEM_callocN(sizeof(bGPDspoint) * totpoints, "gp_stroke_points"); + + /* initialize triangle memory to dummy data */ + gps->tot_triangles = 0; + gps->triangles = NULL; + gps->flag |= GP_STROKE_RECALC_CACHES; + + /* add to strokes to head to be on back */ + BLI_addhead(&tgpf->gpf->strokes, gps); + + /* add points */ + pt = gps->points; + int i = 0; + while (!BLI_stack_is_empty(tgpf->stack)) { + int v[2]; + BLI_stack_pop(tgpf->stack, &v); + point2D.x = v[0]; + point2D.y = v[1]; + + /* convert screen-coordinates to 3D coordinates */ + gp_stroke_convertcoords_tpoint(tgpf->scene, tgpf->ar, tgpf->v3d, &point2D, r_out); + copy_v3_v3(&pt->x, r_out); + /* if parented change position relative to parent object */ + gp_apply_parent_point(tgpf->ob, tgpf->gpd, tgpf->gpl, pt); + + pt->pressure = 1.0f; + pt->strength = 1.0f;; + pt->time = 0.0f; + pt->totweight = 0; + pt->weights = NULL; + + pt++; + } + +#if 0 + /* smooth stroke */ + float reduce = 0.0f; + float smoothfac = 1.0f; + for (int r = 0; r < 1; ++r) { + for (i = 0; i < gps->totpoints; i++) { + BKE_gp_smooth_stroke(gps, i, smoothfac - reduce, false); + } + reduce += 0.25f; // reduce the factor + } + + /* simplify stroke using Ramer-Douglas-Peucker algorithm */ + BKE_gpencil_simplify_stroke(tgpf->gpl, gps, 1.0f); +#endif + + /* if axis locked, reproject to plane locked */ + if (tgpf->lock_axis > GP_LOCKAXIS_NONE) { + float origin[3]; + bGPDspoint *tpt = gps->points; + ED_gp_get_drawing_reference(tgpf->v3d, tgpf->scene, tgpf->ob, tgpf->gpl, + ts->gpencil_v3d_align, origin); + + for (int i = 0; i < gps->totpoints; i++, tpt++) { + ED_gp_project_point_to_plane(tgpf->ob, tgpf->rv3d, origin, + ts->gp_sculpt.lock_axis - 1, + ts->gpencil_src, tpt); + } + } +} + /* ----------------------- */ /* Drawing Callbacks */ @@ -538,6 +665,7 @@ static tGPDfill *gp_session_init_fill(bContext *C, wmOperator *op) /* set GP datablock */ tgpf->gpd = gpd; + tgpf->gpl = BKE_gpencil_layer_getactive(gpd); /* get palette and color info */ bGPDpaletteref *palslot = BKE_gpencil_paletteslot_validate(bmain, gpd); @@ -676,11 +804,25 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) /* apply boundary fill */ gpencil_boundaryfill_area(tgpf); + /* clean borders to avoid infinite loops */ + gpencil_clean_borders(tgpf); + /* analyze outline */ gpencil_get_outline_points(tgpf); + + /* create stroke and reproject */ + gpencil_stroke_from_stack(tgpf); + + /* delete temp image */ + if (tgpf->ima) { + BKE_image_free(tgpf->ima); + } + + /* free temp stack data */ + if (tgpf->stack) { + BLI_stack_free(tgpf->stack); + } - /* TODO: create stroke and reproject */ - /* TODO: delete temp image */ estate = OPERATOR_FINISHED; } else { diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 6d245dac0da..79a1290fd9c 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -45,6 +45,7 @@ struct bGPDpalettecolor; struct bGPDspoint; struct ID; struct Image; +struct BLI_Stack; struct KeyframeEditData; struct ListBase; struct Object; @@ -144,7 +145,8 @@ typedef struct tGPDfill { int sizey; /* window height */ int lock_axis; /* lock to viewport axis */ - Image *ima; /* temp image */ + struct Image *ima; /* temp image */ + struct BLI_Stack *stack; /* temp points data */ void *draw_handle_3d; /* handle for drawing strokes while operator is running 3d stuff */ } tGPDfill; _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs