From 0e1d4dec7a7d50867c97179299775d31ac30938e Mon Sep 17 00:00:00 2001 From: Antonioya Date: Thu, 15 Aug 2019 17:49:55 +0200 Subject: Fix T68722: Improve Smooth algorithm for Thickness and Strength Now the GPencil smooth algorithm uses a average value instead to use only two points and the interpolated value. Differential Revision: https://developer.blender.org/D5489 --- source/blender/blenkernel/intern/gpencil.c | 119 ++++++++++++++++++-------- source/blender/editors/gpencil/gpencil_edit.c | 4 +- 2 files changed, 83 insertions(+), 40 deletions(-) diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 728f4890189..0354aeaf0ca 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -1784,33 +1784,55 @@ bool BKE_gpencil_smooth_stroke_strength(bGPDstroke *gps, int point_index, float bGPDspoint *ptb = &gps->points[point_index]; /* Do nothing if not enough points */ - if (gps->totpoints <= 2) { + if ((gps->totpoints <= 2) || (point_index < 1)) { return false; } + /* Only affect endpoints by a fraction of the normal influence */ + float inf = influence; + if ((point_index == 0) || (point_index == gps->totpoints - 1)) { + inf *= 0.01f; + } + /* Limit max influence to reduce pop effect. */ + CLAMP_MAX(inf, 0.98f); - /* Compute theoretical optimal value using distances */ - bGPDspoint *pta, *ptc; - int before = point_index - 1; - int after = point_index + 1; + float total = 0.0f; + float max_strength = 0.0f; + const int steps = 4; + const float average_fac = 1.0f / (float)(steps * 2 + 1); + int step; - CLAMP_MIN(before, 0); - CLAMP_MAX(after, gps->totpoints - 1); + /* add the point itself */ + total += ptb->strength * average_fac; + max_strength = ptb->strength; - pta = &gps->points[before]; - ptc = &gps->points[after]; + /* n-steps before/after current point */ + for (step = 1; step <= steps; step++) { + bGPDspoint *pt1, *pt2; + int before = point_index - step; + int after = point_index + step; - /* the optimal value is the corresponding to the interpolation of the strength - * at the distance of point b - */ - float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x); - /* sometimes the factor can be wrong due stroke geometry, so use middle point */ - if ((fac < 0.0f) || (fac > 1.0f)) { - fac = 0.5f; + CLAMP_MIN(before, 0); + CLAMP_MAX(after, gps->totpoints - 1); + + pt1 = &gps->points[before]; + pt2 = &gps->points[after]; + + /* add both these points to the average-sum (s += p[i]/n) */ + total += pt1->strength * average_fac; + total += pt2->strength * average_fac; + /* Save max value. */ + if (max_strength < pt1->strength) { + max_strength = pt1->strength; + } + if (max_strength < pt2->strength) { + max_strength = pt2->strength; + } } - const float optimal = (1.0f - fac) * pta->strength + fac * ptc->strength; - /* Based on influence factor, blend between original and optimal */ - ptb->strength = (1.0f - influence) * ptb->strength + influence * optimal; + /* Based on influence factor, blend between original and optimal smoothed value. */ + ptb->strength = interpf(ptb->strength, total, inf); + /* Clamp to maximum stroke strength to avoid weird results. */ + CLAMP_MAX(ptb->strength, max_strength); return true; } @@ -1825,31 +1847,52 @@ bool BKE_gpencil_smooth_stroke_thickness(bGPDstroke *gps, int point_index, float if ((gps->totpoints <= 2) || (point_index < 1)) { return false; } + /* Only affect endpoints by a fraction of the normal influence */ + float inf = influence; + if ((point_index == 0) || (point_index == gps->totpoints - 1)) { + inf *= 0.01f; + } + /* Limit max influence to reduce pop effect. */ + CLAMP_MAX(inf, 0.98f); - /* Compute theoretical optimal value using distances */ - bGPDspoint *pta, *ptc; - int before = point_index - 1; - int after = point_index + 1; + float total = 0.0f; + float max_pressure = 0.0f; + const int steps = 4; + const float average_fac = 1.0f / (float)(steps * 2 + 1); + int step; - CLAMP_MIN(before, 0); - CLAMP_MAX(after, gps->totpoints - 1); + /* add the point itself */ + total += ptb->pressure * average_fac; + max_pressure = ptb->pressure; - pta = &gps->points[before]; - ptc = &gps->points[after]; + /* n-steps before/after current point */ + for (step = 1; step <= steps; step++) { + bGPDspoint *pt1, *pt2; + int before = point_index - step; + int after = point_index + step; - /* the optimal value is the corresponding to the interpolation of the pressure - * at the distance of point b - */ - float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x); - /* sometimes the factor can be wrong due stroke geometry, so use middle point */ - if ((fac < 0.0f) || (fac > 1.0f)) { - fac = 0.5f; - } - float optimal = interpf(ptc->pressure, pta->pressure, fac); + CLAMP_MIN(before, 0); + CLAMP_MAX(after, gps->totpoints - 1); - /* Based on influence factor, blend between original and optimal */ - ptb->pressure = interpf(optimal, ptb->pressure, influence); + pt1 = &gps->points[before]; + pt2 = &gps->points[after]; + + /* add both these points to the average-sum (s += p[i]/n) */ + total += pt1->pressure * average_fac; + total += pt2->pressure * average_fac; + /* Save max value. */ + if (max_pressure < pt1->pressure) { + max_pressure = pt1->pressure; + } + if (max_pressure < pt2->pressure) { + max_pressure = pt2->pressure; + } + } + /* Based on influence factor, blend between original and optimal smoothed value. */ + ptb->pressure = interpf(ptb->pressure, total, inf); + /* Clamp to maximum stroke thickness to avoid weird results. */ + CLAMP_MAX(ptb->pressure, max_pressure); return true; } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index f509be9312a..878f7a1995b 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -3546,7 +3546,7 @@ static void gp_smooth_stroke(bContext *C, wmOperator *op) } if (smooth_thickness) { /* thickness need to repeat process several times */ - for (int r2 = 0; r2 < r * 10; r2++) { + for (int r2 = 0; r2 < r * 20; r2++) { BKE_gpencil_smooth_stroke_thickness(gps, i, factor); } } @@ -4302,7 +4302,7 @@ void GPENCIL_OT_stroke_smooth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - prop = RNA_def_int(ot->srna, "repeat", 1, 1, 10, "Repeat", "", 1, 5); + prop = RNA_def_int(ot->srna, "repeat", 1, 1, 50, "Repeat", "", 1, 20); RNA_def_property_flag(prop, PROP_SKIP_SAVE); RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 2.0f, "Factor", "", 0.0f, 2.0f); -- cgit v1.2.3