GPencil: Add skip option to envelope modifier

This patch adds an option to only use every n-th segment of the
envelope result. This can be used to reduce the complexity of the
result.

Differential Revision: http://developer.blender.org/D14503
This commit is contained in:
Henrik Dick 2022-04-07 17:41:49 +02:00
parent 1a09024eac
commit f8c21937d2
4 changed files with 59 additions and 34 deletions

View File

@ -332,18 +332,17 @@ static void add_stroke(Object *ob,
bGPDstroke *gps,
const int point_index,
const int connection_index,
const int size,
const int size2,
const int size1,
const int mat_nr,
const float thickness,
const float strength,
ListBase *results)
{
const int size = size1 + size2;
bGPdata *gpd = ob->data;
bGPDstroke *gps_dst = BKE_gpencil_stroke_new(mat_nr, size, gps->thickness);
const int size1 = size == 4 ? 2 : 1;
const int size2 = size - size1;
memcpy(&gps_dst->points[0], &gps->points[connection_index], size1 * sizeof(bGPDspoint));
memcpy(&gps_dst->points[size1], &gps->points[point_index], size2 * sizeof(bGPDspoint));
@ -369,35 +368,36 @@ static void add_stroke_cyclic(Object *ob,
bGPDstroke *gps,
const int point_index,
const int connection_index,
const int size,
const int mat_nr,
const float thickness,
const float strength,
ListBase *results)
{
bGPdata *gpd = ob->data;
bGPDstroke *gps_dst = BKE_gpencil_stroke_new(mat_nr, 4, gps->thickness);
bGPDstroke *gps_dst = BKE_gpencil_stroke_new(mat_nr, size * 2, gps->thickness);
if (gps->dvert != NULL) {
gps_dst->dvert = MEM_malloc_arrayN(size * 2, sizeof(MDeformVert), __func__);
}
int connection_index2 = (connection_index + 1) % gps->totpoints;
int point_index2 = (point_index + 1) % gps->totpoints;
for (int i = 0; i < size; i++) {
int a = (connection_index + i) % gps->totpoints;
int b = (point_index + i) % gps->totpoints;
gps_dst->points[0] = gps->points[connection_index];
gps_dst->points[1] = gps->points[connection_index2];
gps_dst->points[2] = gps->points[point_index];
gps_dst->points[3] = gps->points[point_index2];
for (int i = 0; i < 4; i++) {
gps_dst->points[i] = gps->points[a];
gps_dst->points[size + i] = gps->points[b];
if (gps->dvert != NULL) {
BKE_defvert_array_copy(&gps_dst->dvert[i], &gps->dvert[a], 1);
BKE_defvert_array_copy(&gps_dst->dvert[size + i], &gps->dvert[b], 1);
}
}
for (int i = 0; i < size * 2; i++) {
gps_dst->points[i].pressure *= thickness;
gps_dst->points[i].strength *= strength;
memset(&gps_dst->points[i].runtime, 0, sizeof(bGPDspoint_Runtime));
}
if (gps->dvert != NULL) {
gps_dst->dvert = MEM_malloc_arrayN(4, sizeof(MDeformVert), __func__);
BKE_defvert_array_copy(&gps_dst->dvert[0], &gps->dvert[connection_index], 1);
BKE_defvert_array_copy(&gps_dst->dvert[1], &gps->dvert[connection_index2], 1);
BKE_defvert_array_copy(&gps_dst->dvert[2], &gps->dvert[point_index], 1);
BKE_defvert_array_copy(&gps_dst->dvert[3], &gps->dvert[point_index2], 1);
}
BLI_addtail(results, gps_dst);
/* Calc geometry data. */
@ -459,31 +459,41 @@ static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gp
const int mat_nr = mmd->mat_nr < 0 ? gps->mat_nr : min_ii(mmd->mat_nr, ob->totcol - 1);
if (mmd->mode == GP_ENVELOPE_FILLS) {
const int skip = min_ii(mmd->skip, min_ii(mmd->spread / 2, gps->totpoints - 2));
if (gps->flag & GP_STROKE_CYCLIC) {
for (int i = 0; i < gps->totpoints; i++) {
const int connection_index = (i + mmd->spread) % gps->totpoints;
add_stroke_cyclic(
ob, gps, i, connection_index, mat_nr, mmd->thickness, mmd->strength, &duplicates);
const int connection_index = (i + mmd->spread - skip) % gps->totpoints;
add_stroke_cyclic(ob,
gps,
i,
connection_index,
2 + skip,
mat_nr,
mmd->thickness,
mmd->strength,
&duplicates);
i += mmd->skip;
}
}
else {
for (int i = 1; i < gps->totpoints - 1 && i < mmd->spread + 1; i++) {
add_stroke(ob, gps, i, 0, 3, mat_nr, mmd->thickness, mmd->strength, &duplicates);
}
for (int i = 0; i < gps->totpoints - 1; i++) {
const int connection_index = min_ii(i + mmd->spread, gps->totpoints - 1);
const int size = i == gps->totpoints - 2 ? 2 :
connection_index < gps->totpoints - 1 ? 4 :
3;
for (int i = -mmd->spread + skip; i < gps->totpoints - 1; i++) {
const int point_index = max_ii(0, i);
const int connection_index = min_ii(i + mmd->spread + 1, gps->totpoints - 1);
const int size1 = min_ii(2 + skip,
min_ii(point_index + 1, gps->totpoints - point_index));
const int size2 = min_ii(
2 + skip, min_ii(connection_index + 1, gps->totpoints - connection_index));
add_stroke(ob,
gps,
i,
connection_index,
size,
point_index,
connection_index + 1 - size2,
size1,
size2,
mat_nr,
mmd->thickness,
mmd->strength,
&duplicates);
i += mmd->skip;
}
}
BLI_remlink(&gpf->strokes, gps);
@ -496,6 +506,7 @@ static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gp
const int connection_index = (i + 1 + mmd->spread) % gps->totpoints;
add_stroke_simple(
ob, gps, i, connection_index, mat_nr, mmd->thickness, mmd->strength, &duplicates);
i += mmd->skip;
}
}
else {
@ -509,6 +520,7 @@ static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gp
mmd->thickness,
mmd->strength,
&duplicates);
i += mmd->skip;
}
}
}
@ -585,6 +597,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
if (mode != GP_ENVELOPE_DEFORM) {
uiItemR(layout, ptr, "strength", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "mat_nr", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "skip", 0, NULL, ICON_NONE);
}
gpencil_modifier_panel_end(layout, ptr);

View File

@ -373,6 +373,7 @@
.mat_nr = -1, \
.thickness = 1.0f, \
.strength = 1.0f, \
.skip = 0, \
}

View File

@ -1168,10 +1168,14 @@ typedef struct EnvelopeGpencilModifierData {
float thickness;
/** Strength multiplier for the new strokes. */
float strength;
/** Number of points to skip over. */
int skip;
/** Custom index for passes. */
int layer_pass;
/* Length of the envelope effect. */
int spread;
char _pad[4];
} EnvelopeGpencilModifierData;
typedef enum eEnvelopeGpencil_Flag {

View File

@ -4126,6 +4126,13 @@ static void rna_def_modifier_gpencilenvelope(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Strength", "Multiplier for the strength of the new strokes");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "skip", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "skip");
RNA_def_property_range(prop, 0, INT_MAX);
RNA_def_property_ui_text(
prop, "Skip Segments", "The number of generated segments to skip to reduce complexity");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ENVELOPE_INVERT_LAYER);
RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");