[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [60551] trunk/blender/source/blender: fix for lasso failing/glitches on overlapping lines, replace scanfill with 2d pixel filling for drawing and selection.

Campbell Barton ideasman42 at gmail.com
Fri Oct 4 17:02:05 CEST 2013


Revision: 60551
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=60551
Author:   campbellbarton
Date:     2013-10-04 15:02:05 +0000 (Fri, 04 Oct 2013)
Log Message:
-----------
fix for lasso failing/glitches on overlapping lines, replace scanfill with 2d pixel filling for drawing and selection.

Modified Paths:
--------------
    trunk/blender/source/blender/blenlib/BLI_math_geom.h
    trunk/blender/source/blender/blenlib/intern/math_geom.c
    trunk/blender/source/blender/editors/mesh/editmesh_select.c
    trunk/blender/source/blender/windowmanager/intern/wm_gesture.c
    trunk/blender/source/blender/windowmanager/intern/wm_subwindow.c
    trunk/blender/source/blender/windowmanager/wm_subwindow.h

Modified: trunk/blender/source/blender/blenlib/BLI_math_geom.h
===================================================================
--- trunk/blender/source/blender/blenlib/BLI_math_geom.h	2013-10-04 14:47:37 UTC (rev 60550)
+++ trunk/blender/source/blender/blenlib/BLI_math_geom.h	2013-10-04 15:02:05 UTC (rev 60551)
@@ -188,7 +188,10 @@
 bool clip_segment_v3_plane_n(float p1[3], float p2[3], float plane_array[][4], const int plane_tot);
 
 void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int, void *), void *userData);
-
+void fill_poly_v2i_n(
+        const int xmin, const int ymin, const int xmax, const int ymax,
+        const int polyXY[][2], const int polyCorners,
+        void (*callback)(int, int, void *), void *userData);
 /****************************** Interpolation ********************************/
 
 /* tri or quad, d can be NULL */

Modified: trunk/blender/source/blender/blenlib/intern/math_geom.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/math_geom.c	2013-10-04 14:47:37 UTC (rev 60550)
+++ trunk/blender/source/blender/blenlib/intern/math_geom.c	2013-10-04 15:02:05 UTC (rev 60551)
@@ -1997,6 +1997,59 @@
 	}
 }
 
+void fill_poly_v2i_n(
+        const int xmin, const int ymin, const int xmax, const int ymax,
+        const int verts[][2], const int nr,
+        void (*callback)(int, int, void *), void *userData)
+{
+	/* originally by Darel Rex Finley, 2007 */
+
+	int  nodes, pixel_y, i, j, swap;
+	int *node_x = MEM_mallocN(sizeof(*node_x) * (nr + 1), __func__);
+
+	/* Loop through the rows of the image. */
+	for (pixel_y = ymin; pixel_y < ymax; pixel_y++) {
+
+		/* Build a list of nodes. */
+		nodes = 0; j = nr - 1;
+		for (i=0; i<nr; i++) {
+			if ((verts[i][1] < pixel_y && verts[j][1] >= pixel_y) ||
+			    (verts[j][1] < pixel_y && verts[i][1] >= pixel_y))
+			{
+				node_x[nodes++] = (int)(verts[i][0] +
+				                        ((double)(pixel_y - verts[i][1]) / (verts[j][1] - verts[i][1])) *
+				                        (verts[j][0] - verts[i][0]));
+			}
+			j = i;
+		}
+
+		/* Sort the nodes, via a simple "Bubble" sort. */
+		i = 0;
+		while (i < nodes - 1) {
+			if (node_x[i] > node_x[i + 1]) {
+				SWAP_TVAL(swap, node_x[i], node_x[i + 1]);
+				if (i) i--;
+			}
+			else {
+				i++;
+			}
+		}
+
+		/* Fill the pixels between node pairs. */
+		for (i = 0; i < nodes; i += 2) {
+			if (node_x[i] >= xmax) break;
+			if (node_x[i + 1] >  xmin) {
+				if (node_x[i    ] < xmin) node_x[i    ] = xmin;
+				if (node_x[i + 1] > xmax) node_x[i + 1] = xmax;
+				for (j = node_x[i]; j < node_x[i + 1]; j++) {
+					callback(j - xmin, pixel_y - ymin, userData);
+				}
+			}
+		}
+	}
+	MEM_freeN(node_x);
+}
+
 /****************************** Axis Utils ********************************/
 
 /**

Modified: trunk/blender/source/blender/editors/mesh/editmesh_select.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editmesh_select.c	2013-10-04 14:47:37 UTC (rev 60550)
+++ trunk/blender/source/blender/editors/mesh/editmesh_select.c	2013-10-04 15:02:05 UTC (rev 60551)
@@ -186,53 +186,6 @@
 /* facilities for border select and circle select */
 static char *selbuf = NULL;
 
