From ceffc2cd50ea1e35757c8834b83b1d55f93d88c6 Mon Sep 17 00:00:00 2001 From: Peter Larabell Date: Wed, 13 Jun 2012 19:57:23 +0000 Subject: add Anti-Aliasing (very rough draft algorithm, NOT FINAL version) to raskter lib. Code is still quite messy but will be replaced when final algo comes in anyway. --- intern/raskter/raskter.c | 643 +++++++++++++++++++-- intern/raskter/raskter.h | 4 +- source/blender/blenkernel/BKE_mask.h | 2 +- source/blender/blenkernel/intern/mask.c | 4 +- source/blender/blenkernel/intern/sequencer.c | 6 +- source/blender/blenkernel/intern/tracking.c | 2 +- source/blender/compositor/nodes/COM_MaskNode.cpp | 1 + .../compositor/operations/COM_MaskOperation.cpp | 6 +- .../compositor/operations/COM_MaskOperation.h | 2 + source/blender/editors/space_node/drawnode.c | 2 + source/blender/makesrna/intern/rna_nodetree.c | 5 + .../nodes/composite/nodes/node_composite_mask.c | 7 +- 12 files changed, 638 insertions(+), 46 deletions(-) diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index 081a7c6bdbd..8bdd4dccbc0 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -34,7 +34,7 @@ /* from BLI_utildefines.h */ #define MIN2(x, y) ( (x) < (y) ? (x) : (y) ) #define MAX2(x, y) ( (x) > (y) ? (x) : (y) ) - +#define ABS(a) ( (a) < 0 ? (-(a)) : (a) ) struct e_status { int x; @@ -67,8 +67,7 @@ struct r_fill_context { * just the poly. Since the DEM code could end up being coupled with this, we'll keep it separate * for now. */ -static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, struct e_status *open_edge) -{ +static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, struct e_status *open_edge) { int i; int xbeg; int ybeg; @@ -94,8 +93,7 @@ static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *v /* we're not at the last vert, so end of the edge is the previous vertex */ xend = v[i - 1].x; yend = v[i - 1].y; - } - else { + } else { /* we're at the first vertex, so the "end" of this edge is the last vertex */ xend = v[num_verts - 1].x; yend = v[num_verts - 1].y; @@ -124,8 +122,7 @@ static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *v if (dx > 0) { e_new->xdir = 1; xdist = dx; - } - else { + } else { e_new->xdir = -1; xdist = -dx; } @@ -138,15 +135,13 @@ static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *v /* calculate deltas for incremental drawing */ if (dx >= 0) { e_new->drift = 0; - } - else { + } else { e_new->drift = -dy + 1; } if (dy >= xdist) { e_new->drift_inc = xdist; e_new->xshift = 0; - } - else { + } else { e_new->drift_inc = xdist % dy; e_new->xshift = (xdist / dy) * e_new->xdir; } @@ -170,8 +165,7 @@ static void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *v * 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. */ -static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts) -{ +static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, float intensity) { 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 */ @@ -260,8 +254,7 @@ static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, i 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 { + } else { edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */ } } @@ -307,7 +300,7 @@ static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, i if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { /* draw the pixels. */ - for (; cpxl <= mpxl; *cpxl++ = 1.0f); + for(; cpxl <= mpxl; *cpxl++ += intensity); } } @@ -323,8 +316,7 @@ static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, i for (edgec = &ctx->possible_edges; (e_curr = *edgec); ) { if (!(--(e_curr->num))) { *edgec = e_curr->e_next; - } - else { + } else { e_curr->x += e_curr->xshift; if ((e_curr->drift += e_curr->drift_inc) > 0) { e_curr->x += e_curr->xdir; @@ -383,12 +375,17 @@ static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, i } int PLX_raskterize(float (*base_verts)[2], int num_base_verts, - float *buf, int buf_x, int buf_y) -{ + float *buf, int buf_x, int buf_y, int do_mask_AA) { + int subdiv_AA = (do_mask_AA != 0)? 8:0; int i; /* i: Loop counter. */ + int sAx; + int sAy; struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ struct r_fill_context ctx = {0}; - + const float buf_x_f = (float)(buf_x); + const float buf_y_f = (float)(buf_y); + float div_offset=(1.0f / (float)(subdiv_AA)); + float div_offset_static = 0.5f * (float)(subdiv_AA) * div_offset; /* * 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. @@ -400,6 +397,9 @@ int PLX_raskterize(float (*base_verts)[2], int num_base_verts, return(0); } + 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) */ /* * 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 @@ -408,16 +408,25 @@ int PLX_raskterize(float (*base_verts)[2], int num_base_verts, * 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. */ + + if(!subdiv_AA) { 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. */ + ply[i].x = (int)((base_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */ + ply[i].y = (int)((base_verts[i][1] * buf_y_f) + 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. */ + i = rast_scan_fill(&ctx, ply, num_base_verts,1.0f); /* Call our rasterizer, passing in the integer coords for each vert. */ + } else { + for(sAx=0; sAx < subdiv_AA; sAx++) { + for(sAy=0; sAy < subdiv_AA; sAy++) { + for(i=0; i < num_base_verts; i++) { + ply[i].x = (int)((base_verts[i][0]*buf_x_f)+0.5f - div_offset_static + (div_offset*(float)(sAx))); + ply[i].y = (int)((base_verts[i][1]*buf_y_f)+0.5f - div_offset_static + (div_offset*(float)(sAy))); + } + i = rast_scan_fill(&ctx, ply, num_base_verts,(1.0f / (float)(subdiv_AA*subdiv_AA))); + } + } + } free(ply); /* Free the memory allocated for the integer coordinate table. */ return(i); /* Return the value returned by the rasterizer. */ } @@ -429,8 +438,7 @@ int PLX_raskterize(float (*base_verts)[2], int num_base_verts, */ static int rast_scan_feather(struct r_fill_context *ctx, float (*base_verts_f)[2], int num_base_verts, - struct poly_vert *feather_verts, float (*feather_verts_f)[2], int num_feather_verts) -{ + struct poly_vert *feather_verts, float(*feather_verts_f)[2], 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 */ @@ -536,8 +544,7 @@ static int rast_scan_feather(struct r_fill_context *ctx, 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 { + } else { edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */ } } @@ -647,8 +654,7 @@ static int rast_scan_feather(struct r_fill_context *ctx, for (edgec = &ctx->possible_edges; (e_curr = *edgec); ) { if (!(--(e_curr->num))) { *edgec = e_curr->e_next; - } - else { + } else { e_curr->x += e_curr->xshift; if ((e_curr->drift += e_curr->drift_inc) > 0) { e_curr->x += e_curr->xdir; @@ -708,8 +714,7 @@ static int rast_scan_feather(struct r_fill_context *ctx, } int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*feather_verts)[2], int num_feather_verts, - float *buf, int buf_x, int buf_y) -{ + float *buf, int buf_x, int buf_y) { int i; /* i: Loop counter. */ struct poly_vert *fe; /* fe: Pointer to a list of integer buffer-space feather vertex coords. */ struct r_fill_context ctx = {0}; @@ -751,3 +756,569 @@ int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*f free(fe); return i; /* Return the value returned by the rasterizer. */ } + +int get_range_expanded_pixel_coord(float normalized_value, int max_value) { + return (int)((normalized_value * (float)(max_value)) + 0.5f); +} + +float get_pixel_intensity(float *buf, int buf_x, int buf_y, int pos_x, int pos_y) { + if(pos_x < 0 || pos_x >= buf_x || pos_y < 0 || pos_y >= buf_y) { + return 0.0f; + } + return buf[(pos_y * buf_y) + buf_x]; +} + +float get_pixel_intensity_bilinear(float *buf, int buf_x, int buf_y, float u, float v) { + int a; + int b; + int a_plus_1; + int b_plus_1; + float prop_u; + float prop_v; + float inv_prop_u; + float inv_prop_v; + if(u<0.0f || u>1.0f || v<0.0f || v>1.0f) { + return 0.0f; + } + u = u * (float)(buf_x) - 0.5f; + v = v * (float)(buf_y) - 0.5f; + a = (int)(u); + b = (int)(v); + prop_u = u - (float)(a); + prop_v = v - (float)(b); + inv_prop_u = 1.0f - prop_u; + inv_prop_v = 1.0f - prop_v; + a_plus_1 = MIN2((buf_x-1),a+1); + b_plus_1 = MIN2((buf_y-1),b+1); + return (buf[(b * buf_y) + a] * inv_prop_u + buf[(b*buf_y)+(a_plus_1)] * prop_u)*inv_prop_v+(buf[((b_plus_1) * buf_y)+a] * inv_prop_u + buf[((b_plus_1)*buf_y)+(a_plus_1)] * prop_u) * prop_v; + +} + +void set_pixel_intensity(float *buf, int buf_x, int buf_y, int pos_x, int pos_y, float intensity) { + if(pos_x < 0 || pos_x >= buf_x || pos_y < 0 || pos_y >= buf_y) { + return; + } + buf[(pos_y * buf_y) + buf_x] = intensity; +} +#define __PLX__FAKE_AA__ +int PLX_antialias_buffer(float *buf, int buf_x, int buf_y) { +#ifdef __PLX__FAKE_AA__ +#ifdef __PLX_GREY_AA__ + int i=0; + int sz = buf_x * buf_y; + for(i=0; i= edgeVert ? 1:0; + subpixA = subpixNSWE * 2.0f + subpixNWSWNESE; + + if(!horzSpan) { + lumaN = lumaW; + lumaS = lumaE; + } else { + lengthSign = 1.0f / (float)(buf_y); + } + subpixB = (subpixA * (1.0f/12.0f)) - lumaM; + + gradientN = lumaN - lumaM; + gradientS = lumaS - lumaM; + lumaNN = lumaN + lumaM; + lumaSS = lumaS + lumaM; + pairN = (ABS(gradientN)) >= (ABS(gradientS)) ? 1:0; + gradient = MAX2(ABS(gradientN), ABS(gradientS)); + if(pairN) { + lengthSign = -lengthSign; + } + subpixC = MAX2(MIN2(ABS(subpixB) * subpixRcpRange,1.0f),0.0f); + + posB_x = posM_x; + posB_y = posM_y; + offNP_x = (!horzSpan) ? 0.0f:(1.0f / (float)(buf_x)); + offNP_y = (horzSpan) ? 0.0f:(1.0f / (float)(buf_y)); + if(!horzSpan) { + posB_x += lengthSign * 0.5f; + } else { + posB_y += lengthSign * 0.5f; + } + + posN_x = posB_x - offNP_x * p0; + posN_y = posB_y - offNP_y * p0; + posP_x = posB_x + offNP_x * p0; + posP_y = posB_y + offNP_y * p0; + subpixD = ((-2.0f)*subpixC) + 3.0f; + //may need bilinear filtered get_pixel_intensity() here...done + lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y); + subpixE = subpixC * subpixC; + //may need bilinear filtered get_pixel_intensity() here...done + lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y); + + if(!pairN) { + lumaNN = lumaSS; + } + gradientScaled = gradient * 1.0f/4.0f; + lumaMM =lumaM - lumaNN * 0.5f; + subpixF = subpixD * subpixE; + lumaMLTZero = lumaMM < 0.0f ? 1:0; + + lumaEndN -= lumaNN * 0.5f; + lumaEndP -= lumaNN * 0.5f; + doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0; + doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0; + if(!doneN) { + posN_x -= offNP_x * p1; + posN_y -= offNP_y * p1; + } + doneNP = (!doneN) || (!doneP) ? 1:0; + if(!doneP) { + posP_x += offNP_x * p1; + posP_y += offNP_y * p1; + } + + if(doneNP) { + if(!doneN) { + lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posN_x,posN_y); + } + if(!doneP) { + lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x, posP_y); + } + if(!doneN) { + lumaEndN = lumaEndN - lumaNN * 0.5; + } + if(!doneP) { + lumaEndP = lumaEndP - lumaNN * 0.5; + } + doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0; + doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0; + if(!doneN) { + posN_x -= offNP_x * p2; + posN_y -= offNP_y * p2; + } + doneNP = (!doneN) || (!doneP) ? 1:0; + if(!doneP) { + posP_x += offNP_x * p2; + posP_y += offNP_y * p2; + } + if(doneNP) { + if(!doneN) { + lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y); + } + if(!doneP) { + lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y); + } + if(!doneN) { + lumaEndN = lumaEndN - lumaNN * 0.5; + } + if(!doneP) { + lumaEndP = lumaEndP - lumaNN * 0.5; + } + doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0; + doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0; + if(!doneN) { + posN_x -= offNP_x * p3; + posN_y -= offNP_y * p3; + } + doneNP = (!doneN) || (!doneP) ? 1:0; + if(!doneP) { + posP_x += offNP_x * p3; + posP_y += offNP_y * p3; + } + if(doneNP) { + if(!doneN) { + lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y); + } + if(!doneP) { + lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y); + } + if(!doneN) { + lumaEndN = lumaEndN - lumaNN * 0.5; + } + if(!doneP) { + lumaEndP = lumaEndP - lumaNN * 0.5; + } + doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0; + doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0; + if(!doneN) { + posN_x -= offNP_x * p4; + posN_y -= offNP_y * p4; + } + doneNP = (!doneN) || (!doneP) ? 1:0; + if(!doneP) { + posP_x += offNP_x * p4; + posP_y += offNP_y * p4; + } + if(doneNP) { + if(!doneN) { + lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y); + } + if(!doneP) { + lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y); + } + if(!doneN) { + lumaEndN = lumaEndN - lumaNN * 0.5; + } + if(!doneP) { + lumaEndP = lumaEndP - lumaNN * 0.5; + } + doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0; + doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0; + if(!doneN) { + posN_x -= offNP_x * p5; + posN_y -= offNP_y * p5; + } + doneNP = (!doneN) || (!doneP) ? 1:0; + if(!doneP) { + posP_x += offNP_x * p5; + posP_y += offNP_y * p5; + } + if(doneNP) { + if(!doneN) { + lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y); + } + if(!doneP) { + lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y); + } + if(!doneN) { + lumaEndN = lumaEndN - lumaNN * 0.5; + } + if(!doneP) { + lumaEndP = lumaEndP - lumaNN * 0.5; + } + doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0; + doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0; + if(!doneN) { + posN_x -= offNP_x * p6; + posN_y -= offNP_y * p6; + } + doneNP = (!doneN) || (!doneP) ? 1:0; + if(!doneP) { + posP_x += offNP_x * p6; + posP_y += offNP_y * p6; + } + if(doneNP) { + if(!doneN) { + lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y); + } + if(!doneP) { + lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y); + } + if(!doneN) { + lumaEndN = lumaEndN - lumaNN * 0.5; + } + if(!doneP) { + lumaEndP = lumaEndP - lumaNN * 0.5; + } + doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0; + doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0; + if(!doneN) { + posN_x -= offNP_x * p7; + posN_y -= offNP_y * p7; + } + doneNP = (!doneN) || (!doneP) ? 1:0; + if(!doneP) { + posP_x += offNP_x * p7; + posP_y += offNP_y * p7; + } + if(doneNP) { + if(!doneN) { + lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y); + } + if(!doneP) { + lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y); + } + if(!doneN) { + lumaEndN = lumaEndN - lumaNN * 0.5; + } + if(!doneP) { + lumaEndP = lumaEndP - lumaNN * 0.5; + } + doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0; + doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0; + if(!doneN) { + posN_x -= offNP_x * p8; + posN_y -= offNP_y * p8; + } + doneNP = (!doneN) || (!doneP) ? 1:0; + if(!doneP) { + posP_x += offNP_x * p8; + posP_y += offNP_y * p8; + } + if(doneNP) { + if(!doneN) { + lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y); + } + if(!doneP) { + lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y); + } + if(!doneN) { + lumaEndN = lumaEndN - lumaNN * 0.5; + } + if(!doneP) { + lumaEndP = lumaEndP - lumaNN * 0.5; + } + doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0; + doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0; + if(!doneN) { + posN_x -= offNP_x * p9; + posN_y -= offNP_y * p9; + } + doneNP = (!doneN) || (!doneP) ? 1:0; + if(!doneP) { + posP_x += offNP_x * p9; + posP_y += offNP_y * p9; + } + if(doneNP) { + if(!doneN) { + lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y); + } + if(!doneP) { + lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y); + } + if(!doneN) { + lumaEndN = lumaEndN - lumaNN * 0.5; + } + if(!doneP) { + lumaEndP = lumaEndP - lumaNN * 0.5; + } + doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0; + doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0; + if(!doneN) { + posN_x -= offNP_x * p10; + posN_y -= offNP_y * p10; + } + doneNP = (!doneN) || (!doneP) ? 1:0; + if(!doneP) { + posP_x += offNP_x * p10; + posP_y += offNP_y * p10; + } + if(doneNP) { + if(!doneN) { + lumaEndN = get_pixel_intensity_bilinear(buf, buf_x, buf_y,posN_x,posN_y); + } + if(!doneP) { + lumaEndP = get_pixel_intensity_bilinear(buf, buf_x, buf_y, posP_x,posP_y); + } + if(!doneN) { + lumaEndN = lumaEndN - lumaNN * 0.5; + } + if(!doneP) { + lumaEndP = lumaEndP - lumaNN * 0.5; + } + doneN = (ABS(lumaEndN)) >= gradientScaled ? 1:0; + doneP = (ABS(lumaEndP)) >= gradientScaled ? 1:0; + if(!doneN) { + posN_x -= offNP_x * p11; + posN_y -= offNP_y * p11; + } + doneNP = (!doneN) || (!doneP) ? 1:0; + if(!doneP) { + posP_x += offNP_x * p11; + posP_y += offNP_y * p11; + } + } + } + } + } + } + } + } + } + } + } + dstN = posM_x - posN_x; + dstP = posP_x - posM_x; + if(!horzSpan) { + dstN = posM_y - posN_y; + dstP = posP_y - posM_y; + } + + goodSpanN = ((lumaEndN < 0.0f) ? 1:0) != lumaMLTZero ? 1:0; + spanLength = (dstP + dstN); + goodSpanP = ((lumaEndP < 0.0f) ? 1:0) != lumaMLTZero ? 1:0; + spanLengthRcp = 1.0f/spanLength; + + directionN = dstN < dstP ? 1:0; + dst = MIN2(dstN, dstP); + goodSpan = (directionN==1) ? goodSpanN:goodSpanP; + subpixG = subpixF * subpixF; + pixelOffset = (dst * (-spanLengthRcp)) + 0.5f; + subpixH = subpixG * quality_subpix; + + pixelOffsetGood = (goodSpan==1) ? pixelOffset : 0.0f; + pixelOffsetSubpix = MAX2(pixelOffsetGood, subpixH); + if(!horzSpan) { + posM_x += pixelOffsetSubpix * lengthSign; + } else { + posM_y += pixelOffsetSubpix * lengthSign; + } + //may need bilinear filtered get_pixel_intensity() here... + set_pixel_intensity(buf,buf_x,buf_y,curr_x,curr_y,get_pixel_intensity_bilinear(buf, buf_x, buf_y, posM_x,posM_y)* lumaM); + + } + } + return 1; + +#endif +} + diff --git a/intern/raskter/raskter.h b/intern/raskter/raskter.h index e80ca1d41c4..e078b0d26be 100644 --- a/intern/raskter/raskter.h +++ b/intern/raskter/raskter.h @@ -49,11 +49,11 @@ extern "C" { #endif int PLX_raskterize(float (*base_verts)[2], int num_base_verts, - float *buf, int buf_x, int buf_y); + float *buf, int buf_x, int buf_y, int do_mask_AA); int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, float (*feather_verts)[2], int num_feather_verts, float *buf, int buf_x, int buf_y); - +int PLX_antialias_buffer(float *buf, int buf_x, int buf_y); #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index dd2c7cb3a18..0e93869a8b0 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -170,7 +170,7 @@ void BKE_mask_layer_shape_changed_remove(struct MaskLayer *masklay, int index, i /* rasterization */ int BKE_mask_get_duration(struct Mask *mask); void BKE_mask_rasterize(struct Mask *mask, int width, int height, float *buffer, - const short do_aspect_correct); + const short do_aspect_correct, int do_mask_aa); #define MASKPOINT_ISSEL_ANY(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT) #define MASKPOINT_ISSEL_KNOT(p) ( (p)->bezt.f2 & SELECT) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 012ce97b4d7..7e9f189ae01 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -2089,7 +2089,7 @@ int BKE_mask_get_duration(Mask *mask) /* rasterization */ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer, - const short do_aspect_correct) + const short do_aspect_correct, int do_mask_aa) { MaskLayer *masklay; @@ -2154,7 +2154,7 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer, if (tot_diff_point) { PLX_raskterize(diff_points, tot_diff_point, - buffer_tmp, width, height); + buffer_tmp, width, height, do_mask_aa); if (tot_diff_feather_points) { PLX_raskterize_feather(diff_points, tot_diff_point, diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 889eee25d6b..ddf30ecfa81 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2081,7 +2081,8 @@ static ImBuf *seq_render_mask_strip( BKE_mask_rasterize(seq->mask, context.rectx, context.recty, maskbuf, - TRUE); + TRUE, + FALSE /*XXX- TODO: make on/off for anti-aliasing*/); fp_src = maskbuf; fp_dst = ibuf->rect_float; @@ -2104,7 +2105,8 @@ static ImBuf *seq_render_mask_strip( BKE_mask_rasterize(seq->mask, context.rectx, context.recty, maskbuf, - TRUE); + TRUE, + FALSE /*XXX- TODO: mask on/off for anti-aliasing*/); fp_src = maskbuf; ub_dst = (unsigned char *)ibuf->rect; diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index b61a39a2cd2..0aa0d36c537 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1428,7 +1428,7 @@ static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height fp[1] = (stroke_points[i].y - marker->search_min[1]) * frame_height / mask_height; } - PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height); + PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height, FALSE /* XXX- TODO: make on/off for AA*/); MEM_freeN(mask_points); } diff --git a/source/blender/compositor/nodes/COM_MaskNode.cpp b/source/blender/compositor/nodes/COM_MaskNode.cpp index e26756cfc5b..4371a848a3d 100644 --- a/source/blender/compositor/nodes/COM_MaskNode.cpp +++ b/source/blender/compositor/nodes/COM_MaskNode.cpp @@ -54,6 +54,7 @@ void MaskNode::convertToOperations(ExecutionSystem *graph, CompositorContext * c operation->setMask(mask); operation->setFramenumber(context->getFramenumber()); + operation->setSmooth((bool)editorNode->custom1); graph->addOperation(operation); } diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index bfbf2b42e82..8f7115659a1 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -32,6 +32,7 @@ extern "C" { #include "BKE_mask.h" + #include "../../../../intern/raskter/raskter.h" } MaskOperation::MaskOperation(): NodeOperation() @@ -74,7 +75,10 @@ void *MaskOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers float *buffer; buffer = (float *)MEM_callocN(sizeof(float) * width * height, "rasterized mask"); - BKE_mask_rasterize(mask, width, height, buffer, TRUE); + BKE_mask_rasterize(mask, width, height, buffer, TRUE, this->smooth); + if(this->smooth) { + PLX_antialias_buffer(buffer, width, height); + } this->rasterizedMask = buffer; } diff --git a/source/blender/compositor/operations/COM_MaskOperation.h b/source/blender/compositor/operations/COM_MaskOperation.h index 9f2c7f53f56..8534cb20416 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.h +++ b/source/blender/compositor/operations/COM_MaskOperation.h @@ -40,6 +40,7 @@ protected: int maskWidth; int maskHeight; int framenumber; + bool smooth; float *rasterizedMask; /** @@ -59,6 +60,7 @@ public: void setMaskWidth(int width) {this->maskWidth = width;} void setMaskHeight(int height) {this->maskHeight = height;} void setFramenumber(int framenumber) {this->framenumber = framenumber;} + void setSmooth(bool smooth) {this->smooth = smooth;} void executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data); }; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 12c369874fe..e6549034a85 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -2421,6 +2421,8 @@ static void node_composit_buts_viewer_but(uiLayout *layout, bContext *UNUSED(C), static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *ptr) { uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL); + uiItemR(layout, ptr, "smooth_mask", 0, NULL, ICON_NONE); + } /* only once called */ diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 92de882d48b..73e2b5da4f0 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3089,6 +3089,11 @@ static void def_cmp_mask(StructRNA *srna) { PropertyRNA *prop; + prop = RNA_def_property(srna, "smooth_mask", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "custom1", 0); + RNA_def_property_ui_text(prop, "Anti-Alias", "Apply an anti-aliasing filter to the mask"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + prop = RNA_def_property(srna, "mask", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "id"); RNA_def_property_struct_type(prop, "Mask"); diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c index dbe3c11ab55..d323839e690 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mask.c +++ b/source/blender/nodes/composite/nodes/node_composite_mask.c @@ -38,6 +38,8 @@ #include "node_composite_util.h" +#include "../../../../intern/raskter/raskter.h" + /* **************** Translate ******************** */ static bNodeSocketTemplate cmp_node_mask_out[] = { @@ -68,8 +70,11 @@ static void exec(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack ** stackbuf = alloc_compbuf(sx, sy, CB_VAL, TRUE); res = stackbuf->rect; - BKE_mask_rasterize(mask, sx, sy, res, TRUE); + BKE_mask_rasterize(mask, sx, sy, res, TRUE, node->custom1); + if(node->custom1){ + PLX_antialias_buffer(res,sx,sy); + } /* pass on output and free */ out[0]->data = stackbuf; } -- cgit v1.2.3