/* Use 2D quad corners to create a matrix that set * a [-1..1] quad at the right position. */ static void v2_quad_corners_to_mat4(float corners[4][2], float r_mat[4][4]) { unit_m4(r_mat); sub_v2_v2v2(r_mat[0], corners[1], corners[0]); sub_v2_v2v2(r_mat[1], corners[3], corners[0]); mul_v2_fl(r_mat[0], 0.5f); mul_v2_fl(r_mat[1], 0.5f); copy_v2_v2(r_mat[3], corners[0]); add_v2_v2(r_mat[3], r_mat[0]); add_v2_v2(r_mat[3], r_mat[1]); }
static int create_primitive_from_points(bContext *C, wmOperator *op, const float (*points)[2], int num_points, char handle_type) { ScrArea *sa = CTX_wm_area(C); Scene *scene = CTX_data_scene(C); Mask *mask; MaskLayer *mask_layer; MaskSpline *new_spline; float scale, location[2], frame_size[2]; int i, width, height; int size = RNA_float_get(op->ptr, "size"); ED_mask_get_size(sa, &width, &height); scale = (float)size / max_ii(width, height); /* Get location in mask space. */ frame_size[0] = width; frame_size[1] = height; RNA_float_get_array(op->ptr, "location", location); location[0] /= width; location[1] /= height; BKE_mask_coord_from_frame(location, location, frame_size); /* Make it so new primitive is centered to mouse location. */ location[0] -= 0.5f * scale; location[1] -= 0.5f * scale; mask_layer = ED_mask_layer_ensure(C); mask = CTX_data_edit_mask(C); ED_mask_select_toggle_all(mask, SEL_DESELECT); new_spline = BKE_mask_spline_add(mask_layer); new_spline->flag = MASK_SPLINE_CYCLIC | SELECT; new_spline->tot_point = num_points; new_spline->points = MEM_recallocN(new_spline->points, sizeof(MaskSplinePoint) * new_spline->tot_point); mask_layer->act_spline = new_spline; mask_layer->act_point = NULL; for (i = 0; i < num_points; i++) { MaskSplinePoint *new_point = &new_spline->points[i]; copy_v2_v2(new_point->bezt.vec[1], points[i]); mul_v2_fl(new_point->bezt.vec[1], scale); add_v2_v2(new_point->bezt.vec[1], location); new_point->bezt.h1 = handle_type; new_point->bezt.h2 = handle_type; BKE_mask_point_select_set(new_point, true); } WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); /* TODO: only update this spline */ BKE_mask_update_display(mask, CFRA); return OPERATOR_FINISHED; }
static bool kdtree2d_isect_tri( struct KDTree2D *tree, const unsigned int ind[3]) { const float *vs[3]; unsigned int i; struct KDRange2D bounds[2] = { {FLT_MAX, -FLT_MAX}, {FLT_MAX, -FLT_MAX}, }; float tri_center[2] = {0.0f, 0.0f}; for (i = 0; i < 3; i++) { vs[i] = tree->coords[ind[i]]; add_v2_v2(tri_center, vs[i]); CLAMP_MAX(bounds[0].min, vs[i][0]); CLAMP_MIN(bounds[0].max, vs[i][0]); CLAMP_MAX(bounds[1].min, vs[i][1]); CLAMP_MIN(bounds[1].max, vs[i][1]); } mul_v2_fl(tri_center, 1.0f / 3.0f); return kdtree2d_isect_tri_recursive(tree, ind, vs, tri_center, bounds, &tree->nodes[tree->root]); }
static void edit_text_cache_populate_select(void *vedata, Object *ob) { EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; const Curve *cu = ob->data; EditFont *ef = cu->editfont; float final_mat[4][4], box[4][2]; struct GPUBatch *geom = DRW_cache_quad_get(); for (int i = 0; i < ef->selboxes_len; i++) { EditFontSelBox *sb = &ef->selboxes[i]; float selboxw; if (i + 1 != ef->selboxes_len) { if (ef->selboxes[i + 1].y == sb->y) { selboxw = ef->selboxes[i + 1].x - sb->x; } else { selboxw = sb->w; } } else { selboxw = sb->w; } /* NOTE: v2_quad_corners_to_mat4 don't need the 3rd corner. */ if (sb->rot == 0.0f) { copy_v2_fl2(box[0], sb->x, sb->y); copy_v2_fl2(box[1], sb->x + selboxw, sb->y); copy_v2_fl2(box[3], sb->x, sb->y + sb->h); } else { float mat[2][2]; angle_to_mat2(mat, sb->rot); copy_v2_fl2(box[0], sb->x, sb->y); mul_v2_v2fl(box[1], mat[0], selboxw); add_v2_v2(box[1], &sb->x); mul_v2_v2fl(box[3], mat[1], sb->h); add_v2_v2(box[3], &sb->x); } v2_quad_corners_to_mat4(box, final_mat); mul_m4_m4m4(final_mat, ob->obmat, final_mat); DRW_shgroup_call_obmat(stl->g_data->overlay_select_shgrp, geom, final_mat); } }
static int paintcurve_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) { PointSlideData *psd = op->customdata; if (event->type == psd->event && event->val == KM_RELEASE) { MEM_freeN(psd); ED_paintcurve_undo_push_begin(op->type->name); ED_paintcurve_undo_push_end(); return OPERATOR_FINISHED; } switch (event->type) { case MOUSEMOVE: { ARegion *ar = CTX_wm_region(C); wmWindow *window = CTX_wm_window(C); float diff[2] = { event->mval[0] - psd->initial_loc[0], event->mval[1] - psd->initial_loc[1]}; if (psd->select == 1) { int i; for (i = 0; i < 3; i++) add_v2_v2v2(psd->pcp->bez.vec[i], diff, psd->point_initial_loc[i]); } else { add_v2_v2(diff, psd->point_initial_loc[psd->select]); copy_v2_v2(psd->pcp->bez.vec[psd->select], diff); if (psd->align) { char opposite = (psd->select == 0) ? 2 : 0; sub_v2_v2v2(diff, psd->pcp->bez.vec[1], psd->pcp->bez.vec[psd->select]); add_v2_v2v2(psd->pcp->bez.vec[opposite], psd->pcp->bez.vec[1], diff); } } WM_paint_cursor_tag_redraw(window, ar); break; } default: break; } return OPERATOR_RUNNING_MODAL; }
/* Get 4x4 transformation matrix which corresponds to * stabilization data and used for easy coordinate * transformation. * * NOTE: The reason it is 4x4 matrix is because it's * used for OpenGL drawing directly. */ void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect, float translation[2], float scale, float angle, float mat[4][4]) { float translation_mat[4][4], rotation_mat[4][4], scale_mat[4][4], center_mat[4][4], inv_center_mat[4][4], aspect_mat[4][4], inv_aspect_mat[4][4]; float scale_vector[3] = {scale, scale, scale}; unit_m4(translation_mat); unit_m4(rotation_mat); unit_m4(scale_mat); unit_m4(center_mat); unit_m4(aspect_mat); /* aspect ratio correction matrix */ aspect_mat[0][0] = 1.0f / aspect; invert_m4_m4(inv_aspect_mat, aspect_mat); /* image center as rotation center * * Rotation matrix is constructing in a way rotation happens around image center, * and it's matter of calculating translation in a way, that applying translation * after rotation would make it so rotation happens around median point of tracks * used for translation stabilization. */ center_mat[3][0] = (float)width / 2.0f; center_mat[3][1] = (float)height / 2.0f; invert_m4_m4(inv_center_mat, center_mat); size_to_mat4(scale_mat, scale_vector); /* scale matrix */ add_v2_v2(translation_mat[3], translation); /* translation matrix */ rotate_m4(rotation_mat, 'Z', angle); /* rotation matrix */ /* compose transformation matrix */ mul_serie_m4(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat, scale_mat, inv_center_mat, NULL); }
static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event) { SlidePointData *data = (SlidePointData *)op->customdata; BezTriple *bezt = &data->point->bezt; float co[2], dco[2]; switch (event->type) { case LEFTALTKEY: case RIGHTALTKEY: case LEFTSHIFTKEY: case RIGHTSHIFTKEY: if (ELEM(event->type, LEFTALTKEY, RIGHTALTKEY)) { if (data->action == SLIDE_ACTION_FEATHER) data->overall_feather = (event->val == KM_PRESS); else data->curvature_only = (event->val == KM_PRESS); } if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) data->accurate = (event->val == KM_PRESS); /* fall-through */ /* update CV position */ case MOUSEMOVE: { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); ED_mask_mouse_pos(sa, ar, event->mval, co); sub_v2_v2v2(dco, co, data->co); if (data->action == SLIDE_ACTION_HANDLE) { float delta[2], offco[2]; sub_v2_v2v2(delta, data->handle, data->co); sub_v2_v2v2(offco, co, data->co); if (data->accurate) mul_v2_fl(offco, 0.2f); add_v2_v2(offco, data->co); add_v2_v2(offco, delta); BKE_mask_point_set_handle(data->point, offco, data->curvature_only, data->handle, data->vec); } else if (data->action == SLIDE_ACTION_POINT) { float delta[2]; copy_v2_v2(delta, dco); if (data->accurate) mul_v2_fl(delta, 0.2f); add_v2_v2v2(bezt->vec[0], data->vec[0], delta); add_v2_v2v2(bezt->vec[1], data->vec[1], delta); add_v2_v2v2(bezt->vec[2], data->vec[2], delta); } else if (data->action == SLIDE_ACTION_FEATHER) { float vec[2], no[2], p[2], c[2], w, offco[2]; float *weight = NULL; float weight_scalar = 1.0f; int overall_feather = data->overall_feather || data->initial_feather; add_v2_v2v2(offco, data->feather, dco); if (data->uw) { /* project on both sides and find the closest one, * prevents flickering when projecting onto both sides can happen */ const float u_pos = BKE_mask_spline_project_co(data->spline, data->point, data->uw->u, offco, MASK_PROJ_NEG); const float u_neg = BKE_mask_spline_project_co(data->spline, data->point, data->uw->u, offco, MASK_PROJ_POS); float dist_pos = FLT_MAX; float dist_neg = FLT_MAX; float co_pos[2]; float co_neg[2]; float u; if (u_pos > 0.0f && u_pos < 1.0f) { BKE_mask_point_segment_co(data->spline, data->point, u_pos, co_pos); dist_pos = len_squared_v2v2(offco, co_pos); } if (u_neg > 0.0f && u_neg < 1.0f) { BKE_mask_point_segment_co(data->spline, data->point, u_neg, co_neg); dist_neg = len_squared_v2v2(offco, co_neg); } u = dist_pos < dist_neg ? u_pos : u_neg; if (u > 0.0f && u < 1.0f) { data->uw->u = u; data->uw = BKE_mask_point_sort_uw(data->point, data->uw); weight = &data->uw->w; weight_scalar = BKE_mask_point_weight_scalar(data->spline, data->point, u); if (weight_scalar != 0.0f) { weight_scalar = 1.0f / weight_scalar; } BKE_mask_point_normal(data->spline, data->point, data->uw->u, no); BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p); } } else { weight = &bezt->weight; /* weight_scalar = 1.0f; keep as is */ copy_v2_v2(no, data->no); copy_v2_v2(p, bezt->vec[1]); } if (weight) { sub_v2_v2v2(c, offco, p); project_v2_v2v2(vec, c, no); w = len_v2(vec); if (overall_feather) { float delta; if (dot_v2v2(no, vec) <= 0.0f) w = -w; delta = w - data->weight * data->weight_scalar; if (data->orig_spline == NULL) { /* restore weight for currently sliding point, so orig_spline would be created * with original weights used */ *weight = data->weight; data->orig_spline = BKE_mask_spline_copy(data->spline); } slide_point_delta_all_feather(data, delta); } else { if (dot_v2v2(no, vec) <= 0.0f) w = 0.0f; if (data->orig_spline) { /* restore possible overall feather changes */ slide_point_restore_spline(data); BKE_mask_spline_free(data->orig_spline); data->orig_spline = NULL; } if (weight_scalar != 0.0f) { *weight = w * weight_scalar; } } } } WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); DAG_id_tag_update(&data->mask->id, 0); break; } case LEFTMOUSE: if (event->val == KM_RELEASE) { Scene *scene = CTX_data_scene(C); /* dont key sliding feather uw's */ if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == FALSE) { if (IS_AUTOKEY_ON(scene)) { ED_mask_layer_shape_auto_key(data->masklay, CFRA); } } WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); DAG_id_tag_update(&data->mask->id, 0); free_slide_point_data(op->customdata); /* keep this last! */ return OPERATOR_FINISHED; } break; case ESCKEY: cancel_slide_point(op->customdata); WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask); DAG_id_tag_update(&data->mask->id, 0); free_slide_point_data(op->customdata); /* keep this last! */ return OPERATOR_CANCELLED; } return OPERATOR_RUNNING_MODAL; }
static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, int width, int height, float zoomx, float zoomy) { float x, y; const int n = 10; int i, j, a; float pos[2], tpos[2], grid[11][11][2]; MovieTracking *tracking = &clip->tracking; bGPdata *gpd = NULL; float aspy = 1.0f / tracking->camera.pixel_aspect; float dx = (float)width / n, dy = (float)height / n * aspy; float offsx = 0.0f, offsy = 0.0f; if (!tracking->camera.focal) return; if ((sc->flag & SC_SHOW_GRID) == 0 && (sc->flag & SC_MANUAL_CALIBRATION) == 0) return; UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y); glPushMatrix(); glTranslatef(x, y, 0); glScalef(zoomx, zoomy, 0); glMultMatrixf(sc->stabmat); glScalef(width, height, 0); /* grid */ if (sc->flag & SC_SHOW_GRID) { float val[4][2], idx[4][2]; float min[2], max[2]; for (a = 0; a < 4; a++) { if (a < 2) val[a][a % 2] = FLT_MAX; else val[a][a % 2] = -FLT_MAX; } zero_v2(pos); for (i = 0; i <= n; i++) { for (j = 0; j <= n; j++) { if (i == 0 || j == 0 || i == n || j == n) { BKE_tracking_distort_v2(tracking, pos, tpos); for (a = 0; a < 4; a++) { int ok; if (a < 2) ok = tpos[a % 2] < val[a][a % 2]; else ok = tpos[a % 2] > val[a][a % 2]; if (ok) { copy_v2_v2(val[a], tpos); idx[a][0] = j; idx[a][1] = i; } } } pos[0] += dx; } pos[0] = 0.0f; pos[1] += dy; } INIT_MINMAX2(min, max); for (a = 0; a < 4; a++) { pos[0] = idx[a][0] * dx; pos[1] = idx[a][1] * dy; BKE_tracking_undistort_v2(tracking, pos, tpos); minmax_v2v2_v2(min, max, tpos); } copy_v2_v2(pos, min); dx = (max[0] - min[0]) / n; dy = (max[1] - min[1]) / n; for (i = 0; i <= n; i++) { for (j = 0; j <= n; j++) { BKE_tracking_distort_v2(tracking, pos, grid[i][j]); grid[i][j][0] /= width; grid[i][j][1] /= height * aspy; pos[0] += dx; } pos[0] = min[0]; pos[1] += dy; } glColor3f(1.0f, 0.0f, 0.0f); for (i = 0; i <= n; i++) { glBegin(GL_LINE_STRIP); for (j = 0; j <= n; j++) { glVertex2fv(grid[i][j]); } glEnd(); } for (j = 0; j <= n; j++) { glBegin(GL_LINE_STRIP); for (i = 0; i <= n; i++) { glVertex2fv(grid[i][j]); } glEnd(); } } if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking); if (track) { int framenr = ED_space_clip_get_clip_frame_number(sc); MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); offsx = marker->pos[0]; offsy = marker->pos[1]; gpd = track->gpd; } } else { gpd = clip->gpd; } if (sc->flag & SC_MANUAL_CALIBRATION && gpd) { bGPDlayer *layer = gpd->layers.first; while (layer) { bGPDframe *frame = layer->frames.first; if (layer->flag & GP_LAYER_HIDE) { layer = layer->next; continue; } glColor4fv(layer->color); glLineWidth(layer->thickness); glPointSize((float)(layer->thickness + 2)); while (frame) { bGPDstroke *stroke = frame->strokes.first; while (stroke) { if (stroke->flag & GP_STROKE_2DSPACE) { if (stroke->totpoints > 1) { glBegin(GL_LINE_STRIP); for (i = 0; i < stroke->totpoints - 1; i++) { float npos[2], dpos[2], len; int steps; pos[0] = (stroke->points[i].x + offsx) * width; pos[1] = (stroke->points[i].y + offsy) * height * aspy; npos[0] = (stroke->points[i + 1].x + offsx) * width; npos[1] = (stroke->points[i + 1].y + offsy) * height * aspy; len = len_v2v2(pos, npos); steps = ceil(len / 5.0f); /* we want to distort only long straight lines */ if (stroke->totpoints == 2) { BKE_tracking_undistort_v2(tracking, pos, pos); BKE_tracking_undistort_v2(tracking, npos, npos); } sub_v2_v2v2(dpos, npos, pos); mul_v2_fl(dpos, 1.0f / steps); for (j = 0; j <= steps; j++) { BKE_tracking_distort_v2(tracking, pos, tpos); glVertex2f(tpos[0] / width, tpos[1] / (height * aspy)); add_v2_v2(pos, dpos); } } glEnd(); } else if (stroke->totpoints == 1) { glBegin(GL_POINTS); glVertex2f(stroke->points[0].x + offsx, stroke->points[0].y + offsy); glEnd(); } } stroke = stroke->next; } frame = frame->next; } layer = layer->next; } glLineWidth(1.0f); glPointSize(1.0f); } glPopMatrix(); }
CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type) { CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); ImBuf *ibuf, *obuf; float mat[4][4], lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4]; float svec[3]= {scale, scale, scale}, loc[2]= {x, y}; unit_m4(rmat); unit_m4(lmat); unit_m4(smat); unit_m4(cmat); /* image center as rotation center */ cmat[3][0]= (float)cbuf->x/2.0f; cmat[3][1]= (float)cbuf->y/2.0f; invert_m4_m4(icmat, cmat); size_to_mat4(smat, svec); /* scale matrix */ add_v2_v2(lmat[3], loc); /* tranlation matrix */ rotate_m4(rmat, 'Z', angle); /* rotation matrix */ /* compose transformation matrix */ mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL); invert_m4(mat); ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); obuf= IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0); if (ibuf && obuf) { int i, j; ibuf->rect_float= cbuf->rect; obuf->rect_float= stackbuf->rect; for (j=0; j<cbuf->y; j++) { for (i=0; i<cbuf->x;i++) { float vec[3]= {i, j, 0}; mul_v3_m4v3(vec, mat, vec); switch(filter_type) { case 0: neareast_interpolation(ibuf, obuf, vec[0], vec[1], i, j); break; case 1: bilinear_interpolation(ibuf, obuf, vec[0], vec[1], i, j); break; case 2: bicubic_interpolation(ibuf, obuf, vec[0], vec[1], i, j); break; } } } IMB_freeImBuf(ibuf); IMB_freeImBuf(obuf); } /* pass on output and free */ return stackbuf; }
static void object_warp_transverts(TransVertStore *tvs, float mat_view[4][4], const float center_view[3], const float angle_, const float min, const float max) { TransVert *tv; int i; const float angle = -angle_; /* cache vars for tiny speedup */ #if 1 const float range = max - min; const float range_inv = 1.0f / range; const float min_ofs = min + (0.5f * range); #endif float dir_min[2], dir_max[2]; float imat_view[4][4]; invert_m4_m4(imat_view, mat_view); /* calculate the direction vectors outside min/max range */ { const float phi = angle * 0.5f; dir_max[0] = cosf(phi); dir_max[1] = sinf(phi); dir_min[0] = -dir_max[0]; dir_min[1] = dir_max[1]; } tv = tvs->transverts; for (i = 0; i < tvs->transverts_tot; i++, tv++) { float co[3], co_add[2]; float val, phi; /* convert objectspace->viewspace */ mul_v3_m4v3(co, mat_view, tv->loc); sub_v2_v2(co, center_view); val = co[0]; /* is overwritten later anyway */ // co[0] = 0.0f; if (val < min) { mul_v2_v2fl(co_add, dir_min, min - val); val = min; } else if (val > max) { mul_v2_v2fl(co_add, dir_max, val - max); val = max; } else { zero_v2(co_add); } /* map from x axis to (-0.5 - 0.5) */ #if 0 val = ((val - min) / (max - min)) - 0.5f; #else val = (val - min_ofs) * range_inv; #endif /* convert the x axis into a rotation */ phi = val * angle; co[0] = -sinf(phi) * co[1]; co[1] = cosf(phi) * co[1]; add_v2_v2(co, co_add); /* convert viewspace->objectspace */ add_v2_v2(co, center_view); mul_v3_m4v3(tv->loc, imat_view, co); } }
/** 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; }
static void setup_vertex_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point, const float point_co[2], const float tangent[2], const float u, MaskSplinePoint *reference_point, const short reference_adjacent, const float view_zoom) { MaskSplinePoint *prev_point = NULL; MaskSplinePoint *next_point = NULL; BezTriple *bezt; float co[3]; const float len = 10.0; /* default length of handle in pixel space */ copy_v2_v2(co, point_co); co[2] = 0.0f; /* point coordinate */ bezt = &new_point->bezt; bezt->h1 = bezt->h2 = HD_ALIGN; if (reference_point) { bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1); } else if (reference_adjacent) { if (spline->tot_point != 1) { int index = (int)(new_point - spline->points); prev_point = &spline->points[(index - 1) % spline->tot_point]; next_point = &spline->points[(index + 1) % spline->tot_point]; bezt->h1 = bezt->h2 = MAX2(prev_point->bezt.h2, next_point->bezt.h1); /* note, we may want to copy other attributes later, radius? pressure? color? */ } } copy_v3_v3(bezt->vec[0], co); copy_v3_v3(bezt->vec[1], co); copy_v3_v3(bezt->vec[2], co); /* initial offset for handles */ if (spline->tot_point == 1) { /* first point of splien is aligned horizontally */ bezt->vec[0][0] -= len * view_zoom; bezt->vec[2][0] += len * view_zoom; } else if (tangent) { float vec[2]; copy_v2_v2(vec, tangent); mul_v2_fl(vec, len); sub_v2_v2(bezt->vec[0], vec); add_v2_v2(bezt->vec[2], vec); if (reference_adjacent) { BKE_mask_calc_handle_adjacent_interp(spline, new_point, u); } } else { /* calculating auto handles works much nicer */ #if 0 /* next points are aligning in the direction of previous/next point */ MaskSplinePoint *point; float v1[2], v2[2], vec[2]; float dir = 1.0f; if (new_point == spline->points) { point = new_point + 1; dir = -1.0f; } else point = new_point - 1; if (spline->tot_point < 3) { v1[0] = point->bezt.vec[1][0] * width; v1[1] = point->bezt.vec[1][1] * height; v2[0] = new_point->bezt.vec[1][0] * width; v2[1] = new_point->bezt.vec[1][1] * height; } else { if (new_point == spline->points) { v1[0] = spline->points[1].bezt.vec[1][0] * width; v1[1] = spline->points[1].bezt.vec[1][1] * height; v2[0] = spline->points[spline->tot_point - 1].bezt.vec[1][0] * width; v2[1] = spline->points[spline->tot_point - 1].bezt.vec[1][1] * height; } else { v1[0] = spline->points[0].bezt.vec[1][0] * width; v1[1] = spline->points[0].bezt.vec[1][1] * height; v2[0] = spline->points[spline->tot_point - 2].bezt.vec[1][0] * width; v2[1] = spline->points[spline->tot_point - 2].bezt.vec[1][1] * height; } } sub_v2_v2v2(vec, v1, v2); mul_v2_fl(vec, len * dir / len_v2(vec)); vec[0] /= width; vec[1] /= height; add_v2_v2(bezt->vec[0], vec); sub_v2_v2(bezt->vec[2], vec); #else BKE_mask_calc_handle_point_auto(spline, new_point, TRUE); BKE_mask_calc_handle_adjacent_interp(spline, new_point, u); #endif } BKE_mask_parent_init(&new_point->parent); /* select new point */ MASKPOINT_SEL_ALL(new_point); ED_mask_select_flush_all(mask); }