-/* opengl doesn't support concave... */
-static void draw_triangulated(const int mcords[][2], const short tot)
-{
-	ListBase lb = {NULL, NULL};
-	DispList *dl;
-	float *fp;
-	int a;
-	const float z_up[3] = {0.0f, 0.0f, 1.0f};
-	
-	/* make displist */
-	dl = MEM_callocN(sizeof(DispList), "poly disp");
-	dl->type = DL_POLY;
-	dl->parts = 1;
-	dl->nr = tot;
-	dl->verts = fp = MEM_callocN(tot * 3 * sizeof(float), "poly verts");
-	BLI_addtail(&lb, dl);
-	
-	for (a = 0; a < tot; a++, fp += 3) {
-		fp[0] = (float)mcords[a][0];
-		fp[1] = (float)mcords[a][1];
-	}
-	
-	/* do the fill */
-	BKE_displist_fill(&lb, &lb, z_up, false);
-
-	/* do the draw */
-	dl = lb.first;  /* filldisplist adds in head of list */
-	if (dl->type == DL_INDEX3) {
-		int *index;
-		
-		a = dl->parts;
-		fp = dl->verts;
-		index = dl->index;
-		glBegin(GL_TRIANGLES);
-		while (a--) {
-			glVertex3fv(fp + 3 * index[0]);
-			glVertex3fv(fp + 3 * index[1]);
-			glVertex3fv(fp + 3 * index[2]);
-			index += 3;
-		}
-		glEnd();
-	}
-	
-	BKE_displist_free(&lb);
-}
-
-
 /* reads rect, and builds selection array for quick lookup */
 /* returns if all is OK */
 bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
@@ -282,6 +235,18 @@
 	selbuf = NULL;
 }
 
+struct LassoMaskData {
+	unsigned int *px;
+	int width;
+};
+
+static void edbm_mask_lasso_px_cb(int x, int y, void *user_data)
+{
+	struct LassoMaskData *data = user_data;
+	data->px[(y * data->width) + x] = true;
+}
+
+
 /* mcords is a polygon mask
  * - grab backbuffer,
  * - draw with black in backbuffer, 
@@ -290,9 +255,10 @@
  */
 bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
 {
-	unsigned int *dr, *drm;
-	struct ImBuf *buf, *bufmask;
+	unsigned int *dr, *dr_mask, *dr_mask_arr;
+	struct ImBuf *buf;
 	int a;
+	struct LassoMaskData lasso_mask_data;
 	
 	/* method in use for face selecting too */
 	if (vc->obedit == NULL) {
@@ -310,49 +276,25 @@
 
 	dr = buf->rect;
 
-	if (vc->rv3d->gpuoffscreen)
-		GPU_offscreen_bind(vc->rv3d->gpuoffscreen);
-	
-	/* draw the mask */
-	glDisable(GL_DEPTH_TEST);
-	
-	glColor3ub(0, 0, 0);
-	
-	/* yah, opengl doesn't do concave... tsk! */
-	ED_region_pixelspace(vc->ar);
-	draw_triangulated(mcords, tot);
-	
-	glBegin(GL_LINE_LOOP);  /* for zero sized masks, lines */
-	for (a = 0; a < tot; a++) {
-		glVertex2iv(mcords[a]);
-	}
-	glEnd();
-	
-	glFinish(); /* to be sure readpixels sees mask */
-	
-	if (vc->rv3d->gpuoffscreen)
-		GPU_offscreen_unbind(vc->rv3d->gpuoffscreen);
-	
-	/* grab mask */
-	bufmask = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax);
+	dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf->x * buf->y, __func__);
+	lasso_mask_data.px = dr_mask;
+	lasso_mask_data.width = (xmax - xmin) + 1;
 
-	if (bufmask == NULL) {
-		return false;  /* only when mem alloc fails, go crash somewhere else! */
-	}
-	else {
-		drm = bufmask->rect;
-	}
+	fill_poly_v2i_n(
+	       xmin, ymin, xmax + 1, ymax + 1,
+	       mcords, tot,
+	       edbm_mask_lasso_px_cb, &lasso_mask_data);
 
 	/* build selection lookup */
 	selbuf = MEM_callocN(bm_vertoffs + 1, "selbuf");
 	
 	a = (xmax - xmin + 1) * (ymax - ymin + 1);
 	while (a--) {
-		if (*dr > 0 && *dr <= bm_vertoffs && *drm == 0) selbuf[*dr] = 1;
-		dr++; drm++;
+		if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) selbuf[*dr] = 1;
+		dr++; dr_mask++;
 	}
 	IMB_freeImBuf(buf);
-	IMB_freeImBuf(bufmask);
+	MEM_freeN(dr_mask_arr);
 
 	return true;
 }

