Example #1
0
/* 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]);
}
Example #2
0
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;
}
Example #3
0
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]);
}
Example #4
0
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);
  }
}
Example #5
0
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);
}
Example #7
0
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;
}
Example #8
0
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();
}
Example #9
0
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;
}
Example #10
0
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);
	}
}
Example #11
0
/** 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;
}
Example #12
0
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);
}