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;
}
Esempio n. 2
0
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;
}
Esempio n. 4
0
/* 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;
}