Modified: trunk/blender/source/blender/windowmanager/intern/wm_gesture.c
===================================================================
--- trunk/blender/source/blender/windowmanager/intern/wm_gesture.c	2013-10-04 14:47:37 UTC (rev 60550)
+++ trunk/blender/source/blender/windowmanager/intern/wm_gesture.c	2013-10-04 15:02:05 UTC (rev 60551)
@@ -40,6 +40,7 @@
 #include "BLI_math.h"
 #include "BLI_scanfill.h"   /* lasso tessellation */
 #include "BLI_utildefines.h"
+#include "BLI_lasso.h"
 
 #include "BKE_context.h"
 
@@ -231,56 +232,73 @@
 	
 }
 
-static void draw_filled_lasso(wmGesture *gt)
+struct LassoFillData {
+	unsigned int *px;
+	int width;
+};
+
+static void draw_filled_lasso_px_cb(int x, int y, void *user_data)
 {
-	ScanFillContext sf_ctx;
-	ScanFillVert *sf_vert = NULL, *sf_vert_last = NULL, *sf_vert_first = NULL;
-	ScanFillFace *sf_tri;
+	struct LassoFillData *data = user_data;
+	unsigned char *col = (unsigned char *)&(data->px[(y * data->width) + x]);
+	col[0] = col[1] = col[2] = 0xff;
+	col[3] = 0x10;
+}
+
+static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
+{
 	short *lasso = (short *)gt->customdata;
+	const int tot = gt->points;
+	int (*moves)[2] = MEM_mallocN(sizeof(*moves) * (tot + 1), __func__);
 	int i;
-	
-	BLI_scanfill_begin(&sf_ctx);
-	for (i = 0; i < gt->points; i++, lasso += 2) {
-		float co[3];
+	rcti rect;
+	rcti rect_win;
 
-		co[0] = (float)lasso[0];
-		co[1] = (float)lasso[1];
-		co[2] = 0.0f;
+	for (i = 0; i < tot; i++, lasso += 2) {
+		moves[i][0] = lasso[0];
+		moves[i][1] = lasso[1];
+	}
 
-		sf_vert = BLI_scanfill_vert_add(&sf_ctx, co);
-		if (sf_vert_last)
-			/* e = */ /* UNUSED */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
-		sf_vert_last = sf_vert;
-		if (sf_vert_first == NULL) sf_vert_first = sf_vert;
-	}
-	
-	/* highly unlikely this will fail, but could crash if (gt->points == 0) */
-	if (sf_vert_first) {
-		const float zvec[3] = {0.0f, 0.0f, 1.0f};
-		BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert);
-		BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_HOLES, zvec);
-	
+	BLI_lasso_boundbox(&rect, (const int (*)[2])moves, tot);
+
+	wm_subwindow_getrect(win, gt->swinid, &rect_win);
+	BLI_rcti_translate(&rect, rect_win.xmin, rect_win.ymin);
+	BLI_rcti_isect(&rect_win, &rect, &rect);
+	BLI_rcti_translate(&rect, -rect_win.xmin, -rect_win.ymin);
+
+	/* highly unlikely this will fail, but could crash if (tot == 0) */
+	if (BLI_rcti_is_empty(&rect) == false) {
+		const int w = BLI_rcti_size_x(&rect);
+		const int h = BLI_rcti_size_y(&rect);
+		unsigned int *pixel_buf = MEM_callocN(sizeof(*pixel_buf) * w * h, __func__);
+		struct LassoFillData lasso_fill_data = {pixel_buf, w};
+
+		fill_poly_v2i_n(
+		       rect.xmin, rect.ymin, rect.xmax, rect.ymax,
+		       (const int (*)[2])moves, tot,
+		       draw_filled_lasso_px_cb, &lasso_fill_data);
+
 		glEnable(GL_BLEND);
-		glColor4f(1.0, 1.0, 1.0, 0.05);
-		glBegin(GL_TRIANGLES);
-		for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
-			glVertex2fv(sf_tri->v1->co);
-			glVertex2fv(sf_tri->v2->co);
-			glVertex2fv(sf_tri->v3->co);
-		}
-		glEnd();
+		// glColor4f(1.0, 1.0, 1.0, 0.05);
+
+		glRasterPos2f(rect.xmin, rect.ymin);
+
+		glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixel_buf);
+
 		glDisable(GL_BLEND);
-	
-		BLI_scanfill_end(&sf_ctx);
+		MEM_freeN(pixel_buf);
 	}
+
+	MEM_freeN(moves);
 }
 
-static void wm_gesture_draw_lasso(wmGesture *gt)
+
+static void wm_gesture_draw_lasso(wmWindow *win, wmGesture *gt)
 {
 	short *lasso = (short *)gt->customdata;
 	int i;
 
-	draw_filled_lasso(gt);
+	draw_filled_lasso(win, gt);
 	
 	glEnable(GL_LINE_STIPPLE);
 	glColor3ub(96, 96, 96);
@@ -347,9 +365,9 @@
 				wm_gesture_draw_cross(win, gt);

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list