示例#1
0
void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint)
{
	Material *ma;
	StrandBuffer *strandbuf;
	float *simplify;
	float p[4][3], data[4], cross[3], w, dx, dy, t;
	int type;

	strandbuf= sseg->buffer;
	ma= sseg->buffer->ma;
	t= spoint->t;
	type= (strandbuf->flag & R_STRAND_BSPLINE)? KEY_BSPLINE: KEY_CARDINAL;

	copy_v3_v3(p[0], sseg->v[0]->co);
	copy_v3_v3(p[1], sseg->v[1]->co);
	copy_v3_v3(p[2], sseg->v[2]->co);
	copy_v3_v3(p[3], sseg->v[3]->co);

	if (sseg->obi->flag & R_TRANSFORMED) {
		mul_m4_v3(sseg->obi->mat, p[0]);
		mul_m4_v3(sseg->obi->mat, p[1]);
		mul_m4_v3(sseg->obi->mat, p[2]);
		mul_m4_v3(sseg->obi->mat, p[3]);
	}

	if (t == 0.0f) {
		copy_v3_v3(spoint->co, p[1]);
		spoint->strandco= sseg->v[1]->strandco;

		spoint->dtstrandco= (sseg->v[2]->strandco - sseg->v[0]->strandco);
		if (sseg->v[0] != sseg->v[1])
			spoint->dtstrandco *= 0.5f;
	}
	else if (t == 1.0f) {
		copy_v3_v3(spoint->co, p[2]);
		spoint->strandco= sseg->v[2]->strandco;

		spoint->dtstrandco= (sseg->v[3]->strandco - sseg->v[1]->strandco);
		if (sseg->v[3] != sseg->v[2])
			spoint->dtstrandco *= 0.5f;
	}
	else {
		key_curve_position_weights(t, data, type);
		spoint->co[0]= data[0]*p[0][0] + data[1]*p[1][0] + data[2]*p[2][0] + data[3]*p[3][0];
		spoint->co[1]= data[0]*p[0][1] + data[1]*p[1][1] + data[2]*p[2][1] + data[3]*p[3][1];
		spoint->co[2]= data[0]*p[0][2] + data[1]*p[1][2] + data[2]*p[2][2] + data[3]*p[3][2];
		spoint->strandco= (1.0f-t)*sseg->v[1]->strandco + t*sseg->v[2]->strandco;
	}

	key_curve_tangent_weights(t, data, type);
	spoint->dtco[0]= data[0]*p[0][0] + data[1]*p[1][0] + data[2]*p[2][0] + data[3]*p[3][0];
	spoint->dtco[1]= data[0]*p[0][1] + data[1]*p[1][1] + data[2]*p[2][1] + data[3]*p[3][1];
	spoint->dtco[2]= data[0]*p[0][2] + data[1]*p[1][2] + data[2]*p[2][2] + data[3]*p[3][2];

	normalize_v3_v3(spoint->tan, spoint->dtco);
	normalize_v3_v3(spoint->nor, spoint->co);
	negate_v3(spoint->nor);

	spoint->width= strand_eval_width(ma, spoint->strandco);
	
	/* simplification */
	simplify= RE_strandren_get_simplify(strandbuf->obr, sseg->strand, 0);
	spoint->alpha= (simplify)? simplify[1]: 1.0f;

	/* outer points */
	cross_v3_v3v3(cross, spoint->co, spoint->tan);

	w= spoint->co[2]*strandbuf->winmat[2][3] + strandbuf->winmat[3][3];
	dx= strandbuf->winx*cross[0]*strandbuf->winmat[0][0]/w;
	dy= strandbuf->winy*cross[1]*strandbuf->winmat[1][1]/w;
	w= sqrt(dx*dx + dy*dy);

	if (w > 0.0f) {
		if (strandbuf->flag & R_STRAND_B_UNITS) {
			const float crosslen= len_v3(cross);
			w= 2.0f*crosslen*strandbuf->minwidth/w;

			if (spoint->width < w) {
				spoint->alpha= spoint->width/w;
				spoint->width= w;
			}

			if (simplify)
				/* squared because we only change width, not length */
				spoint->width *= simplify[0]*simplify[0];

			mul_v3_fl(cross, spoint->width*0.5f/crosslen);
		}
		else
			mul_v3_fl(cross, spoint->width/w);
	}

	sub_v3_v3v3(spoint->co1, spoint->co, cross);
	add_v3_v3v3(spoint->co2, spoint->co, cross);

	copy_v3_v3(spoint->dsco, cross);
}
示例#2
0
/* calculate the deformation implied by the curve path at a given parametric position,
 * and returns whether this operation succeeded.
 *
 * note: ctime is normalized range <0-1>
 *
 * returns OK: 1/0
 */
