Exemplo n.º 1
0
float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline,
                                                      unsigned int *tot_diff_point,
                                                      const unsigned int resol
                                                      ))[2]
{
	MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);

	MaskSplinePoint *point_curr, *point_prev;
	float (*diff_points)[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_diff_point = 0;
		return NULL;
	}

	/* len+1 because of 'forward_diff_bezier' function */
	*tot_diff_point = tot;
	diff_points = fp = MEM_mallocN((tot + 1) * sizeof(*diff_points), "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 *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;

		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));
		}

		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++;
	}

	return diff_points;
}
Exemplo n.º 2
0
static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject *args)
{
	VectorObject *vec_k1, *vec_h1, *vec_k2, *vec_h2;
	int resolu;
	int dims;
	int i;
	float *coord_array, *fp;
	PyObject *list;

	float k1[4] = {0.0, 0.0, 0.0, 0.0};
	float h1[4] = {0.0, 0.0, 0.0, 0.0};
	float k2[4] = {0.0, 0.0, 0.0, 0.0};
	float h2[4] = {0.0, 0.0, 0.0, 0.0};


	if (!PyArg_ParseTuple(args, "O!O!O!O!i:interpolate_bezier",
	                      &vector_Type, &vec_k1,
	                      &vector_Type, &vec_h1,
	                      &vector_Type, &vec_h2,
	                      &vector_Type, &vec_k2, &resolu))
	{
		return NULL;
	}

	if (resolu <= 1) {
		PyErr_SetString(PyExc_ValueError,
		                "resolution must be 2 or over");
		return NULL;
	}

	if (BaseMath_ReadCallback(vec_k1) == -1 ||
	    BaseMath_ReadCallback(vec_h1) == -1 ||
	    BaseMath_ReadCallback(vec_k2) == -1 ||
	    BaseMath_ReadCallback(vec_h2) == -1)
	{
		return NULL;
	}

	dims = MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);

	for (i = 0; i < vec_k1->size; i++) k1[i] = vec_k1->vec[i];
	for (i = 0; i < vec_h1->size; i++) h1[i] = vec_h1->vec[i];
	for (i = 0; i < vec_k2->size; i++) k2[i] = vec_k2->vec[i];
	for (i = 0; i < vec_h2->size; i++) h2[i] = vec_h2->vec[i];

	coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "interpolate_bezier");
	for (i = 0; i < dims; i++) {
		BKE_curve_forward_diff_bezier(k1[i], h1[i], h2[i], k2[i], coord_array + i, resolu - 1, sizeof(float) * dims);
	}

	list = PyList_New(resolu);
	fp = coord_array;
	for (i = 0; i < resolu; i++, fp = fp + dims) {
		PyList_SET_ITEM(list, i, Vector_CreatePyObject(fp, dims, Py_NEW, NULL));
	}
	MEM_freeN(coord_array);
	return list;
}
Exemplo n.º 3
0
/* only creates a table for a single channel in CurveMapping */
static void curvemap_make_table(CurveMap *cuma, rctf *clipr)
{
	CurveMapPoint *cmp = cuma->curve;
	BezTriple *bezt;
	float *fp, *allpoints, *lastpoint, curf, range;
	int a, totpoint;
	
	if (cuma->curve == NULL) return;
	
	/* default rect also is table range */
	cuma->mintable = clipr->xmin;
	cuma->maxtable = clipr->xmax;
	
	/* hrmf... we now rely on blender ipo beziers, these are more advanced */
	bezt = MEM_callocN(cuma->totpoint * sizeof(BezTriple), "beztarr");
	
	for (a = 0; a < cuma->totpoint; a++) {
		cuma->mintable = MIN2(cuma->mintable, cmp[a].x);
		cuma->maxtable = MAX2(cuma->maxtable, cmp[a].x);
		bezt[a].vec[1][0] = cmp[a].x;
		bezt[a].vec[1][1] = cmp[a].y;
		if (cmp[a].flag & CUMA_VECTOR)
			bezt[a].h1 = bezt[a].h2 = HD_VECT;
		else
			bezt[a].h1 = bezt[a].h2 = HD_AUTO;
	}
	
	for (a = 0; a < cuma->totpoint; a++) {
		if (a == 0)
			calchandle_curvemap(bezt, NULL, bezt + 1, 0);
		else if (a == cuma->totpoint - 1)
			calchandle_curvemap(bezt + a, bezt + a - 1, NULL, 0);
		else
			calchandle_curvemap(bezt + a, bezt + a - 1, bezt + a + 1, 0);
	}
	
	/* first and last handle need correction, instead of pointing to center of next/prev, 
	 * we let it point to the closest handle */
	if (cuma->totpoint > 2) {
		float hlen, nlen, vec[3];
		
		if (bezt[0].h2 == HD_AUTO) {
			
			hlen = len_v3v3(bezt[0].vec[1], bezt[0].vec[2]); /* original handle length */
			/* clip handle point */
			copy_v3_v3(vec, bezt[1].vec[0]);
			if (vec[0] < bezt[0].vec[1][0])
				vec[0] = bezt[0].vec[1][0];
			
			sub_v3_v3(vec, bezt[0].vec[1]);
			nlen = len_v3(vec);
			if (nlen > FLT_EPSILON) {
				mul_v3_fl(vec, hlen / nlen);
				add_v3_v3v3(bezt[0].vec[2], vec, bezt[0].vec[1]);
				sub_v3_v3v3(bezt[0].vec[0], bezt[0].vec[1], vec);
			}
		}
		a = cuma->totpoint - 1;
		if (bezt[a].h2 == HD_AUTO) {
			
			hlen = len_v3v3(bezt[a].vec[1], bezt[a].vec[0]); /* original handle length */
			/* clip handle point */
			copy_v3_v3(vec, bezt[a - 1].vec[2]);
			if (vec[0] > bezt[a].vec[1][0])
				vec[0] = bezt[a].vec[1][0];
			
			sub_v3_v3(vec, bezt[a].vec[1]);
			nlen = len_v3(vec);
			if (nlen > FLT_EPSILON) {
				mul_v3_fl(vec, hlen / nlen);
				add_v3_v3v3(bezt[a].vec[0], vec, bezt[a].vec[1]);
				sub_v3_v3v3(bezt[a].vec[2], bezt[a].vec[1], vec);
			}
		}
	}	
	/* make the bezier curve */
	if (cuma->table)
		MEM_freeN(cuma->table);
	totpoint = (cuma->totpoint - 1) * CM_RESOL;
	fp = allpoints = MEM_callocN(totpoint * 2 * sizeof(float), "table");
	
	for (a = 0; a < cuma->totpoint - 1; a++, fp += 2 * CM_RESOL) {
		correct_bezpart(bezt[a].vec[1], bezt[a].vec[2], bezt[a + 1].vec[0], bezt[a + 1].vec[1]);
		BKE_curve_forward_diff_bezier(bezt[a].vec[1][0], bezt[a].vec[2][0], bezt[a + 1].vec[0][0], bezt[a + 1].vec[1][0], fp, CM_RESOL - 1, 2 * sizeof(float));
		BKE_curve_forward_diff_bezier(bezt[a].vec[1][1], bezt[a].vec[2][1], bezt[a + 1].vec[0][1], bezt[a + 1].vec[1][1], fp + 1, CM_RESOL - 1, 2 * sizeof(float));
	}
	
	/* store first and last handle for extrapolation, unit length */
	cuma->ext_in[0] = bezt[0].vec[0][0] - bezt[0].vec[1][0];
	cuma->ext_in[1] = bezt[0].vec[0][1] - bezt[0].vec[1][1];
	range = sqrt(cuma->ext_in[0] * cuma->ext_in[0] + cuma->ext_in[1] * cuma->ext_in[1]);
	cuma->ext_in[0] /= range;
	cuma->ext_in[1] /= range;

	a = cuma->totpoint - 1;
	cuma->ext_out[0] = bezt[a].vec[1][0] - bezt[a].vec[2][0];
	cuma->ext_out[1] = bezt[a].vec[1][1] - bezt[a].vec[2][1];
	range = sqrt(cuma->ext_out[0] * cuma->ext_out[0] + cuma->ext_out[1] * cuma->ext_out[1]);
	cuma->ext_out[0] /= range;
	cuma->ext_out[1] /= range;
	
	/* cleanup */
	MEM_freeN(bezt);

	range = CM_TABLEDIV * (cuma->maxtable - cuma->mintable);
	cuma->range = 1.0f / range;
	
	/* now make a table with CM_TABLE equal x distances */
	fp = allpoints;
	lastpoint = allpoints + 2 * (totpoint - 1);
	cmp = MEM_callocN((CM_TABLE + 1) * sizeof(CurveMapPoint), "dist table");

	for (a = 0; a <= CM_TABLE; a++) {
		curf = cuma->mintable + range * (float)a;
		cmp[a].x = curf;
		
		/* get the first x coordinate larger than curf */
		while (curf >= fp[0] && fp != lastpoint) {
			fp += 2;
		}
		if (fp == allpoints || (curf >= fp[0] && fp == lastpoint))
			cmp[a].y = curvemap_calc_extend(cuma, curf, allpoints, lastpoint);
		else {
			float fac1 = fp[0] - fp[-2];
			float fac2 = fp[0] - curf;
			if (fac1 > FLT_EPSILON)
				fac1 = fac2 / fac1;
			else
				fac1 = 0.0f;
			cmp[a].y = fac1 * fp[-1] + (1.0f - fac1) * fp[1];
		}
	}
	
	MEM_freeN(allpoints);
	cuma->table = cmp;
}
Exemplo n.º 4
0
/* helper func - draw one repeat of an F-Curve */
static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d)
{
	BezTriple *prevbezt = fcu->bezt;
	BezTriple *bezt = prevbezt + 1;
	float v1[2], v2[2], v3[2], v4[2];
	float *fp, data[120];
	float fac = 0.0f;
	int b = fcu->totvert - 1;
	int resol;
	float unit_scale;
	short mapping_flag = ANIM_get_normalization_flags(ac);

	/* apply unit mapping */
	glPushMatrix();
	unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag);
	glScalef(1.0f, unit_scale, 1.0f);

	glBegin(GL_LINE_STRIP);
	
	/* extrapolate to left? */
	if (prevbezt->vec[1][0] > v2d->cur.xmin) {
		/* left-side of view comes before first keyframe, so need to extend as not cyclic */
		v1[0] = v2d->cur.xmin;
		
		/* y-value depends on the interpolation */
		if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) {
			/* just extend across the first keyframe's value */
			v1[1] = prevbezt->vec[1][1];
		}
		else if (prevbezt->ipo == BEZT_IPO_LIN) {
			/* extrapolate linear dosnt use the handle, use the next points center instead */
			fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
			if (fac) fac = 1.0f / fac;
			v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
		}
		else {
			/* based on angle of handle 1 (relative to keyframe) */
			fac = (prevbezt->vec[0][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
			if (fac) fac = 1.0f / fac;
			v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]);
		}
		
		glVertex2fv(v1);
	}
	
	/* if only one keyframe, add it now */
	if (fcu->totvert == 1) {
		v1[0] = prevbezt->vec[1][0];
		v1[1] = prevbezt->vec[1][1];
		glVertex2fv(v1);
	}
	
	/* draw curve between first and last keyframe (if there are enough to do so) */
	/* TODO: optimize this to not have to calc stuff out of view too? */
	while (b--) {
		if (prevbezt->ipo == BEZT_IPO_CONST) {
			/* Constant-Interpolation: draw segment between previous keyframe and next, but holding same value */
			v1[0] = prevbezt->vec[1][0];
			v1[1] = prevbezt->vec[1][1];
			glVertex2fv(v1);
			
			v1[0] = bezt->vec[1][0];
			v1[1] = prevbezt->vec[1][1];
			glVertex2fv(v1);
		}
		else if (prevbezt->ipo == BEZT_IPO_LIN) {
			/* Linear interpolation: just add one point (which should add a new line segment) */
			v1[0] = prevbezt->vec[1][0];
			v1[1] = prevbezt->vec[1][1];
			glVertex2fv(v1);
		}
		else {
			/* Bezier-Interpolation: draw curve as series of segments between keyframes 
			 *	- resol determines number of points to sample in between keyframes
			 */
			
			/* resol depends on distance between points (not just horizontal) OR is a fixed high res */
			/* TODO: view scale should factor into this someday too... */
			if (fcu->driver) 
				resol = 32;
			else 
				resol = (int)(5.0f * len_v2v2(bezt->vec[1], prevbezt->vec[1]));
			
			if (resol < 2) {
				/* only draw one */
				v1[0] = prevbezt->vec[1][0];
				v1[1] = prevbezt->vec[1][1];
				glVertex2fv(v1);
			}
			else {
				/* clamp resolution to max of 32 */
				/* NOTE: higher values will crash */
				if (resol > 32) resol = 32;
				
				v1[0] = prevbezt->vec[1][0];
				v1[1] = prevbezt->vec[1][1];
				v2[0] = prevbezt->vec[2][0];
				v2[1] = prevbezt->vec[2][1];
				
				v3[0] = bezt->vec[0][0];
				v3[1] = bezt->vec[0][1];
				v4[0] = bezt->vec[1][0];
				v4[1] = bezt->vec[1][1];
				
				correct_bezpart(v1, v2, v3, v4);
				
				BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3);
				BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3);
				
				for (fp = data; resol; resol--, fp += 3)
					glVertex2fv(fp);
			}
		}
		
		/* get next pointers */
		prevbezt = bezt;
		bezt++;
		
		/* last point? */
		if (b == 0) {
			v1[0] = prevbezt->vec[1][0];
			v1[1] = prevbezt->vec[1][1];
			glVertex2fv(v1);
		}
	}
	
	/* extrapolate to right? (see code for left-extrapolation above too) */
	if (prevbezt->vec[1][0] < v2d->cur.xmax) {
		v1[0] = v2d->cur.xmax;
		
		/* y-value depends on the interpolation */
		if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) {
			/* based on last keyframe's value */
			v1[1] = prevbezt->vec[1][1];
		}
		else if (prevbezt->ipo == BEZT_IPO_LIN) {
			/* extrapolate linear dosnt use the handle, use the previous points center instead */
			bezt = prevbezt - 1;
			fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
			if (fac) fac = 1.0f / fac;
			v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
		}
		else {
			/* based on angle of handle 1 (relative to keyframe) */
			fac = (prevbezt->vec[2][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
			if (fac) fac = 1.0f / fac;
			v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]);
		}
		
		glVertex2fv(v1);
	}
	
	glEnd();
	glPopMatrix();
}
Exemplo n.º 5
0
static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase,
                              const bool for_render, const bool use_render_resolution)
{
	Nurb *nu;
	DispList *dl;
	BezTriple *bezt, *prevbezt;
	BPoint *bp;
	float *data;
	int a, len, resolu;
	const bool editmode = (!for_render && (cu->editnurb || cu->editfont));

	nu = nubase->first;
	while (nu) {
		if (nu->hide == 0 || editmode == false) {
			if (use_render_resolution && cu->resolu_ren != 0)
				resolu = cu->resolu_ren;
			else
				resolu = nu->resolu;

			if (!BKE_nurb_check_valid_u(nu)) {
				/* pass */
			}
			else if (nu->type == CU_BEZIER) {
				/* count */
				len = 0;
				a = nu->pntsu - 1;
				if (nu->flagu & CU_NURB_CYCLIC) a++;

				prevbezt = nu->bezt;
				bezt = prevbezt + 1;
				while (a--) {
					if (a == 0 && (nu->flagu & CU_NURB_CYCLIC))
						bezt = nu->bezt;

					if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT)
						len++;
					else
						len += resolu;

					if (a == 0 && (nu->flagu & CU_NURB_CYCLIC) == 0)
						len++;

					prevbezt = bezt;
					bezt++;
				}

				dl = MEM_callocN(sizeof(DispList), "makeDispListbez");
				/* len+1 because of 'forward_diff_bezier' function */
				dl->verts = MEM_mallocN((len + 1) * sizeof(float[3]), "dlverts");
				BLI_addtail(dispbase, dl);
				dl->parts = 1;
				dl->nr = len;
				dl->col = nu->mat_nr;
				dl->charidx = nu->charidx;

				data = dl->verts;

				/* check that (len != 2) so we don't immediately loop back on ourselves */
				if (nu->flagu & CU_NURB_CYCLIC && (dl->nr != 2)) {
					dl->type = DL_POLY;
					a = nu->pntsu;
				}
				else {
					dl->type = DL_SEGM;
					a = nu->pntsu - 1;
				}

				prevbezt = nu->bezt;
				bezt = prevbezt + 1;

				while (a--) {
					if (a == 0 && dl->type == DL_POLY)
						bezt = nu->bezt;

					if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) {
						copy_v3_v3(data, prevbezt->vec[1]);
						data += 3;
					}
					else {
						int j;
						for (j = 0; j < 3; j++) {
							BKE_curve_forward_diff_bezier(prevbezt->vec[1][j],
							                              prevbezt->vec[2][j],
							                              bezt->vec[0][j],
							                              bezt->vec[1][j],
							                              data + j, resolu, 3 * sizeof(float));
						}

						data += 3 * resolu;
					}

					if (a == 0 && dl->type == DL_SEGM) {
						copy_v3_v3(data, bezt->vec[1]);
					}

					prevbezt = bezt;
					bezt++;
				}
			}
			else if (nu->type == CU_NURBS) {
				len = (resolu * SEGMENTSU(nu));

				dl = MEM_callocN(sizeof(DispList), "makeDispListsurf");
				dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts");
				BLI_addtail(dispbase, dl);
				dl->parts = 1;

				dl->nr = len;
				dl->col = nu->mat_nr;
				dl->charidx = nu->charidx;

				data = dl->verts;
				if (nu->flagu & CU_NURB_CYCLIC)
					dl->type = DL_POLY;
				else dl->type = DL_SEGM;
				BKE_nurb_makeCurve(nu, data, NULL, NULL, NULL, resolu, 3 * sizeof(float));
			}
			else if (nu->type == CU_POLY) {
				len = nu->pntsu;
				dl = MEM_callocN(sizeof(DispList), "makeDispListpoly");
				dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts");
				BLI_addtail(dispbase, dl);
				dl->parts = 1;
				dl->nr = len;
				dl->col = nu->mat_nr;
				dl->charidx = nu->charidx;

				data = dl->verts;
				if ((nu->flagu & CU_NURB_CYCLIC) && (dl->nr != 2)) {
					dl->type = DL_POLY;
				}
				else {
					dl->type = DL_SEGM;
				}

				a = len;
				bp = nu->bp;
				while (a--) {
					copy_v3_v3(data, bp->vec);
					bp++;
					data += 3;
				}
			}
		}
		nu = nu->next;
	}
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, float *r_offset)
{
	float factor = 1.0f, offset = 0.0f;

	if (flag & ANIM_UNITCONV_RESTORE) {
		if (r_offset)
			*r_offset = fcu->prev_offset;

		return 1.0f / fcu->prev_norm_factor;
	}

	if (flag & ANIM_UNITCONV_NORMALIZE_FREEZE) {
		if (r_offset)
			*r_offset = fcu->prev_offset;
		if (fcu->prev_norm_factor == 0.0f) {
			/* Happens when Auto Normalize was disabled before
			 * any curves were displayed.
			 */
			return 1.0f;
		}
		return fcu->prev_norm_factor;
	}

	if (G.moving & G_TRANSFORM_FCURVES) {
		if (r_offset)
			*r_offset = fcu->prev_offset;
		if (fcu->prev_norm_factor == 0.0f) {
			/* Same as above. */
			return 1.0f;
		}
		return fcu->prev_norm_factor;
	}

	fcu->prev_norm_factor = 1.0f;
	if (fcu->bezt) {
		const bool use_preview_only = PRVRANGEON;
		const BezTriple *bezt;
		int i;
		float max_coord = -FLT_MAX;
		float min_coord = FLT_MAX;
		float range;

		if (fcu->totvert < 1) {
			return 1.0f;
		}

		for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
			if (use_preview_only && !IN_RANGE_INCL(bezt->vec[1][0],
			                                       scene->r.psfra,
			                                       scene->r.pefra))
			{
				continue;
			}

			if (i == 0) {
				/* We ignore extrapolation flags and handle here, and use the
				 * control point position only. so we normalize "interesting"
				 * part of the curve.
				 *
				 * Here we handle left extrapolation.
				 */
				max_coord = max_ff(max_coord, bezt->vec[1][1]);

				min_coord = min_ff(min_coord, bezt->vec[1][1]);
			}
			else {
				const BezTriple *prev_bezt = bezt - 1;
				if (prev_bezt->ipo == BEZT_IPO_CONST) {
					/* Constant interpolation: previous CV value is used up
					 * to the current keyframe.
					 */
					max_coord = max_ff(max_coord, bezt->vec[1][1]);
					min_coord = min_ff(min_coord, bezt->vec[1][1]);
				}
				else if (prev_bezt->ipo == BEZT_IPO_LIN) {
					/* Linear interpolation: min/max using both previous and
					 * and current CV.
					 */
					max_coord = max_ff(max_coord, bezt->vec[1][1]);
					min_coord = min_ff(min_coord, bezt->vec[1][1]);
					max_coord = max_ff(max_coord, prev_bezt->vec[1][1]);
					min_coord = min_ff(min_coord, prev_bezt->vec[1][1]);
				}
				else if (prev_bezt->ipo == BEZT_IPO_BEZ) {
					const int resol = fcu->driver
					        ? 32
					        : min_ii((int)(5.0f * len_v2v2(bezt->vec[1], prev_bezt->vec[1])), 32);
					if (resol < 2) {
						max_coord = max_ff(max_coord, prev_bezt->vec[1][1]);
						min_coord = min_ff(min_coord, prev_bezt->vec[1][1]);
					}
					else {
						float data[120];
						float v1[2], v2[2], v3[2], v4[2];

						v1[0] = prev_bezt->vec[1][0];
						v1[1] = prev_bezt->vec[1][1];
						v2[0] = prev_bezt->vec[2][0];
						v2[1] = prev_bezt->vec[2][1];

						v3[0] = bezt->vec[0][0];
						v3[1] = bezt->vec[0][1];
						v4[0] = bezt->vec[1][0];
						v4[1] = bezt->vec[1][1];

						correct_bezpart(v1, v2, v3, v4);

						BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3);
						BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3);

						for (int j = 0; j <= resol; ++j) {
							const float *fp = &data[j * 3];
							max_coord = max_ff(max_coord, fp[1]);
							min_coord = min_ff(min_coord, fp[1]);
						}
					}
				}
			}
		}

		if (max_coord > min_coord) {
			range = max_coord - min_coord;
			if (range > FLT_EPSILON) {
				factor = 2.0f / range;
			}
			offset = -min_coord - range / 2.0f;
		}
		else if (max_coord == min_coord) {
			factor = 1.0f;
			offset = -min_coord;
		}
	}
	BLI_assert(factor != 0.0f);
	if (r_offset) {
		*r_offset = offset;
	}

	fcu->prev_norm_factor = factor;
	fcu->prev_offset = offset;
	return factor;
}