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; }
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 int slide_plane_marker_modal(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); SlidePlaneMarkerData *data = (SlidePlaneMarkerData *) op->customdata; float dx, dy, mdelta[2]; int next_corner_index, prev_corner_index, diag_corner_index; const float *next_corner, *prev_corner, *diag_corner; float next_edge[2], prev_edge[2], next_diag_edge[2], prev_diag_edge[2]; switch (event->type) { case LEFTCTRLKEY: case RIGHTCTRLKEY: case LEFTSHIFTKEY: case RIGHTSHIFTKEY: if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) { data->accurate = event->val == KM_PRESS; } /* fall-through */ case MOUSEMOVE: mdelta[0] = event->mval[0] - data->previous_mval[0]; mdelta[1] = event->mval[1] - data->previous_mval[1]; dx = mdelta[0] / data->width / sc->zoom; dy = mdelta[1] / data->height / sc->zoom; if (data->accurate) { dx /= 5.0f; dy /= 5.0f; } data->corner[0] = data->previous_corner[0] + dx; data->corner[1] = data->previous_corner[1] + dy; /* prev_edge (Corner 3, current) <----------------------- (Corner 2, previous) | ^ | | | | | | next_edge | | next_diag_edge | | | | | | v | (Corner 0, next) -----------------------> (Corner 1, diagonal) prev_diag_edge */ next_corner_index = (data->corner_index + 1) % 4; prev_corner_index = (data->corner_index + 3) % 4; diag_corner_index = (data->corner_index + 2) % 4; next_corner = data->plane_marker->corners[next_corner_index]; prev_corner = data->plane_marker->corners[prev_corner_index]; diag_corner = data->plane_marker->corners[diag_corner_index]; sub_v2_v2v2(next_edge, next_corner, data->corner); sub_v2_v2v2(prev_edge, data->corner, prev_corner); sub_v2_v2v2(next_diag_edge, prev_corner, diag_corner); sub_v2_v2v2(prev_diag_edge, diag_corner, next_corner); if (cross_v2v2(prev_edge, next_edge) < 0.0f) { closest_to_line_v2(data->corner, data->corner, prev_corner, next_corner); } if (cross_v2v2(next_diag_edge, prev_edge) < 0.0f) { closest_to_line_v2(data->corner, data->corner, prev_corner, diag_corner); } if (cross_v2v2(next_edge, prev_diag_edge) < 0.0f) { closest_to_line_v2(data->corner, data->corner, next_corner, diag_corner); } data->previous_mval[0] = event->mval[0]; data->previous_mval[1] = event->mval[1]; copy_v2_v2(data->previous_corner, data->corner); DAG_id_tag_update(&sc->clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL); break; case LEFTMOUSE: case RIGHTMOUSE: if (event->type == data->event_type && event->val == KM_RELEASE) { /* Marker is now keyframed. */ data->plane_marker->flag &= ~PLANE_MARKER_TRACKED; slide_plane_marker_update_homographies(sc, data); free_slide_plane_marker_data(op->customdata); clip_tracking_show_cursor(C); DAG_id_tag_update(&sc->clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); return OPERATOR_FINISHED; } break; case ESCKEY: cancel_mouse_slide_plane_marker(op->customdata); free_slide_plane_marker_data(op->customdata); clip_tracking_show_cursor(C); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); return OPERATOR_CANCELLED; } return OPERATOR_RUNNING_MODAL; }
/* Calculate factor of a scale, which will eliminate black areas * appearing on the frame caused by frame translation. */ static float stabilization_calculate_autoscale_factor(MovieTracking *tracking, int width, int height) { float firstmedian[2]; MovieTrackingStabilization *stab = &tracking->stabilization; float aspect = tracking->camera.pixel_aspect; /* Early output if stabilization data is already up-to-date. */ if (stab->ok) return stab->scale; /* See comment in BKE_tracking_stabilization_data_get about first frame. */ if (stabilization_median_point_get(tracking, 1, firstmedian)) { int sfra = INT_MAX, efra = INT_MIN, cfra; float scale = 1.0f; MovieTrackingTrack *track; stab->scale = 1.0f; /* Calculate frame range of tracks used for stabilization. */ track = tracking->tracks.first; while (track) { if (track->flag & TRACK_USE_2D_STAB || ((stab->flag & TRACKING_STABILIZE_ROTATION) && track == stab->rot_track)) { sfra = min_ii(sfra, track->markers[0].framenr); efra = max_ii(efra, track->markers[track->markersnr - 1].framenr); } track = track->next; } /* For every frame we calculate scale factor needed to eliminate black * area and choose largest scale factor as final one. */ for (cfra = sfra; cfra <= efra; cfra++) { float median[2]; float translation[2], angle, tmp_scale; int i; float mat[4][4]; float points[4][2] = {{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}}; float si, co; stabilization_median_point_get(tracking, cfra, median); stabilization_calculate_data(tracking, cfra, width, height, firstmedian, median, translation, &tmp_scale, &angle); BKE_tracking_stabilization_data_to_mat4(width, height, aspect, translation, 1.0f, angle, mat); si = sinf(angle); co = cosf(angle); for (i = 0; i < 4; i++) { int j; float a[3] = {0.0f, 0.0f, 0.0f}, b[3] = {0.0f, 0.0f, 0.0f}; copy_v3_v3(a, points[i]); copy_v3_v3(b, points[(i + 1) % 4]); mul_m4_v3(mat, a); mul_m4_v3(mat, b); for (j = 0; j < 4; j++) { float point[3] = {points[j][0], points[j][1], 0.0f}; float v1[3], v2[3]; sub_v3_v3v3(v1, b, a); sub_v3_v3v3(v2, point, a); if (cross_v2v2(v1, v2) >= 0.0f) { const float rotDx[4][2] = {{1.0f, 0.0f}, {0.0f, -1.0f}, {-1.0f, 0.0f}, {0.0f, 1.0f}}; const float rotDy[4][2] = {{0.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, -1.0f}, {-1.0f, 0.0f}}; float dx = translation[0] * rotDx[j][0] + translation[1] * rotDx[j][1], dy = translation[0] * rotDy[j][0] + translation[1] * rotDy[j][1]; float w, h, E, F, G, H, I, J, K, S; if (j % 2) { w = (float)height / 2.0f; h = (float)width / 2.0f; } else { w = (float)width / 2.0f; h = (float)height / 2.0f; } E = -w * co + h * si; F = -h * co - w * si; if ((i % 2) == (j % 2)) { G = -w * co - h * si; H = h * co - w * si; } else { G = w * co + h * si; H = -h * co + w * si; } I = F - H; J = G - E; K = G * F - E * H; S = (-w * I - h * J) / (dx * I + dy * J + K); scale = max_ff(scale, S); } } } } stab->scale = scale; if (stab->maxscale > 0.0f) stab->scale = min_ff(stab->scale, stab->maxscale); } else { stab->scale = 1.0f; } stab->ok = true; return stab->scale; }