static void maskrasterize_spline_differentiate_point_outset(float (*diff_feather_points)[2], float (*diff_points)[2], const unsigned int tot_diff_point, const float ofs, const bool do_test) { unsigned int k_prev = tot_diff_point - 2; unsigned int k_curr = tot_diff_point - 1; unsigned int k_next = 0; unsigned int k; float d_prev[2]; float d_next[2]; float d[2]; const float *co_prev; const float *co_curr; const float *co_next; const float ofs_squared = ofs * ofs; co_prev = diff_points[k_prev]; co_curr = diff_points[k_curr]; co_next = diff_points[k_next]; /* precalc */ sub_v2_v2v2(d_prev, co_prev, co_curr); normalize_v2(d_prev); for (k = 0; k < tot_diff_point; k++) { /* co_prev = diff_points[k_prev]; */ /* precalc */ co_curr = diff_points[k_curr]; co_next = diff_points[k_next]; /* sub_v2_v2v2(d_prev, co_prev, co_curr); */ /* precalc */ sub_v2_v2v2(d_next, co_curr, co_next); /* normalize_v2(d_prev); */ /* precalc */ normalize_v2(d_next); if ((do_test == FALSE) || (len_squared_v2v2(diff_feather_points[k], diff_points[k]) < ofs_squared)) { add_v2_v2v2(d, d_prev, d_next); normalize_v2(d); diff_feather_points[k][0] = diff_points[k][0] + ( d[1] * ofs); diff_feather_points[k][1] = diff_points[k][1] + (-d[0] * ofs); } /* use next iter */ copy_v2_v2(d_prev, d_next); /* k_prev = k_curr; */ /* precalc */ k_curr = k_next; k_next++; } }
static void stencil_set_target(StencilControlData *scd) { Brush *br = scd->br; float mdiff[2]; if (scd->mask) { copy_v2_v2(scd->init_sdim, br->mask_stencil_dimension); copy_v2_v2(scd->init_spos, br->mask_stencil_pos); scd->init_rot = br->mask_mtex.rot; scd->dim_target = br->mask_stencil_dimension; scd->rot_target = &br->mask_mtex.rot; scd->pos_target = br->mask_stencil_pos; sub_v2_v2v2(mdiff, scd->init_mouse, br->mask_stencil_pos); } else { copy_v2_v2(scd->init_sdim, br->stencil_dimension); copy_v2_v2(scd->init_spos, br->stencil_pos); scd->init_rot = br->mtex.rot; scd->dim_target = br->stencil_dimension; scd->rot_target = &br->mtex.rot; scd->pos_target = br->stencil_pos; sub_v2_v2v2(mdiff, scd->init_mouse, br->stencil_pos); } scd->lenorig = len_v2(mdiff); scd->init_angle = atan2(mdiff[1], mdiff[0]); }
static bool check_corners(float corners[4][2]) { int i, next, prev; float cross = 0.0f; for (i = 0; i < 4; i++) { float v1[2], v2[2], cur_cross; next = (i + 1) % 4; prev = (4 + i - 1) % 4; sub_v2_v2v2(v1, corners[i], corners[prev]); sub_v2_v2v2(v2, corners[next], corners[i]); cur_cross = cross_v2v2(v1, v2); if (fabsf(cur_cross) <= FLT_EPSILON) { return false; } if (cross == 0.0f) { cross = cur_cross; } else if (cross * cur_cross < 0.0f) { return false; } } return true; }
/* 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 void stencil_control_calculate(StencilControlData *scd, const int mval[2]) { #define PIXEL_MARGIN 5 float mdiff[2]; float mvalf[2] = {mval[0], mval[1]}; switch (scd->mode) { case STENCIL_TRANSLATE: sub_v2_v2v2(mdiff, mvalf, scd->init_mouse); add_v2_v2v2(scd->pos_target, scd->init_spos, mdiff); CLAMP(scd->pos_target[0], -scd->dim_target[0] + PIXEL_MARGIN, scd->area_size[0] + scd->dim_target[0] - PIXEL_MARGIN); CLAMP(scd->pos_target[1], -scd->dim_target[1] + PIXEL_MARGIN, scd->area_size[1] + scd->dim_target[1] - PIXEL_MARGIN); break; case STENCIL_SCALE: { float len, factor; sub_v2_v2v2(mdiff, mvalf, scd->pos_target); len = len_v2(mdiff); factor = len / scd->lenorig; copy_v2_v2(mdiff, scd->init_sdim); if (scd->constrain_mode != STENCIL_CONSTRAINT_Y) mdiff[0] = factor * scd->init_sdim[0]; if (scd->constrain_mode != STENCIL_CONSTRAINT_X) mdiff[1] = factor * scd->init_sdim[1]; CLAMP(mdiff[0], 5.0f, 10000.0f); CLAMP(mdiff[1], 5.0f, 10000.0f); copy_v2_v2(scd->dim_target, mdiff); break; } case STENCIL_ROTATE: { float angle; sub_v2_v2v2(mdiff, mvalf, scd->pos_target); angle = atan2(mdiff[1], mdiff[0]); angle = scd->init_rot + angle - scd->init_angle; if (angle < 0.0f) angle += (float)(2 * M_PI); if (angle > (float)(2 * M_PI)) angle -= (float)(2 * M_PI); *scd->rot_target = angle; break; } } #undef PIXEL_MARGIN }
MINLINE float len_manhattan_v2v2(const float a[2], const float b[2]) { float d[2]; sub_v2_v2v2(d, b, a); return len_manhattan_v2(d); }
/* Project screenspace coordinates to 3D-space * NOTE: We include this as a utility function, since the standard method * involves quite a few steps, which are invariably always the same * for all GPencil operations. So, it's nicer to just centralise these. * WARNING: Assumes that it is getting called in a 3D view only */ bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, Scene *scene, const float screen_co[2], float r_out[3]) { View3D *v3d = gsc->sa->spacedata.first; RegionView3D *rv3d = gsc->ar->regiondata; float *rvec = ED_view3d_cursor3d_get(scene, v3d); float ref[3] = {rvec[0], rvec[1], rvec[2]}; float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL); float mval_f[2], mval_prj[2]; float dvec[3]; copy_v2_v2(mval_f, screen_co); if (ED_view3d_project_float_global(gsc->ar, ref, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { sub_v2_v2v2(mval_f, mval_prj, mval_f); ED_view3d_win_to_delta(gsc->ar, mval_f, dvec, zfac); sub_v3_v3v3(r_out, rvec, dvec); return true; } else { zero_v3(r_out); return false; } }
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) { float d[2]; sub_v2_v2v2(d, b, a); return dot_v2v2(d, d); }
void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist) { if (!equals_v2v2(v2, v1)) { float nor[2]; sub_v2_v2v2(nor, v1, v2); normalize_v2(nor); madd_v2_v2v2fl(v1, v2, nor, dist); } }
static void marker_unified_to_search_pixel(int frame_width, int frame_height, const MovieTrackingMarker *marker, const float marker_unified[2], float search_pixel[2]) { float frame_pixel[2]; float search_origin_frame_pixel[2]; marker_unified_to_frame_pixel_coordinates(frame_width, frame_height, marker, marker_unified, frame_pixel); tracking_get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel); sub_v2_v2v2(search_pixel, frame_pixel, search_origin_frame_pixel); }
/* Calculate stabilization data (translation, scale and rotation) from * given median of first and current frame medians, tracking data and * frame number. * * NOTE: frame number should be in clip space, not scene space */ static void stabilization_calculate_data(MovieTracking *tracking, int framenr, int width, int height, const float firstmedian[2], const float median[2], float translation[2], float *scale, float *angle) { MovieTrackingStabilization *stab = &tracking->stabilization; *scale = (stab->scale - 1.0f) * stab->scaleinf + 1.0f; *angle = 0.0f; translation[0] = (firstmedian[0] - median[0]) * width * (*scale); translation[1] = (firstmedian[1] - median[1]) * height * (*scale); mul_v2_fl(translation, stab->locinf); if ((stab->flag & TRACKING_STABILIZE_ROTATION) && stab->rot_track && stab->rotinf) { MovieTrackingMarker *marker; float a[2], b[2]; float x0 = (float)width / 2.0f, y0 = (float)height / 2.0f; float x = median[0] * width, y = median[1] * height; marker = BKE_tracking_marker_get(stab->rot_track, 1); sub_v2_v2v2(a, marker->pos, firstmedian); a[0] *= width; a[1] *= height; marker = BKE_tracking_marker_get(stab->rot_track, framenr); sub_v2_v2v2(b, marker->pos, median); b[0] *= width; b[1] *= height; *angle = -atan2f(a[0] * b[1] - a[1] * b[0], a[0] * b[0] + a[1] * b[1]); *angle *= stab->rotinf; /* convert to rotation around image center */ translation[0] -= (x0 + (x - x0) * cosf(*angle) - (y - y0) * sinf(*angle) - x) * (*scale); translation[1] -= (y0 + (x - x0) * sinf(*angle) + (y - y0) * cosf(*angle) - y) * (*scale); } }
static void search_pixel_to_marker_unified(int frame_width, int frame_height, const MovieTrackingMarker *marker, const float search_pixel[2], float marker_unified[2]) { float frame_unified[2]; float search_origin_frame_pixel[2]; tracking_get_search_origin_frame_pixel(frame_width, frame_height, marker, search_origin_frame_pixel); add_v2_v2v2(frame_unified, search_pixel, search_origin_frame_pixel); pixel_to_unified(frame_width, frame_height, frame_unified, frame_unified); /* marker pos is in frame unified */ sub_v2_v2v2(marker_unified, frame_unified, marker->pos); }
/** * \return The best angle for fitting the convex hull to an axis aligned bounding box. * * Intended to be used with #BLI_convexhull_2d * * \param points Orded hull points * (result of #BLI_convexhull_2d mapped to a contiguous array). * * \note we could return the index of the best edge too if its needed. */ float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned int n) { unsigned int i, i_prev; float area_best = FLT_MAX; float angle_best = 0.0f; i_prev = n - 1; for (i = 0; i < n; i++) { const float *ev_a = points_hull[i]; const float *ev_b = points_hull[i_prev]; float dvec[2]; sub_v2_v2v2(dvec, ev_a, ev_b); if (normalize_v2(dvec) != 0.0f) { float mat[2][2]; float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX}; unsigned int j; const float angle = atan2f(dvec[0], dvec[1]); float area; angle_to_mat2(mat, angle); for (j = 0; j < n; j++) { float tvec[2]; mul_v2_m2v2(tvec, mat, points_hull[j]); min[0] = min_ff(min[0], tvec[0]); min[1] = min_ff(min[1], tvec[1]); max[0] = max_ff(max[0], tvec[0]); max[1] = max_ff(max[1], tvec[1]); area = (max[0] - min[0]) * (max[1] - min[1]); if (area > area_best) { break; } } if (area < area_best) { area_best = area; angle_best = angle; } } i_prev = i; } return angle_best; }
static void calc_ray_shift(rcti *rect, float x, float y, const float source[2], float ray_length) { float co[2] = {(float)x, (float)y}; float dir[2], dist; /* move (x,y) vector toward the source by ray_length distance */ sub_v2_v2v2(dir, co, source); dist = normalize_v2(dir); mul_v2_fl(dir, min_ff(dist, ray_length)); sub_v2_v2(co, dir); int ico[2] = {(int)co[0], (int)co[1]}; BLI_rcti_do_minmax_v(rect, ico); }
void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_pos[2]) { const float u = 0.5f; const float r = RAKE_THRESHHOLD; float dpos[2]; sub_v2_v2v2(dpos, ups->last_rake, mouse_pos); if (len_squared_v2(dpos) >= r * r) { ups->brush_rotation = atan2(dpos[0], dpos[1]); interp_v2_v2v2(ups->last_rake, ups->last_rake, mouse_pos, u); } }
/** * \return The best angle for fitting the convex hull to an axis aligned bounding box. * * Intended to be used with #BLI_convexhull_2d * * \param points_hull Ordered hull points * (result of #BLI_convexhull_2d mapped to a contiguous array). * * \note we could return the index of the best edge too if its needed. */ float BLI_convexhull_aabb_fit_hull_2d(const float (*points_hull)[2], unsigned int n) { unsigned int i, i_prev; float area_best = FLT_MAX; float dvec_best[2]; /* best angle, delay atan2 */ i_prev = n - 1; for (i = 0; i < n; i++) { const float *ev_a = points_hull[i]; const float *ev_b = points_hull[i_prev]; float dvec[2]; /* 2d rotation matrix */ sub_v2_v2v2(dvec, ev_a, ev_b); if (normalize_v2(dvec) != 0.0f) { /* rotation matrix */ float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX}; unsigned int j; float area; for (j = 0; j < n; j++) { float tvec[2]; mul_v2_v2_cw(tvec, dvec, points_hull[j]); min[0] = min_ff(min[0], tvec[0]); min[1] = min_ff(min[1], tvec[1]); max[0] = max_ff(max[0], tvec[0]); max[1] = max_ff(max[1], tvec[1]); area = (max[0] - min[0]) * (max[1] - min[1]); if (area > area_best) { break; } } if (area < area_best) { area_best = area; copy_v2_v2(dvec_best, dvec); } } i_prev = i; } return (area_best != FLT_MAX) ? atan2f(dvec_best[0], dvec_best[1]) : 0.0f; }
static bool mesh_bisect_interactive_calc( bContext *C, wmOperator *op, BMEditMesh *em, float plane_co[3], float plane_no[3]) { wmGesture *gesture = op->customdata; BisectData *opdata; ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = ar->regiondata; int x_start = RNA_int_get(op->ptr, "xstart"); int y_start = RNA_int_get(op->ptr, "ystart"); int x_end = RNA_int_get(op->ptr, "xend"); int y_end = RNA_int_get(op->ptr, "yend"); /* reference location (some point in front of the view) for finding a point on a plane */ const float *co_ref = rv3d->ofs; float co_a_ss[2] = {x_start, y_start}, co_b_ss[2] = {x_end, y_end}, co_delta_ss[2]; float co_a[3], co_b[3]; const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL); opdata = gesture->userdata; /* view vector */ ED_view3d_win_to_vector(ar, co_a_ss, co_a); /* view delta */ sub_v2_v2v2(co_delta_ss, co_a_ss, co_b_ss); ED_view3d_win_to_delta(ar, co_delta_ss, co_b, zfac); /* cross both to get a normal */ cross_v3_v3v3(plane_no, co_a, co_b); normalize_v3(plane_no); /* not needed but nicer for user */ /* point on plane, can use either start or endpoint */ ED_view3d_win_to_3d(ar, co_ref, co_a_ss, plane_co); if (opdata->is_first == false) EDBM_redo_state_restore(opdata->mesh_backup, em, false); opdata->is_first = false; return true; }
static void getArrowEndPoint(const int width, const int height, const float zoom, const float start_corner[2], const float end_corner[2], float end_point[2]) { float direction[2]; float max_length; sub_v2_v2v2(direction, end_corner, start_corner); direction[0] *= width; direction[1] *= height; max_length = normalize_v2(direction); mul_v2_fl(direction, min_ff(32.0f / zoom, max_length)); direction[0] /= width; direction[1] /= height; add_v2_v2v2(end_point, start_corner, direction); }
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; }
float BLI_dial_angle(Dial *dial, float current_position[2]) { float current_direction[2]; sub_v2_v2v2(current_direction, current_position, dial->center); /* only update when we have enough precision, by having the mouse adequately away from center */ if (len_squared_v2(current_direction) > dial->threshold_squared) { float angle; float cosval, sinval; normalize_v2(current_direction); if (!dial->initialized) { copy_v2_v2(dial->initial_direction, current_direction); dial->initialized = true; } /* calculate mouse angle between initial and final mouse position */ cosval = dot_v2v2(current_direction, dial->initial_direction); sinval = cross_v2v2(current_direction, dial->initial_direction); /* clamp to avoid nans in acos */ angle = atan2f(sinval, cosval); /* change of sign, we passed the 180 degree threshold. This means we need to add a turn. * to distinguish between transition from 0 to -1 and -PI to +PI, use comparison with PI/2 */ if ((angle * dial->last_angle < 0.0f) && (fabsf(dial->last_angle) > (float)M_PI_2)) { if (dial->last_angle < 0.0f) dial->rotations--; else dial->rotations++; } dial->last_angle = angle; return angle + 2.0f * (float)M_PI * dial->rotations; } return dial->last_angle; }
static void tracking_error_segment_point_cb(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, int scene_framenr, float UNUSED(value)) { if (coord == 1) { TrackErrorCurveUserData *data = (TrackErrorCurveUserData *) userdata; float reprojected_position[4], bundle_position[4], marker_position[2], delta[2]; float reprojection_error; float weight = BKE_tracking_track_get_weight_for_marker(data->clip, track, marker); if (!data->matrix_initialized || data->matrix_frame != scene_framenr) { BKE_tracking_get_projection_matrix(data->tracking, data->tracking_object, scene_framenr, data->width, data->height, data->projection_matrix); } copy_v3_v3(bundle_position, track->bundle_pos); bundle_position[3] = 1; mul_v4_m4v4(reprojected_position, data->projection_matrix, bundle_position); reprojected_position[0] = (reprojected_position[0] / (reprojected_position[3] * 2.0f) + 0.5f) * data->width; reprojected_position[1] = (reprojected_position[1] / (reprojected_position[3] * 2.0f) + 0.5f) * data->height * data->aspy; BKE_tracking_distort_v2(data->tracking, reprojected_position, reprojected_position); marker_position[0] = (marker->pos[0] + track->offset[0]) * data->width; marker_position[1] = (marker->pos[1] + track->offset[1]) * data->height * data->aspy; sub_v2_v2v2(delta, reprojected_position, marker_position); reprojection_error = len_v2(delta) * weight; glVertex2f(scene_framenr, reprojection_error); } }
UvVertMap *BKE_mesh_uv_vert_map_create( struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv, unsigned int totpoly, unsigned int totvert, const float limit[2], const bool selected, const bool use_winding) { UvVertMap *vmap; UvMapVert *buf; MPoly *mp; unsigned int a; int i, totuv, nverts; bool *winding = NULL; BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, 32); totuv = 0; /* generate UvMapVert array */ mp = mpoly; for (a = 0; a < totpoly; a++, mp++) if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) totuv += mp->totloop; if (totuv == 0) return NULL; vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap"); buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * (size_t)totuv, "UvMapVert"); vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totvert, "UvMapVert*"); if (use_winding) { winding = MEM_callocN(sizeof(*winding) * totpoly, "winding"); } if (!vmap->vert || !vmap->buf) { BKE_mesh_uv_vert_map_free(vmap); return NULL; } mp = mpoly; for (a = 0; a < totpoly; a++, mp++) { if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) { float (*tf_uv)[2] = NULL; if (use_winding) { tf_uv = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, (size_t)mp->totloop); } nverts = mp->totloop; for (i = 0; i < nverts; i++) { buf->tfindex = (unsigned char)i; buf->f = a; buf->separate = 0; buf->next = vmap->vert[mloop[mp->loopstart + i].v]; vmap->vert[mloop[mp->loopstart + i].v] = buf; if (use_winding) { copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i].uv); } buf++; } if (use_winding) { winding[a] = cross_poly_v2((const float (*)[2])tf_uv, (unsigned int)nverts) > 0; } } } /* sort individual uvs for each vert */ for (a = 0; a < totvert; a++) { UvMapVert *newvlist = NULL, *vlist = vmap->vert[a]; UvMapVert *iterv, *v, *lastv, *next; float *uv, *uv2, uvdiff[2]; while (vlist) { v = vlist; vlist = vlist->next; v->next = newvlist; newvlist = v; uv = mloopuv[mpoly[v->f].loopstart + v->tfindex].uv; lastv = NULL; iterv = vlist; while (iterv) { next = iterv->next; uv2 = mloopuv[mpoly[iterv->f].loopstart + iterv->tfindex].uv; sub_v2_v2v2(uvdiff, uv2, uv); if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] && (!use_winding || winding[iterv->f] == winding[v->f])) { if (lastv) lastv->next = next; else vlist = next; iterv->next = newvlist; newvlist = iterv; } else lastv = iterv; iterv = next; } newvlist->separate = 1; } vmap->vert[a] = newvlist; } if (use_winding) { MEM_freeN(winding); } BLI_buffer_free(&tf_uv_buf); return vmap; }
/* reduced copy of garbled calchandleNurb() code in curve.c */ static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *next, int UNUSED(mode)) { float *p1, *p2, *p3, pt[3]; float len, len_a, len_b; float dvec_a[2], dvec_b[2]; if (bezt->h1 == 0 && bezt->h2 == 0) { return; } p2 = bezt->vec[1]; if (prev == NULL) { p3 = next->vec[1]; pt[0] = 2.0f * p2[0] - p3[0]; pt[1] = 2.0f * p2[1] - p3[1]; p1 = pt; } else { p1 = prev->vec[1]; } if (next == NULL) { p1 = prev->vec[1]; pt[0] = 2.0f * p2[0] - p1[0]; pt[1] = 2.0f * p2[1] - p1[1]; p3 = pt; } else { p3 = next->vec[1]; } sub_v2_v2v2(dvec_a, p2, p1); sub_v2_v2v2(dvec_b, p3, p2); len_a = len_v2(dvec_a); len_b = len_v2(dvec_b); if (len_a == 0.0f) len_a = 1.0f; if (len_b == 0.0f) len_b = 1.0f; if (bezt->h1 == HD_AUTO || bezt->h2 == HD_AUTO) { /* auto */ float tvec[2]; tvec[0] = dvec_b[0] / len_b + dvec_a[0] / len_a; tvec[1] = dvec_b[1] / len_b + dvec_a[1] / len_a; len = len_v2(tvec) * 2.5614f; if (len != 0.0f) { if (bezt->h1 == HD_AUTO) { len_a /= len; madd_v2_v2v2fl(p2 - 3, p2, tvec, -len_a); } if (bezt->h2 == HD_AUTO) { len_b /= len; madd_v2_v2v2fl(p2 + 3, p2, tvec, len_b); } } } if (bezt->h1 == HD_VECT) { /* vector */ madd_v2_v2v2fl(p2 - 3, p2, dvec_a, -1.0f / 3.0f); } if (bezt->h2 == HD_VECT) { madd_v2_v2v2fl(p2 + 3, p2, dvec_b, 1.0f / 3.0f); } }
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; }
bool ED_mask_find_nearest_diff_point(const bContext *C, struct Mask *mask, const float normal_co[2], int threshold, bool feather, MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r, float *u_r, float tangent[2], const bool use_deform, const bool use_project) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); MaskLayer *masklay, *point_masklay; MaskSpline *point_spline; MaskSplinePoint *point = NULL; float dist = FLT_MAX, co[2]; int width, height; float u; float scalex, scaley; ED_mask_get_size(sa, &width, &height); ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley); co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } for (spline = masklay->splines.first; spline; spline = spline->next) { int i; MaskSplinePoint *cur_point; for (i = 0, cur_point = use_deform ? spline->points_deform : spline->points; i < spline->tot_point; i++, cur_point++) { float *diff_points; unsigned int tot_diff_point; diff_points = BKE_mask_point_segment_diff(spline, cur_point, width, height, &tot_diff_point); if (diff_points) { int j, tot_point; unsigned int tot_feather_point; float *feather_points = NULL, *points; if (feather) { feather_points = BKE_mask_point_segment_feather_diff(spline, cur_point, width, height, &tot_feather_point); points = feather_points; tot_point = tot_feather_point; } else { points = diff_points; tot_point = tot_diff_point; } for (j = 0; j < tot_point - 1; j++) { float cur_dist, a[2], b[2]; a[0] = points[2 * j] * scalex; a[1] = points[2 * j + 1] * scaley; b[0] = points[2 * j + 2] * scalex; b[1] = points[2 * j + 3] * scaley; cur_dist = dist_to_line_segment_v2(co, a, b); if (cur_dist < dist) { if (tangent) sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]); point_masklay = masklay; point_spline = spline; point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : cur_point; dist = cur_dist; u = (float)j / tot_point; } } if (feather_points) MEM_freeN(feather_points); MEM_freeN(diff_points); } } } } if (point && dist < threshold) { if (masklay_r) *masklay_r = point_masklay; if (spline_r) *spline_r = point_spline; if (point_r) *point_r = point; if (u_r) { /* TODO(sergey): Projection fails in some weirdo cases.. */ if (use_project) { u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY); } *u_r = u; } return true; } if (masklay_r) *masklay_r = NULL; if (spline_r) *spline_r = NULL; if (point_r) *point_r = NULL; return false; }
static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *arg) { Scene *scene = CTX_data_scene(C); UnitSettings *unit = &scene->unit; RulerItem *ruler_item; RulerInfo *ruler_info = arg; RegionView3D *rv3d = ruler_info->ar->regiondata; // ARegion *ar = ruler_info->ar; const float cap_size = 4.0f; const float bg_margin = 4.0f * U.pixelsize; const float bg_radius = 4.0f * U.pixelsize; const float arc_size = 64.0f * U.pixelsize; #define ARC_STEPS 24 const int arc_steps = ARC_STEPS; int i; //unsigned int color_act = 0x666600; unsigned int color_act = 0xffffff; unsigned int color_base = 0x0; unsigned char color_back[4] = {0xff, 0xff, 0xff, 0x80}; unsigned char color_text[3]; unsigned char color_wire[3]; /* anti-aliased lines for more consistent appearance */ glEnable(GL_LINE_SMOOTH); BLF_enable(blf_mono_font, BLF_ROTATION); BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi); BLF_rotation(blf_mono_font, 0.0f); UI_GetThemeColor3ubv(TH_TEXT, color_text); UI_GetThemeColor3ubv(TH_WIRE, color_wire); for (ruler_item = ruler_info->items.first, i = 0; ruler_item; ruler_item = ruler_item->next, i++) { const bool is_act = (i == ruler_info->item_active); float dir_ruler[2]; float co_ss[3][2]; int j; /* should these be checked? - ok for now not to */ for (j = 0; j < 3; j++) { ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP); } glEnable(GL_BLEND); cpack(is_act ? color_act : color_base); if (ruler_item->flag & RULERITEM_USE_ANGLE) { glBegin(GL_LINE_STRIP); for (j = 0; j < 3; j++) { glVertex2fv(co_ss[j]); } glEnd(); cpack(0xaaaaaa); setlinestyle(3); glBegin(GL_LINE_STRIP); for (j = 0; j < 3; j++) { glVertex2fv(co_ss[j]); } glEnd(); setlinestyle(0); /* arc */ { float dir_tmp[3]; float co_tmp[3]; float arc_ss_coords[ARC_STEPS + 1][2]; float dir_a[3]; float dir_b[3]; float quat[4]; float axis[3]; float angle; const float px_scale = (ED_view3d_pixel_size(rv3d, ruler_item->co[1]) * min_fff(arc_size, len_v2v2(co_ss[0], co_ss[1]) / 2.0f, len_v2v2(co_ss[2], co_ss[1]) / 2.0f)); sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]); sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]); normalize_v3(dir_a); normalize_v3(dir_b); cross_v3_v3v3(axis, dir_a, dir_b); angle = angle_normalized_v3v3(dir_a, dir_b); axis_angle_to_quat(quat, axis, angle / arc_steps); copy_v3_v3(dir_tmp, dir_a); glColor3ubv(color_wire); for (j = 0; j <= arc_steps; j++) { madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale); ED_view3d_project_float_global(ar, co_tmp, arc_ss_coords[j], V3D_PROJ_TEST_NOP); mul_qt_v3(quat, dir_tmp); } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, arc_ss_coords); glDrawArrays(GL_LINE_STRIP, 0, arc_steps + 1); glDisableClientState(GL_VERTEX_ARRAY); } /* text */ { char numstr[256]; float numstr_size[2]; float pos[2]; const int prec = 2; /* XXX, todo, make optional */ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); pos[0] = co_ss[1][0] + (cap_size * 2.0f); pos[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); /* draw text (bg) */ glColor4ubv(color_back); uiSetRoundBox(UI_CNR_ALL); uiRoundBox(pos[0] - bg_margin, pos[1] - bg_margin, pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1], bg_radius); /* draw text */ glColor3ubv(color_text); BLF_position(blf_mono_font, pos[0], pos[1], 0.0f); BLF_rotation(blf_mono_font, 0.0f); BLF_draw(blf_mono_font, numstr, sizeof(numstr)); } /* capping */ { float rot_90_vec_a[2]; float rot_90_vec_b[2]; float cap[2]; sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]); rot_90_vec_a[0] = -dir_ruler[1]; rot_90_vec_a[1] = dir_ruler[0]; normalize_v2(rot_90_vec_a); sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]); rot_90_vec_b[0] = -dir_ruler[1]; rot_90_vec_b[1] = dir_ruler[0]; normalize_v2(rot_90_vec_b); glEnable(GL_BLEND); glColor3ubv(color_wire); glBegin(GL_LINES); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size); glVertex2fv(cap); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size); glVertex2fv(cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size); glVertex2fv(cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size); glVertex2fv(cap); /* angle vertex */ glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); glEnd(); glDisable(GL_BLEND); } } else { glBegin(GL_LINE_STRIP); for (j = 0; j < 3; j += 2) { glVertex2fv(co_ss[j]); } glEnd(); cpack(0xaaaaaa); setlinestyle(3); glBegin(GL_LINE_STRIP); for (j = 0; j < 3; j += 2) { glVertex2fv(co_ss[j]); } glEnd(); setlinestyle(0); sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); /* text */ { char numstr[256]; float numstr_size[2]; const int prec = 6; /* XXX, todo, make optional */ float pos[2]; ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); mid_v2_v2v2(pos, co_ss[0], co_ss[2]); /* center text */ pos[0] -= numstr_size[0] / 2.0f; pos[1] -= numstr_size[1] / 2.0f; /* draw text (bg) */ glColor4ubv(color_back); uiSetRoundBox(UI_CNR_ALL); uiRoundBox(pos[0] - bg_margin, pos[1] - bg_margin, pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1], bg_radius); /* draw text */ glColor3ubv(color_text); BLF_position(blf_mono_font, pos[0], pos[1], 0.0f); BLF_draw(blf_mono_font, numstr, sizeof(numstr)); } /* capping */ { float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]}; float cap[2]; normalize_v2(rot_90_vec); glEnable(GL_BLEND); glColor3ubv(color_wire); glBegin(GL_LINES); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size); glVertex2fv(cap); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size); glVertex2fv(cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size); glVertex2fv(cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size); glVertex2fv(cap); glEnd(); glDisable(GL_BLEND); } } } glDisable(GL_LINE_SMOOTH); BLF_disable(blf_mono_font, BLF_ROTATION); #undef ARC_STEPS /* draw snap */ if ((ruler_info->snap_flag & RULER_SNAP_OK) && (ruler_info->state == RULER_STATE_DRAG)) { ruler_item = ruler_item_active_get(ruler_info); if (ruler_item) { /* size from drawSnapping */ const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); float co_ss[3]; ED_view3d_project_float_global(ar, ruler_item->co[ruler_item->co_index], co_ss, V3D_PROJ_TEST_NOP); cpack(color_act); circ(co_ss[0], co_ss[1], size * U.pixelsize); } } }
static void setNearestAxis3d(TransInfo *t) { float zfac; float mvec[3], proj[3]; float len[3]; int i; /* calculate mouse movement */ mvec[0] = (float)(t->mval[0] - t->con.imval[0]); mvec[1] = (float)(t->mval[1] - t->con.imval[1]); mvec[2] = 0.0f; /* we need to correct axis length for the current zoomlevel of view, * this to prevent projected values to be clipped behind the camera * and to overflow the short integers. * The formula used is a bit stupid, just a simplification of the subtraction * of two 2D points 30 pixels apart (that's the last factor in the formula) after * projecting them with ED_view3d_win_to_delta and then get the length of that vector. */ zfac = mul_project_m4_v3_zfac(t->persmat, t->center); zfac = len_v3(t->persinv[0]) * 2.0f / t->ar->winx * zfac * 30.0f; for (i = 0; i < 3; i++) { float axis[3], axis_2d[2]; copy_v3_v3(axis, t->con.mtx[i]); mul_v3_fl(axis, zfac); /* now we can project to get window coordinate */ add_v3_v3(axis, t->center_global); projectFloatView(t, axis, axis_2d); sub_v2_v2v2(axis, axis_2d, t->center2d); axis[2] = 0.0f; if (normalize_v3(axis) > 1e-3f) { project_v3_v3v3(proj, mvec, axis); sub_v3_v3v3(axis, mvec, proj); len[i] = normalize_v3(axis); } else { len[i] = 1e10f; } } if (len[0] <= len[1] && len[0] <= len[2]) { if (t->modifiers & MOD_CONSTRAINT_PLANE) { t->con.mode |= (CON_AXIS1 | CON_AXIS2); BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s X axis"), t->spacename); } else { t->con.mode |= CON_AXIS0; BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s X axis"), t->spacename); } } else if (len[1] <= len[0] && len[1] <= len[2]) { if (t->modifiers & MOD_CONSTRAINT_PLANE) { t->con.mode |= (CON_AXIS0 | CON_AXIS2); BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Y axis"), t->spacename); } else { t->con.mode |= CON_AXIS1; BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Y axis"), t->spacename); } } else if (len[2] <= len[1] && len[2] <= len[0]) { if (t->modifiers & MOD_CONSTRAINT_PLANE) { t->con.mode |= (CON_AXIS0 | CON_AXIS1); BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Z axis"), t->spacename); } else { t->con.mode |= CON_AXIS2; BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Z axis"), t->spacename); } } }
static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, const float marker_pos[2], int width, int height, int act, int sel) { int tiny = sc->flag & SC_SHOW_TINY_MARKER; bool show_search = false; float col[3], scol[3], px[2]; track_colors(track, act, col, scol); px[0] = 1.0f / width / sc->zoom; px[1] = 1.0f / height / sc->zoom; /* marker position and offset position */ if ((track->flag & SELECT) == sel && (marker->flag & MARKER_DISABLED) == 0) { float pos[2], p[2]; if (track->flag & TRACK_LOCKED) { if (act) UI_ThemeColor(TH_ACT_MARKER); else if (track->flag & SELECT) UI_ThemeColorShade(TH_LOCK_MARKER, 64); else UI_ThemeColor(TH_LOCK_MARKER); } else { if (track->flag & SELECT) glColor3fv(scol); else glColor3fv(col); } add_v2_v2v2(pos, marker->pos, track->offset); ED_clip_point_undistorted_pos(sc, pos, pos); sub_v2_v2v2(p, pos, marker_pos); if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1], marker->pattern_corners[2], marker->pattern_corners[3])) { if (!tiny) glPointSize(2.0f); glBegin(GL_POINTS); glVertex2f(pos[0], pos[1]); glEnd(); if (!tiny) glPointSize(1.0f); } else { glBegin(GL_LINES); glVertex2f(pos[0] + px[0] * 3, pos[1]); glVertex2f(pos[0] + px[0] * 7, pos[1]); glVertex2f(pos[0] - px[0] * 3, pos[1]); glVertex2f(pos[0] - px[0] * 7, pos[1]); glVertex2f(pos[0], pos[1] - px[1] * 3); glVertex2f(pos[0], pos[1] - px[1] * 7); glVertex2f(pos[0], pos[1] + px[1] * 3); glVertex2f(pos[0], pos[1] + px[1] * 7); glEnd(); glColor3f(0.0f, 0.0f, 0.0f); glLineStipple(3, 0xaaaa); glEnable(GL_LINE_STIPPLE); glEnable(GL_COLOR_LOGIC_OP); glLogicOp(GL_NOR); glBegin(GL_LINES); glVertex2fv(pos); glVertex2fv(marker_pos); glEnd(); glDisable(GL_COLOR_LOGIC_OP); glDisable(GL_LINE_STIPPLE); } } /* pattern */ glPushMatrix(); glTranslatef(marker_pos[0], marker_pos[1], 0); if (tiny) { glLineStipple(3, 0xaaaa); glEnable(GL_LINE_STIPPLE); } if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) { if (track->flag & TRACK_LOCKED) { if (act) UI_ThemeColor(TH_ACT_MARKER); else if (track->pat_flag & SELECT) UI_ThemeColorShade(TH_LOCK_MARKER, 64); else UI_ThemeColor(TH_LOCK_MARKER); } else if (marker->flag & MARKER_DISABLED) { if (act) UI_ThemeColor(TH_ACT_MARKER); else if (track->pat_flag & SELECT) UI_ThemeColorShade(TH_DIS_MARKER, 128); else UI_ThemeColor(TH_DIS_MARKER); } else { if (track->pat_flag & SELECT) glColor3fv(scol); else glColor3fv(col); } glBegin(GL_LINE_LOOP); glVertex2fv(marker->pattern_corners[0]); glVertex2fv(marker->pattern_corners[1]); glVertex2fv(marker->pattern_corners[2]); glVertex2fv(marker->pattern_corners[3]); glEnd(); } /* search */ show_search = (TRACK_VIEW_SELECTED(sc, track) && ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0; if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) { if (track->flag & TRACK_LOCKED) { if (act) UI_ThemeColor(TH_ACT_MARKER); else if (track->search_flag & SELECT) UI_ThemeColorShade(TH_LOCK_MARKER, 64); else UI_ThemeColor(TH_LOCK_MARKER); } else if (marker->flag & MARKER_DISABLED) { if (act) UI_ThemeColor(TH_ACT_MARKER); else if (track->search_flag & SELECT) UI_ThemeColorShade(TH_DIS_MARKER, 128); else UI_ThemeColor(TH_DIS_MARKER); } else { if (track->search_flag & SELECT) glColor3fv(scol); else glColor3fv(col); } glBegin(GL_LINE_LOOP); glVertex2f(marker->search_min[0], marker->search_min[1]); glVertex2f(marker->search_max[0], marker->search_min[1]); glVertex2f(marker->search_max[0], marker->search_max[1]); glVertex2f(marker->search_min[0], marker->search_max[1]); glEnd(); } if (tiny) glDisable(GL_LINE_STIPPLE); glPopMatrix(); }
static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker, const float marker_pos[2], int width, int height) { int tiny = sc->flag & SC_SHOW_TINY_MARKER; bool show_search = false; float px[2]; UI_ThemeColor(TH_MARKER_OUTLINE); px[0] = 1.0f / width / sc->zoom; px[1] = 1.0f / height / sc->zoom; if ((marker->flag & MARKER_DISABLED) == 0) { float pos[2]; float p[2]; add_v2_v2v2(pos, marker->pos, track->offset); ED_clip_point_undistorted_pos(sc, pos, pos); sub_v2_v2v2(p, pos, marker_pos); if (isect_point_quad_v2(p, marker->pattern_corners[0], marker->pattern_corners[1], marker->pattern_corners[2], marker->pattern_corners[3])) { if (tiny) glPointSize(3.0f); else glPointSize(4.0f); glBegin(GL_POINTS); glVertex2f(pos[0], pos[1]); glEnd(); glPointSize(1.0f); } else { if (!tiny) glLineWidth(3.0f); glBegin(GL_LINES); glVertex2f(pos[0] + px[0] * 2, pos[1]); glVertex2f(pos[0] + px[0] * 8, pos[1]); glVertex2f(pos[0] - px[0] * 2, pos[1]); glVertex2f(pos[0] - px[0] * 8, pos[1]); glVertex2f(pos[0], pos[1] - px[1] * 2); glVertex2f(pos[0], pos[1] - px[1] * 8); glVertex2f(pos[0], pos[1] + px[1] * 2); glVertex2f(pos[0], pos[1] + px[1] * 8); glEnd(); if (!tiny) glLineWidth(1.0f); } } /* pattern and search outline */ glPushMatrix(); glTranslatef(marker_pos[0], marker_pos[1], 0); if (!tiny) glLineWidth(3.0f); if (sc->flag & SC_SHOW_MARKER_PATTERN) { glBegin(GL_LINE_LOOP); glVertex2fv(marker->pattern_corners[0]); glVertex2fv(marker->pattern_corners[1]); glVertex2fv(marker->pattern_corners[2]); glVertex2fv(marker->pattern_corners[3]); glEnd(); } show_search = (TRACK_VIEW_SELECTED(sc, track) && ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0; if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) { glBegin(GL_LINE_LOOP); glVertex2f(marker->search_min[0], marker->search_min[1]); glVertex2f(marker->search_max[0], marker->search_min[1]); glVertex2f(marker->search_max[0], marker->search_max[1]); glVertex2f(marker->search_min[0], marker->search_max[1]); glEnd(); } glPopMatrix(); if (!tiny) glLineWidth(1.0f); }
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(); }