gpencil simplified filtering, unbiased smoothing, and pen eraser that works

This commit is contained in:
Mike Erwin 2010-06-14 02:03:01 +00:00
parent 6154ea9f28
commit 707220b150

@ -184,24 +184,21 @@ static void gp_get_3d_reference (tGPsdata *p, float *vec)
/* check if the current mouse position is suitable for adding a new point */ /* check if the current mouse position is suitable for adding a new point */
static short gp_stroke_filtermval (tGPsdata *p, int mval[2], int pmval[2]) static short gp_stroke_filtermval (tGPsdata *p, int mval[2], int pmval[2])
{ {
int dx= abs(mval[0] - pmval[0]);
int dy= abs(mval[1] - pmval[1]);
/* if buffer is empty, just let this go through (i.e. so that dots will work) */ /* if buffer is empty, just let this go through (i.e. so that dots will work) */
if (p->gpd->sbuffer_size == 0) if (p->gpd->sbuffer_size == 0)
return 1; return 1;
else {
/* check if the distance since the last point is significant enough
no need for abs() or sqrt(), and don't bother checking Manhattan distance (ok?) */
/* check if mouse moved at least certain distance on both axes (best case) */ int dx= mval[0] - pmval[0];
else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX)) int dy= mval[1] - pmval[1];
if ((dx*dx + dy*dy) > (MIN_EUCLIDEAN_PX * MIN_EUCLIDEAN_PX))
return 1; return 1;
}
/* check if the distance since the last point is significant enough */ /* pencil 'didn't move' if we make it this far */
// future optimisation: sqrt here may be too slow?
else if (sqrt(dx*dx + dy*dy) > MIN_EUCLIDEAN_PX)
return 1;
/* mouse 'didn't move' */
else
return 0; return 0;
} }
@ -349,29 +346,43 @@ static short gp_stroke_addpoint (tGPsdata *p, int mval[2], float pressure)
/* smooth a stroke (in buffer) before storing it */ /* smooth a stroke (in buffer) before storing it */
static void gp_stroke_smooth (tGPsdata *p) static void gp_stroke_smooth (tGPsdata *p)
{ {
bGPdata *gpd= p->gpd;
int i=0, cmx=gpd->sbuffer_size;
/* only smooth if smoothing is enabled, and we're not doing a straight line */ /* only smooth if smoothing is enabled, and we're not doing a straight line */
if (!(U.gp_settings & GP_PAINT_DOSMOOTH) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)) if (!(U.gp_settings & GP_PAINT_DOSMOOTH) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT))
return; return;
else {
bGPdata *gpd= p->gpd;
int num_points=gpd->sbuffer_size;
/* don't try if less than 2 points in buffer */ /* don't try if less than 5 points in buffer */
if ((cmx <= 2) || (gpd->sbuffer == NULL)) if ((num_points <= 5) || (gpd->sbuffer == NULL))
return; return;
else {
/* apply weighting-average (avoiding errors from sequential processing) */
/* apply weighting-average (note doing this along path sequentially does introduce slight error) */ tGPspoint *begin = (tGPspoint*)gpd->sbuffer + 2;
for (i=0; i < gpd->sbuffer_size; i++) { tGPspoint *end = (tGPspoint*)gpd->sbuffer + num_points - 2;
tGPspoint *pc= (((tGPspoint *)gpd->sbuffer) + i);
tGPspoint *pb= (i-1 > 0)?(pc-1):(pc);
tGPspoint *pa= (i-2 > 0)?(pc-2):(pb);
tGPspoint *pd= (i+1 < cmx)?(pc+1):(pc);
tGPspoint *pe= (i+2 < cmx)?(pc+2):(pd);
pc->x= (short)(0.1*pa->x + 0.2*pb->x + 0.4*pc->x + 0.2*pd->x + 0.1*pe->x); tGPspoint orig_a = *(begin - 2);
pc->y= (short)(0.1*pa->y + 0.2*pb->y + 0.4*pc->y + 0.2*pd->y + 0.1*pe->y); tGPspoint orig_b = *(begin - 1);
tGPspoint *c = begin;
tGPspoint *d = begin + 1;
tGPspoint *e = begin + 2;
for (; c < end; ++c, ++d, ++e) {
tGPspoint orig_c = *c;
c->x= (short)(0.1*orig_a.x + 0.2*orig_b.x + 0.4*orig_c.x + 0.2*d->x + 0.1*e->x);
c->y= (short)(0.1*orig_a.y + 0.2*orig_b.y + 0.4*orig_c.y + 0.2*d->y + 0.1*e->y);
orig_a = orig_b;
orig_b = orig_c;
} }
} }
}
}
/* simplify a stroke (in buffer) before storing it /* simplify a stroke (in buffer) before storing it
* - applies a reverse Chaikin filter * - applies a reverse Chaikin filter
@ -385,12 +396,12 @@ static void gp_stroke_simplify (tGPsdata *p)
short flag= gpd->sbuffer_sflag; short flag= gpd->sbuffer_sflag;
short i, j; short i, j;
/* only simplify if simlification is enabled, and we're not doing a straight line */ /* only simplify if simplification is enabled, and we're not doing a straight line */
if (!(U.gp_settings & GP_PAINT_DOSIMPLIFY) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)) if (!(U.gp_settings & GP_PAINT_DOSIMPLIFY) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT))
return; return;
/* don't simplify if less than 4 points in buffer */ /* don't simplify if less than 4 points in buffer */
if ((num_points <= 2) || (old_points == NULL)) if ((num_points < 4) || (old_points == NULL))
return; return;
/* clear buffer (but don't free mem yet) so that we can write to it /* clear buffer (but don't free mem yet) so that we can write to it
@ -1283,8 +1294,10 @@ static void gpencil_draw_apply_event (bContext *C, wmOperator *op, wmEvent *even
tablet= (wmtab->Active != EVT_TABLET_NONE); tablet= (wmtab->Active != EVT_TABLET_NONE);
p->pressure= wmtab->Pressure; p->pressure= wmtab->Pressure;
//if (wmtab->Active == EVT_TABLET_ERASER) if (wmtab->Active == EVT_TABLET_ERASER)
// TODO... this should get caught by the keymaps which call drawing in the first place // TODO... this should get caught by the keymaps which call drawing in the first place
// .. but until that's possible, duct tape the eraser function back on
p->paintmode = GP_PAINTMODE_ERASER;
} }
else else
p->pressure= 1.0f; p->pressure= 1.0f;
@ -1515,8 +1528,6 @@ static EnumPropertyItem prop_gpencil_drawmodes[] = {
void GPENCIL_OT_draw (wmOperatorType *ot) void GPENCIL_OT_draw (wmOperatorType *ot)
{ {
PropertyRNA *prop;
/* identifiers */ /* identifiers */
ot->name= "Grease Pencil Draw"; ot->name= "Grease Pencil Draw";
ot->idname= "GPENCIL_OT_draw"; ot->idname= "GPENCIL_OT_draw";
@ -1533,8 +1544,6 @@ void GPENCIL_OT_draw (wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
/* settings for drawing */ /* settings for drawing */
prop= RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to intepret mouse movements."); RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to intepret mouse movements.");
RNA_def_property_flag(prop, PROP_HIDDEN);
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
} }