[Bf-blender-cvs] [4ca90c7a990] greasepencil-object: WIP: Create stroke for fill

Antonioya noreply at git.blender.org
Thu Dec 28 19:46:18 CET 2017


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;



More information about the Bf-blender-cvs mailing list