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:
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
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue