/* *** mask point functions which involve evaluation *** */ float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, int width, int height, unsigned int *tot_feather_point) { float *feather, *fp; unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height); unsigned int i; feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points"); for (i = 0; i < resol; i++, fp += 2) { float u = (float)(i % resol) / resol, weight; float co[2], n[2]; BKE_mask_point_segment_co(spline, point, u, co); BKE_mask_point_normal(spline, point, u, n); weight = BKE_mask_point_weight(spline, point, u); fp[0] = co[0] + n[0] * weight; fp[1] = co[1] + n[1] * weight; } *tot_feather_point = resol; return feather; }
float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); int i, tot = 0; float (*feather)[2], (*fp)[2]; /* count */ for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &points_array[i]; tot += point->tot_uw + 1; } /* create data */ feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points"); for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &points_array[i]; BezTriple *bezt = &point->bezt; float weight, n[2]; int j; BKE_mask_point_normal(spline, point, 0.0f, n); weight = BKE_mask_point_weight(spline, point, 0.0f); madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight); fp++; for (j = 0; j < point->tot_uw; j++) { float u = point->uw[j].u; float co[2]; BKE_mask_point_segment_co(spline, point, u, co); BKE_mask_point_normal(spline, point, u, n); weight = BKE_mask_point_weight(spline, point, u); madd_v2_v2v2fl(*fp, co, n, weight); fp++; } } *tot_feather_point = tot; return feather; }
static int add_feather_vertex_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; MaskSpline *spline; MaskSplinePoint *point = NULL; const float threshold = 9; float co[2], u; RNA_float_get_array(op->ptr, "location", co); point = ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL); if (point) return OPERATOR_FINISHED; if (ED_mask_find_nearest_diff_point(C, mask, co, threshold, true, NULL, true, true, &masklay, &spline, &point, &u, NULL)) { Scene *scene = CTX_data_scene(C); float w = BKE_mask_point_weight(spline, point, u); float weight_scalar = BKE_mask_point_weight_scalar(spline, point, u); if (weight_scalar != 0.0f) { w = w / weight_scalar; } BKE_mask_point_add_uw(point, u, w); BKE_mask_update_display(mask, scene->r.cfra); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); DAG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } return OPERATOR_CANCELLED; }
/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution() ! */ static float (*mask_spline_feather_differentiated_points_with_resolution__double( MaskSpline *spline, unsigned int *tot_feather_point, const unsigned int resol, const bool do_feather_isect))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); MaskSplinePoint *point_curr, *point_prev; float (*feather)[2], (*fp)[2]; const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); int a; if (spline->tot_point <= 1) { /* nothing to differentiate */ *tot_feather_point = 0; return NULL; } /* len+1 because of 'forward_diff_bezier' function */ *tot_feather_point = tot; feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline vets"); a = spline->tot_point - 1; if (spline->flag & MASK_SPLINE_CYCLIC) a++; point_prev = points_array; point_curr = point_prev + 1; while (a--) { BezTriple local_prevbezt; BezTriple local_bezt; float point_prev_n[2], point_curr_n[2], tvec[2]; float weight_prev, weight_curr; float len_base, len_feather, len_scalar; BezTriple *bezt_prev; BezTriple *bezt_curr; int j; if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) point_curr = points_array; bezt_prev = &point_prev->bezt; bezt_curr = &point_curr->bezt; /* modified copy for feather */ local_prevbezt = *bezt_prev; local_bezt = *bezt_curr; bezt_prev = &local_prevbezt; bezt_curr = &local_bezt; /* calc the normals */ sub_v2_v2v2(tvec, bezt_prev->vec[1], bezt_prev->vec[0]); normalize_v2(tvec); point_prev_n[0] = -tvec[1]; point_prev_n[1] = tvec[0]; sub_v2_v2v2(tvec, bezt_curr->vec[1], bezt_curr->vec[0]); normalize_v2(tvec); point_curr_n[0] = -tvec[1]; point_curr_n[1] = tvec[0]; weight_prev = bezt_prev->weight; weight_curr = bezt_curr->weight; mul_v2_fl(point_prev_n, weight_prev); mul_v2_fl(point_curr_n, weight_curr); /* before we transform verts */ len_base = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]); // add_v2_v2(bezt_prev->vec[0], point_prev_n); // not needed add_v2_v2(bezt_prev->vec[1], point_prev_n); add_v2_v2(bezt_prev->vec[2], point_prev_n); add_v2_v2(bezt_curr->vec[0], point_curr_n); add_v2_v2(bezt_curr->vec[1], point_curr_n); // add_v2_v2(bezt_curr->vec[2], point_curr_n); // not needed len_feather = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]); /* scale by chane in length */ len_scalar = len_feather / len_base; dist_ensure_v2_v2fl(bezt_prev->vec[2], bezt_prev->vec[1], len_scalar * len_v2v2(bezt_prev->vec[2], bezt_prev->vec[1])); dist_ensure_v2_v2fl(bezt_curr->vec[0], bezt_curr->vec[1], len_scalar * len_v2v2(bezt_curr->vec[0], bezt_curr->vec[1])); for (j = 0; j < 2; j++) { BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], bezt_prev->vec[2][j], bezt_curr->vec[0][j], bezt_curr->vec[1][j], &(*fp)[j], resol, 2 * sizeof(float)); } /* scale by the uw's */ if (point_prev->tot_uw) { for (j = 0; j < resol; j++, fp++) { float u = (float) j / resol; float weight_uw, weight_scalar; float co[2]; /* TODO - these calls all calculate similar things * could be unified for some speed */ BKE_mask_point_segment_co(spline, point_prev, u, co); weight_uw = BKE_mask_point_weight(spline, point_prev, u); weight_scalar = BKE_mask_point_weight_scalar(spline, point_prev, u); dist_ensure_v2_v2fl(*fp, co, len_v2v2(*fp, co) * (weight_uw / weight_scalar)); } } else { fp += resol; } if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { copy_v2_v2(*fp, bezt_curr->vec[1]); } point_prev = point_curr; point_curr++; } if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) { BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot); } return feather; }
/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution() ! */ static float (*mask_spline_feather_differentiated_points_with_resolution__even( MaskSpline *spline, unsigned int *tot_feather_point, const unsigned int resol, const bool do_feather_isect))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); MaskSplinePoint *point_curr, *point_prev; float (*feather)[2], (*fp)[2]; const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); int a; /* tot+1 because of 'forward_diff_bezier' function */ feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline feather diff points"); a = spline->tot_point - 1; if (spline->flag & MASK_SPLINE_CYCLIC) a++; point_prev = points_array; point_curr = point_prev + 1; while (a--) { /* BezTriple *bezt_prev; */ /* UNUSED */ /* BezTriple *bezt_curr; */ /* UNUSED */ int j; if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) point_curr = points_array; /* bezt_prev = &point_prev->bezt; */ /* bezt_curr = &point_curr->bezt; */ for (j = 0; j < resol; j++, fp++) { float u = (float) j / resol, weight; float co[2], n[2]; /* TODO - these calls all calculate similar things * could be unified for some speed */ BKE_mask_point_segment_co(spline, point_prev, u, co); BKE_mask_point_normal(spline, point_prev, u, n); weight = BKE_mask_point_weight(spline, point_prev, u); madd_v2_v2v2fl(*fp, co, n, weight); } if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { float u = 1.0f, weight; float co[2], n[2]; BKE_mask_point_segment_co(spline, point_prev, u, co); BKE_mask_point_normal(spline, point_prev, u, n); weight = BKE_mask_point_weight(spline, point_prev, u); madd_v2_v2v2fl(*fp, co, n, weight); } point_prev = point_curr; point_curr++; } *tot_feather_point = tot; if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) { BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot); } return feather; }