GPencil: Improve interpolation of strokes with unequal lengths
Use the BKE_gpencil_stroke_uniform_subdivide function to subdivide strokes before interpolation. When the target/source stroke is smaller than the other stroke, it is subdivided until the lengths match. This improves the overall quality of the interpolation of different sized strokes. Before/After video: {F9511779} Reviewed By: #grease_pencil, antoniov, pepeland, mendio Differential Revision: https://developer.blender.org/D9839
This commit is contained in:
parent
5535b0b887
commit
151e847b87
|
@ -283,8 +283,8 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
|
|||
tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer");
|
||||
|
||||
tgpil->gpl = gpl;
|
||||
tgpil->prevFrame = gpl->actframe;
|
||||
tgpil->nextFrame = gpl->actframe->next;
|
||||
tgpil->prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe);
|
||||
tgpil->nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next);
|
||||
|
||||
BLI_addtail(&tgpi->ilayers, tgpil);
|
||||
|
||||
|
@ -326,24 +326,25 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
|
|||
valid = false;
|
||||
}
|
||||
|
||||
/* create new stroke */
|
||||
new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
|
||||
|
||||
if (valid) {
|
||||
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
|
||||
if (gps_from->totpoints > gps_to->totpoints) {
|
||||
new_stroke->points = MEM_recallocN(new_stroke->points,
|
||||
sizeof(*new_stroke->points) * gps_to->totpoints);
|
||||
if (new_stroke->dvert != NULL) {
|
||||
new_stroke->dvert = MEM_recallocN(new_stroke->dvert,
|
||||
sizeof(*new_stroke->dvert) * gps_to->totpoints);
|
||||
}
|
||||
new_stroke->totpoints = gps_to->totpoints;
|
||||
BKE_gpencil_stroke_uniform_subdivide(gpd, gps_to, gps_from->totpoints, true);
|
||||
}
|
||||
/* update points position */
|
||||
if (gps_to->totpoints > gps_from->totpoints) {
|
||||
BKE_gpencil_stroke_uniform_subdivide(gpd, gps_from, gps_to->totpoints, true);
|
||||
}
|
||||
|
||||
/* Create new stroke. */
|
||||
new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
|
||||
|
||||
/* Update points position. */
|
||||
gpencil_interpolate_update_points(gps_from, gps_to, new_stroke, tgpil->factor);
|
||||
}
|
||||
else {
|
||||
/* Create new stroke. */
|
||||
new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
|
||||
|
||||
/* need an empty stroke to keep index correct for lookup, but resize to smallest size */
|
||||
new_stroke->totpoints = 0;
|
||||
new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points));
|
||||
|
@ -443,12 +444,16 @@ static void gpencil_interpolate_exit(bContext *C, wmOperator *op)
|
|||
|
||||
/* finally, free memory used by temp data */
|
||||
LISTBASE_FOREACH (tGPDinterpolate_layer *, tgpil, &tgpi->ilayers) {
|
||||
BKE_gpencil_free_strokes(tgpil->prevFrame);
|
||||
BKE_gpencil_free_strokes(tgpil->nextFrame);
|
||||
BKE_gpencil_free_strokes(tgpil->interFrame);
|
||||
MEM_freeN(tgpil->interFrame);
|
||||
MEM_SAFE_FREE(tgpil->prevFrame);
|
||||
MEM_SAFE_FREE(tgpil->nextFrame);
|
||||
MEM_SAFE_FREE(tgpil->interFrame);
|
||||
}
|
||||
|
||||
BLI_freelistN(&tgpi->ilayers);
|
||||
MEM_freeN(tgpi);
|
||||
MEM_SAFE_FREE(tgpi);
|
||||
}
|
||||
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
|
||||
|
@ -992,8 +997,8 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
/* store extremes */
|
||||
prevFrame = gpl->actframe;
|
||||
nextFrame = gpl->actframe->next;
|
||||
prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe);
|
||||
nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next);
|
||||
|
||||
/* Loop over intermediary frames and create the interpolation */
|
||||
for (cframe = prevFrame->framenum + step; cframe < nextFrame->framenum; cframe += step) {
|
||||
|
@ -1049,27 +1054,16 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
|
|||
interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN;
|
||||
}
|
||||
|
||||
/* create new stroke */
|
||||
bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
|
||||
|
||||
/* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
|
||||
if (gps_from->totpoints > gps_to->totpoints) {
|
||||
/* free weights of removed points */
|
||||
if (new_stroke->dvert != NULL) {
|
||||
BKE_defvert_array_free_elems(new_stroke->dvert + gps_to->totpoints,
|
||||
gps_from->totpoints - gps_to->totpoints);
|
||||
}
|
||||
|
||||
new_stroke->points = MEM_recallocN(new_stroke->points,
|
||||
sizeof(*new_stroke->points) * gps_to->totpoints);
|
||||
|
||||
if (new_stroke->dvert != NULL) {
|
||||
new_stroke->dvert = MEM_recallocN(new_stroke->dvert,
|
||||
sizeof(*new_stroke->dvert) * gps_to->totpoints);
|
||||
}
|
||||
|
||||
new_stroke->totpoints = gps_to->totpoints;
|
||||
BKE_gpencil_stroke_uniform_subdivide(gpd, gps_to, gps_from->totpoints, true);
|
||||
}
|
||||
if (gps_to->totpoints > gps_from->totpoints) {
|
||||
BKE_gpencil_stroke_uniform_subdivide(gpd, gps_from, gps_to->totpoints, true);
|
||||
}
|
||||
|
||||
/* create new stroke */
|
||||
bGPDstroke *new_stroke = BKE_gpencil_stroke_duplicate(gps_from, true, true);
|
||||
|
||||
/* update points position */
|
||||
gpencil_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
|
||||
|
@ -1081,6 +1075,11 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
|
|||
BLI_addtail(&interFrame->strokes, new_stroke);
|
||||
}
|
||||
}
|
||||
|
||||
BKE_gpencil_free_strokes(prevFrame);
|
||||
BKE_gpencil_free_strokes(nextFrame);
|
||||
MEM_SAFE_FREE(prevFrame);
|
||||
MEM_SAFE_FREE(nextFrame);
|
||||
}
|
||||
|
||||
/* notifiers */
|
||||
|
|
Loading…
Reference in New Issue