Commit: 9fa9ee61368860833e535a51aa789ed04fd2db72 Author: Falk David Date: Sat Jul 11 17:00:15 2020 +0200 Branches: soc-2020-greasepencil-curve https://developer.blender.org/rB9fa9ee61368860833e535a51aa789ed04fd2db72
GPencil: Implement editcurve subdivide Implement an algorithm to subdivide an editcurve. =================================================================== M source/blender/blenkernel/BKE_gpencil_curve.h M source/blender/blenkernel/intern/gpencil_curve.c M source/blender/editors/gpencil/gpencil_edit.c =================================================================== diff --git a/source/blender/blenkernel/BKE_gpencil_curve.h b/source/blender/blenkernel/BKE_gpencil_curve.h index f16e8ae7acb..3527d678355 100644 --- a/source/blender/blenkernel/BKE_gpencil_curve.h +++ b/source/blender/blenkernel/BKE_gpencil_curve.h @@ -51,6 +51,7 @@ void BKE_gpencil_stroke_editcurve_sync_selection(struct bGPDstroke *gps, struct void BKE_gpencil_selected_strokes_editcurve_update(struct bGPdata *gpd); void BKE_gpencil_stroke_update_geometry_from_editcurve(struct bGPDstroke *gps); void BKE_gpencil_editcurve_recalculate_handles(struct bGPDstroke *gps); +void BKE_gpencil_editcurve_subdivide(struct bGPDstroke *gps, const int cuts); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c index 4bd3c326a09..3bd60746028 100644 --- a/source/blender/blenkernel/intern/gpencil_curve.c +++ b/source/blender/blenkernel/intern/gpencil_curve.c @@ -852,4 +852,143 @@ void BKE_gpencil_editcurve_recalculate_handles(bGPDstroke *gps) } } +/* Helper: count how many new curve points must be generated. */ +static int gpencil_editcurve_subdivide_count(bGPDcurve *gpc, bool is_cyclic) +{ + int count = 0; + for (int i = 0; i < gpc->tot_curve_points - 1; i++) { + bGPDcurve_point *cpt = &gpc->curve_points[i]; + bGPDcurve_point *cpt_next = &gpc->curve_points[i + 1]; + + if (cpt->flag & GP_CURVE_POINT_SELECT && cpt_next->flag & GP_CURVE_POINT_SELECT) { + count++; + } + } + + if (is_cyclic) { + bGPDcurve_point *cpt = &gpc->curve_points[0]; + bGPDcurve_point *cpt_next = &gpc->curve_points[gpc->tot_curve_points - 1]; + + if (cpt->flag & GP_CURVE_POINT_SELECT && cpt_next->flag & GP_CURVE_POINT_SELECT) { + count++; + } + } + + return count; +} + +static void gpencil_editcurve_subdivide_curve_segment(bGPDcurve_point *cpt_start, + bGPDcurve_point *cpt_end, + bGPDcurve_point *cpt_new) +{ + BezTriple *bezt_start = &cpt_start->bezt; + BezTriple *bezt_end = &cpt_end->bezt; + BezTriple *bezt_new = &cpt_new->bezt; + for (int axis = 0; axis < 3; axis++) { + float p0, p1, p2, p3, m0, m1, q0, q1, b; + p0 = bezt_start->vec[1][axis]; + p1 = bezt_start->vec[2][axis]; + p2 = bezt_end->vec[0][axis]; + p3 = bezt_end->vec[1][axis]; + + m0 = (p0 + p1) / 2; + q0 = (p0 + 2 * p1 + p2) / 4; + b = (p0 + 3 * p1 + 3 * p2 + p3) / 8; + q1 = (p1 + 2 * p2 + p3) / 4; + m1 = (p2 + p3) / 2; + + bezt_new->vec[0][axis] = q0; + bezt_new->vec[2][axis] = q1; + bezt_new->vec[1][axis] = b; + + bezt_start->vec[2][axis] = m0; + bezt_end->vec[0][axis] = m1; + } + + cpt_new->pressure = interpf(cpt_end->pressure, cpt_start->pressure, 0.5f); + cpt_new->strength = interpf(cpt_end->strength, cpt_start->strength, 0.5f); + interp_v4_v4v4(cpt_new->vert_color, cpt_start->vert_color, cpt_end->vert_color, 0.5f); +} + +void BKE_gpencil_editcurve_subdivide(bGPDstroke *gps, const int cuts) +{ + bGPDcurve *gpc = gps->editcurve; + if (gpc == NULL || gpc->tot_curve_points < 2) { + return; + } + bool is_cyclic = gps->flag & GP_STROKE_CYCLIC; + + /* repeat for number of cuts */ + for (int s = 0; s < cuts; s++) { + int old_tot_curve_points = gpc->tot_curve_points; + int new_num_curve_points = gpencil_editcurve_subdivide_count(gpc, is_cyclic); + if (new_num_curve_points == 0) { + break; + } + int new_tot_curve_points = old_tot_curve_points + new_num_curve_points; + + bGPDcurve_point *temp_curve_points = (bGPDcurve_point *)MEM_callocN( + sizeof(bGPDcurve_point) * new_tot_curve_points, __func__); + + bool prev_subdivided = false; + int j = 0; + for (int i = 0; i < old_tot_curve_points - 1; i++, j++) { + bGPDcurve_point *cpt = &gpc->curve_points[i]; + bGPDcurve_point *cpt_next = &gpc->curve_points[i + 1]; + + if (cpt->flag & GP_CURVE_POINT_SELECT && cpt_next->flag & GP_CURVE_POINT_SELECT) { + bGPDcurve_point *cpt_new = &temp_curve_points[j + 1]; + gpencil_editcurve_subdivide_curve_segment(cpt, cpt_next, cpt_new); + + memcpy(&temp_curve_points[j], cpt, sizeof(bGPDcurve_point)); + memcpy(&temp_curve_points[j + 2], cpt_next, sizeof(bGPDcurve_point)); + + cpt_new->flag |= GP_CURVE_POINT_SELECT; + cpt_new->bezt.h1 = HD_ALIGN; + cpt_new->bezt.h2 = HD_ALIGN; + BEZT_SEL_ALL(&cpt_new->bezt); + + prev_subdivided = true; + j++; + } + else if (!prev_subdivided) { + memcpy(&temp_curve_points[j], cpt, sizeof(bGPDcurve_point)); + prev_subdivided = false; + } + else { + prev_subdivided = false; + } + } + + if (is_cyclic) { + bGPDcurve_point *cpt = &gpc->curve_points[old_tot_curve_points - 1]; + bGPDcurve_point *cpt_next = &gpc->curve_points[0]; + + if (cpt->flag & GP_CURVE_POINT_SELECT && cpt_next->flag & GP_CURVE_POINT_SELECT) { + bGPDcurve_point *cpt_new = &temp_curve_points[j + 1]; + gpencil_editcurve_subdivide_curve_segment(cpt, cpt_next, cpt_new); + + memcpy(&temp_curve_points[j], cpt, sizeof(bGPDcurve_point)); + memcpy(&temp_curve_points[0], cpt_next, sizeof(bGPDcurve_point)); + + cpt_new->flag |= GP_CURVE_POINT_SELECT; + cpt_new->bezt.h1 = HD_ALIGN; + cpt_new->bezt.h2 = HD_ALIGN; + BEZT_SEL_ALL(&cpt_new->bezt); + } + else if (!prev_subdivided) { + memcpy(&temp_curve_points[j], cpt, sizeof(bGPDcurve_point)); + } + } + else { + bGPDcurve_point *cpt = &gpc->curve_points[old_tot_curve_points - 1]; + memcpy(&temp_curve_points[j], cpt, sizeof(bGPDcurve_point)); + } + + MEM_freeN(gpc->curve_points); + gpc->curve_points = temp_curve_points; + gpc->tot_curve_points = new_tot_curve_points; + } +} + /** \} */ diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 4375f601db2..51cb9dea743 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -4171,7 +4171,17 @@ static int gpencil_stroke_subdivide_exec(bContext *C, wmOperator *op) bool changed = false; if (is_curve_edit) { - /* TODO: do curve subdivide */ + GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc) + { + if (gpc->flag & GP_CURVE_SELECT) { + BKE_gpencil_editcurve_subdivide(gps, cuts); + BKE_gpencil_editcurve_recalculate_handles(gps); + gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE; + BKE_gpencil_stroke_geometry_update(gpd, gps); + changed = true; + } + } + GP_EDITABLE_CURVES_END(gps_iter); } else { /* Go through each editable + selected stroke */ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs