[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [47259] branches/soc-2011-tomato: patch from pete larabell - feather support for masking.

Campbell Barton ideasman42 at gmail.com
Thu May 31 10:39:22 CEST 2012


Revision: 47259
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=47259
Author:   campbellbarton
Date:     2012-05-31 08:39:22 +0000 (Thu, 31 May 2012)
Log Message:
-----------
patch from pete larabell - feather support for masking.

Modified Paths:
--------------
    branches/soc-2011-tomato/intern/raskter/raskter.c
    branches/soc-2011-tomato/intern/raskter/raskter.h
    branches/soc-2011-tomato/source/blender/blenkernel/intern/mask.c
    branches/soc-2011-tomato/source/blender/blenkernel/intern/tracking.c

Modified: branches/soc-2011-tomato/intern/raskter/raskter.c
===================================================================
--- branches/soc-2011-tomato/intern/raskter/raskter.c	2012-05-31 08:38:50 UTC (rev 47258)
+++ branches/soc-2011-tomato/intern/raskter/raskter.c	2012-05-31 08:39:22 UTC (rev 47259)
@@ -388,22 +388,358 @@
 	return 1;
 }
 
-int PLX_raskterize(float *verts, int num, float *buf, int buf_x, int buf_y) {
+int PLX_raskterize(float (*base_verts)[2], int num_base_verts, float *buf, int buf_x, int buf_y)
+{
 	int i;                                       /* i: Loop counter. */
 	struct poly_vert *ply;                       /* ply: Pointer to a list of integer buffer-space vertex coordinates. */
 	struct r_fill_context ctx = {0};
 
 	/*
 	 * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert
+	 * data structure multiplied by the number of base_verts.
+	 *
+	 * In the event of a failure to allocate the memory, return 0, so this error can
+	 * be distinguished as a memory allocation error.
+	 */
+	if ((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_base_verts))) == NULL) {
+		return(0);
+	}
+
+	/*
+	 * Loop over all verts passed in to be rasterized. Each vertex's X and Y coordinates are
+	 * then converted from normalized screen space (0.0 <= POS <= 1.0) to integer coordinates
+	 * in the buffer-space coordinates passed in inside buf_x and buf_y.
+	 *
+	 * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel
+	 * drawn will be 1.0f in value, there is no anti-aliasing.
+	 */
+	for (i = 0; i < num_base_verts; i++) {                          /* Loop over all base_verts. */
+		ply[i].x = (base_verts[i][0] * buf_x) + 0.5f;       /* Range expand normalized X to integer buffer-space X. */
+		ply[i].y = (base_verts[i][1] * buf_y) + 0.5f; /* Range expand normalized Y to integer buffer-space Y. */
+	}
+
+	ctx.rb.buf = buf;                            /* Set the output buffer pointer. */
+	ctx.rb.sizex = buf_x;                        /* Set the output buffer size in X. (width) */
+	ctx.rb.sizey = buf_y;                        /* Set the output buffer size in Y. (height) */
+
+	i = rast_scan_fill(&ctx, ply, num_base_verts);  /* Call our rasterizer, passing in the integer coords for each vert. */
+	free(ply);                                      /* Free the memory allocated for the integer coordinate table. */
+	return(i);                                      /* Return the value returned by the rasterizer. */
+}
+
+/*
+ * This function clips drawing to the frame buffer. That clipping will likely be moved into the preprocessor
+ * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need
+ * if it ends up being coupled with this function.
+ */
+int rast_scan_feather(struct r_fill_context *ctx,
+                      struct poly_vert *base_verts, int num_base_verts,
+                      struct poly_vert *feather_verts, int num_feather_verts)
+{
+	int x_curr;                 /* current pixel position in X */
+	int y_curr;                 /* current scan line being drawn */
+	int yp;                     /* y-pixel's position in frame buffer */
+	int swixd = 0;              /* whether or not edges switched position in X */
+	float *cpxl;                /* pixel pointers... */
+	float *mpxl;
+	float *spxl;
+	struct e_status *e_curr;    /* edge pointers... */
+	struct e_status *e_temp;
+	struct e_status *edgbuf;
+	struct e_status **edgec;
+
+	/* from dem */
+	int a;                          // a = temporary pixel index buffer loop counter
+	int fsz;                        // size of the frame
+	unsigned int rsl;               // long used for finding fast 1.0/sqrt
+	float rsf;                      // float used for finding fast 1.0/sqrt
+	const float rsopf = 1.5f;       // constant float used for finding fast 1.0/sqrt
+
+	//unsigned int gradientFillOffset;
+	unsigned int t;
+	unsigned int ud;                // ud = unscaled edge distance
+	unsigned int dmin;              // dmin = minimun edge distance
+	float odist;                    // odist = current outer edge distance
+	float idist;                    // idist = current inner edge distance
+	int dx;                         // dx = X-delta (used for distance proportion calculation)
+	int dy;                         // dy = Y-delta (used for distance proportion calculation)
+
+
+	/*
+	 * If the number of verts specified to render as a polygon is less than 3,
+	 * return immediately. Obviously we cant render a poly with sides < 3. The
+	 * return for this we set to 1, simply so it can be distinguished from the
+	 * next place we could return, /home/guest/blender-svn/soc-2011-tomato/intern/raskter/raskter
+	 * which is a failure to allocate memory.
+	 */
+	if (num_feather_verts < 3) {
+		return(1);
+	}
+
+	/*
+	 * Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data
+	 * multiplied by the number of edges, which is always equal to the number of verts in
+	 * a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for
+	 * the preceeding error, which was a rasterization request on a 2D poly with less than
+	 * 3 sides.
+	 */
+	if ((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_feather_verts))) == NULL) {
+		return(0);
+	}
+
+	/*
+	 * Do some preprocessing on all edges. This constructs a table structure in memory of all
+	 * the edge properties and can "flip" some edges so sorting works correctly.
+	 */
+	preprocess_all_edges(ctx, feather_verts, num_feather_verts, edgbuf);
+
+	/*
+	 * Set the pointer for tracking the edges currently in processing to NULL to make sure
+	 * we don't get some crazy value after initialization.
+	 */
+	ctx->possible_edges = NULL;
+
+	/*
+	 * Loop through all scan lines to be drawn. Since we sorted by Y values during
+	 * preprocess_all_edges(), we can already exact values for the lowest and
+	 * highest Y values we could possibly need by induction. The preprocessing sorted
+	 * out edges by Y position, we can cycle the current edge being processed once
+	 * it runs out of Y pixels. When we have no more edges, meaning the current edge
+	 * is NULL after setting the "current" edge to be the previous current edge's
+	 * "next" edge in the Y sorted edge connection chain, we can stop looping Y values,
+	 * since we can't possibly have more scan lines if we ran out of edges. :)
+	 *
+	 * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here.
+	 *       Will get changed once DEM code gets in.
+	 */
+	for (y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) {
+
+		/*
+		 * Link any edges that start on the current scan line into the list of
+		 * edges currently needed to draw at least this, if not several, scan lines.
+		 */
+
+		/*
+		 * Set the current edge to the beginning of the list of edges to be rasterized
+		 * into this scan line.
+		 *
+		 * We could have lots of edge here, so iterate over all the edges needed. The
+		 * preprocess_all_edges() function sorted edges by X within each chunk of Y sorting
+		 * so we safely cycle edges to thier own "next" edges in order.
+		 *
+		 * At each iteration, make sure we still have a non-NULL edge.
+		 */
+		for (edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr); ) {
+			x_curr = ctx->all_edges->x;                  /* Set current X position. */
+			for (;; ) {                                  /* Start looping edges. Will break when edges run out. */
+				e_curr = *edgec;                         /* Set up a current edge pointer. */
+				if (!e_curr || (e_curr->x >= x_curr)) {  /* If we have an no edge, or we need to skip some X-span, */
+					e_temp = ctx->all_edges->e_next;     /* set a temp "next" edge to test. */
+					*edgec = ctx->all_edges;             /* Add this edge to the list to be scanned. */
+					ctx->all_edges->e_next = e_curr;     /* Set up the next edge. */
+					edgec = &ctx->all_edges->e_next;     /* Set our list to the next edge's location in memory. */
+					ctx->all_edges = e_temp;             /* Skip the NULL or bad X edge, set pointer to next edge. */
+					break;                               /* Stop looping edges (since we ran out or hit empty X span. */
+				}
+				else {
+					edgec = &e_curr->e_next;             /* Set the pointer to the edge list the "next" edge. */
+				}
+			}
+		}
+
+		/*
+		 * Determine the current scan line's offset in the pixel buffer based on its Y position.
+		 * Basically we just multiply the current scan line's Y value by the number of pixels in each line.
+		 */
+		yp = y_curr * ctx->rb.sizex;
+		/*
+		 * Set a "scan line pointer" in memory. The location of the buffer plus the row offset.
+		 */
+		spxl = ctx->rb.buf + (yp);
+		/*
+		 * Set up the current edge to the first (in X) edge. The edges which could possibly be in this
+		 * list were determined in the preceeding edge loop above. They were already sorted in X by the
+		 * initial processing function.
+		 *
+		 * At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge
+		 * we will eventually hit a NULL when the list runs out.
+		 */
+		for (e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) {
+			/*
+			 * Calculate a span of pixels to fill on the current scan line.
+			 *
+			 * Set the current pixel pointer by adding the X offset to the scan line's start offset.
+			 * Cycle the current edge the next edge.
+			 * Set the max X value to draw to be one less than the next edge's first pixel. This way we are
+			 * sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than
+			 * one time because it's on a vertex connecting two edges)
+			 *
+			 * Then blast through all the pixels in the span, advancing the pointer and setting the color to white.
+			 *
+			 * TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor,
+			 *       but for now it is done here until the DEM code comes in.
+			 */
+
+			/* set up xmin and xmax bounds on this scan line */
+			cpxl = spxl + MAX2(e_curr->x, 0);
+			e_curr = e_curr->e_next;
+			mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1;
+
+			if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) {
+				/* draw the pixels. */

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list