From 151e847b8709c44a731f3d07c9a50139d728e227 Mon Sep 17 00:00:00 2001 From: Falk David Date: Tue, 15 Dec 2020 22:28:28 +0100 Subject: 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 --- .../blender/editors/gpencil/gpencil_interpolate.c | 69 +++++++++++----------- 1 file changed, 34 insertions(+), 35 deletions(-) (limited to 'source/blender/editors/gpencil/gpencil_interpolate.c') diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 3617f20763e..9bca294cf30 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -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,28 +1054,17 @@ 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 */ -- cgit v1.2.3