int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius, float *weight)
{
	Curve *cu;
	Nurb *nu;
	BevList *bl;
	Path *path;
	PathPoint *pp, *p0, *p1, *p2, *p3;
	float fac;
	float data[4];
	int cycl=0, s0, s1, s2, s3;

	if (ob==NULL || ob->type != OB_CURVE) return 0;
	cu= ob->data;
	if (cu->path==NULL || cu->path->data==NULL) {
		printf("no path!\n");
		return 0;
	}
	path= cu->path;
	pp= path->data;
	
	/* test for cyclic */
	bl= cu->bev.first;
	if (!bl) return 0;
	if (!bl->nr) return 0;
	if (bl->poly> -1) cycl= 1;

	ctime *= (path->len-1);
	
	s1= (int)floor(ctime);
	fac= (float)(s1+1)-ctime;

	/* path->len is corected for cyclic */
	s0= interval_test(0, path->len-1-cycl, s1-1, cycl);
	s1= interval_test(0, path->len-1-cycl, s1, cycl);
	s2= interval_test(0, path->len-1-cycl, s1+1, cycl);
	s3= interval_test(0, path->len-1-cycl, s1+2, cycl);

	p0= pp + s0;
	p1= pp + s1;
	p2= pp + s2;
	p3= pp + s3;

	/* note, commented out for follow constraint */
	//if (cu->flag & CU_FOLLOW) {

		key_curve_tangent_weights(1.0f-fac, data, KEY_BSPLINE);

		interp_v3_v3v3v3v3(dir, p0->vec, p1->vec, p2->vec, p3->vec, data);

		/* make compatible with vectoquat */
		negate_v3(dir);
	//}
	
	nu= cu->nurb.first;

	/* make sure that first and last frame are included in the vectors here  */
	if (nu->type == CU_POLY) key_curve_position_weights(1.0f-fac, data, KEY_LINEAR);
	else if (nu->type == CU_BEZIER) key_curve_position_weights(1.0f-fac, data, KEY_LINEAR);
	else if (s0==s1 || p2==p3) key_curve_position_weights(1.0f-fac, data, KEY_CARDINAL);
	else key_curve_position_weights(1.0f-fac, data, KEY_BSPLINE);

	vec[0]= data[0]*p0->vec[0] + data[1]*p1->vec[0] + data[2]*p2->vec[0] + data[3]*p3->vec[0] ; /* X */
	vec[1]= data[0]*p0->vec[1] + data[1]*p1->vec[1] + data[2]*p2->vec[1] + data[3]*p3->vec[1] ; /* Y */
	vec[2]= data[0]*p0->vec[2] + data[1]*p1->vec[2] + data[2]*p2->vec[2] + data[3]*p3->vec[2] ; /* Z */
	vec[3]= data[0]*p0->vec[3] + data[1]*p1->vec[3] + data[2]*p2->vec[3] + data[3]*p3->vec[3] ; /* Tilt, should not be needed since we have quat still used */

	if (quat) {
		float totfac, q1[4], q2[4];

		totfac= data[0]+data[3];
		if (totfac>FLT_EPSILON)	interp_qt_qtqt(q1, p0->quat, p3->quat, data[3] / totfac);
		else					copy_qt_qt(q1, p1->quat);

		totfac= data[1]+data[2];
		if (totfac>FLT_EPSILON)	interp_qt_qtqt(q2, p1->quat, p2->quat, data[2] / totfac);
		else					copy_qt_qt(q2, p3->quat);

		totfac = data[0]+data[1]+data[2]+data[3];
		if (totfac>FLT_EPSILON)	interp_qt_qtqt(quat, q1, q2, (data[1]+data[2]) / totfac);
		else					copy_qt_qt(quat, q2);
	}

	if (radius)
		*radius= data[0]*p0->radius + data[1]*p1->radius + data[2]*p2->radius + data[3]*p3->radius;

	if (weight)
		*weight= data[0]*p0->weight + data[1]*p1->weight + data[2]*p2->weight + data[3]*p3->weight;

	return 1;
}
示例#3
0
文件: anim.c 项目: jinjoh/NOOR
/* ctime is normalized range <0-1> */
int where_on_path(Object *ob, float ctime, float *vec, float *dir, float *quat, float *radius)	/* returns OK */
{
	Curve *cu;
	Nurb *nu;
	BevList *bl;
	Path *path;
	PathPoint *pp, *p0, *p1, *p2, *p3;
	float fac;
	float data[4];
	int cycl=0, s0, s1, s2, s3;

	if(ob==NULL || ob->type != OB_CURVE) return 0;
	cu= ob->data;
	if(cu->path==NULL || cu->path->data==NULL) {
		printf("no path!\n");
		return 0;
	}
	path= cu->path;
	pp= path->data;
	
	/* test for cyclic */
	bl= cu->bev.first;
	if (!bl) return 0;
	if (!bl->nr) return 0;
	if(bl->poly> -1) cycl= 1;

	ctime *= (path->len-1);
	
	s1= (int)floor(ctime);
	fac= (float)(s1+1)-ctime;

	/* path->len is corected for cyclic */
	s0= interval_test(0, path->len-1-cycl, s1-1, cycl);
	s1= interval_test(0, path->len-1-cycl, s1, cycl);
	s2= interval_test(0, path->len-1-cycl, s1+1, cycl);
	s3= interval_test(0, path->len-1-cycl, s1+2, cycl);

	p0= pp + s0;
	p1= pp + s1;
	p2= pp + s2;
	p3= pp + s3;

	/* note, commented out for follow constraint */
	//if(cu->flag & CU_FOLLOW) {
		
		key_curve_tangent_weights(1.0f-fac, data, KEY_BSPLINE);
		
		dir[0]= data[0]*p0->vec[0] + data[1]*p1->vec[0] + data[2]*p2->vec[0] + data[3]*p3->vec[0] ;
		dir[1]= data[0]*p0->vec[1] + data[1]*p1->vec[1] + data[2]*p2->vec[1] + data[3]*p3->vec[1] ;
		dir[2]= data[0]*p0->vec[2] + data[1]*p1->vec[2] + data[2]*p2->vec[2] + data[3]*p3->vec[2] ;
		
		/* make compatible with vectoquat */
		dir[0]= -dir[0];
		dir[1]= -dir[1];
		dir[2]= -dir[2];
	//}
	
	nu= cu->nurb.first;

	/* make sure that first and last frame are included in the vectors here  */
	if(nu->type == CU_POLY) key_curve_position_weights(1.0f-fac, data, KEY_LINEAR);
	else if(nu->type == CU_BEZIER) key_curve_position_weights(1.0f-fac, data, KEY_LINEAR);
	else if(s0==s1 || p2==p3) key_curve_position_weights(1.0f-fac, data, KEY_CARDINAL);
	else key_curve_position_weights(1.0f-fac, data, KEY_BSPLINE);

	vec[0]= data[0]*p0->vec[0] + data[1]*p1->vec[0] + data[2]*p2->vec[0] + data[3]*p3->vec[0] ; /* X */
	vec[1]= data[0]*p0->vec[1] + data[1]*p1->vec[1] + data[2]*p2->vec[1] + data[3]*p3->vec[1] ; /* Y */
	vec[2]= data[0]*p0->vec[2] + data[1]*p1->vec[2] + data[2]*p2->vec[2] + data[3]*p3->vec[2] ; /* Z */
	vec[3]= data[0]*p0->vec[3] + data[1]*p1->vec[3] + data[2]*p2->vec[3] + data[3]*p3->vec[3] ; /* Tilt, should not be needed since we have quat still used */
	/* Need to verify the quat interpolation is correct - XXX */

	if (quat) {
		//float totfac, q1[4], q2[4];

		/* checks for totfac are needed when 'fac' is 1.0 key_curve_position_weights can assign zero
		 * to more then one index in data which can give divide by zero error */
/*
		totfac= data[0]+data[1];
		if(totfac>0.000001)	QuatInterpol(q1, p0->quat, p1->quat, data[0] / totfac);
		else				QUATCOPY(q1, p1->quat);

		NormalQuat(q1);

		totfac= data[2]+data[3];
		if(totfac>0.000001)	QuatInterpol(q2, p2->quat, p3->quat, data[2] / totfac);
		else				QUATCOPY(q1, p3->quat);
		NormalQuat(q2);

		totfac = data[0]+data[1]+data[2]+data[3];
		if(totfac>0.000001)	QuatInterpol(quat, q1, q2, (data[0]+data[1]) / totfac);
		else				QUATCOPY(quat, q2);
		NormalQuat(quat);
		*/
		// XXX - find some way to make quat interpolation work correctly, above code fails in rare but nasty cases.
		QUATCOPY(quat, p1->quat);
	}

	if(radius)
		*radius= data[0]*p0->radius + data[1]*p1->radius + data[2]*p2->radius + data[3]*p3->radius;

	return 1;
}