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
This commit is contained in:
Antonio Vazquez 2019-08-15 17:49:55 +02:00
parent a477c2e0e0
commit 0e1d4dec7a
Notes: blender-bot 2023-02-14 02:41:05 +01:00
Referenced by issue #68767, Crash on loading File
Referenced by issue #68722, GPencil: Improve Smooth algorith for Thickness and Strength
2 changed files with 90 additions and 47 deletions

View File

@ -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;
}
/* Compute theoretical optimal value using distances */
bGPDspoint *pta, *ptc;
int before = point_index - 1;
int after = point_index + 1;
CLAMP_MIN(before, 0);
CLAMP_MAX(after, gps->totpoints - 1);
pta = &gps->points[before];
ptc = &gps->points[after];
/* 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;
/* 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;
}
const float optimal = (1.0f - fac) * pta->strength + fac * ptc->strength;
/* Limit max influence to reduce pop effect. */
CLAMP_MAX(inf, 0.98f);
/* Based on influence factor, blend between original and optimal */
ptb->strength = (1.0f - influence) * ptb->strength + influence * optimal;
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;
/* add the point itself */
total += ptb->strength * average_fac;
max_strength = ptb->strength;
/* 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;
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;
}
}
/* 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;
}
/* Compute theoretical optimal value using distances */
bGPDspoint *pta, *ptc;
int before = point_index - 1;
int after = point_index + 1;
CLAMP_MIN(before, 0);
CLAMP_MAX(after, gps->totpoints - 1);
pta = &gps->points[before];
ptc = &gps->points[after];
/* 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;
/* 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;
}
float optimal = interpf(ptc->pressure, pta->pressure, fac);
/* Limit max influence to reduce pop effect. */
CLAMP_MAX(inf, 0.98f);
/* Based on influence factor, blend between original and optimal */
ptb->pressure = interpf(optimal, ptb->pressure, influence);
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;
/* add the point itself */
total += ptb->pressure * average_fac;
max_pressure = ptb->pressure;
/* 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;
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->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;
}

View File

@ -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);