示例#1
0
/* Raytracing for vertex to bone/vertex visibility */
static void heat_ray_tree_create(LaplacianSystem *sys)
{
	MFace *mface = sys->heat.mface;
	float (*verts)[3] = sys->heat.verts;
	int totface = sys->heat.totface;
	int totvert = sys->heat.totvert;
	int a;

	sys->heat.bvhtree = BLI_bvhtree_new(totface, 0.0f, 4, 6);
	sys->heat.vface = MEM_callocN(sizeof(MFace*)*totvert, "HeatVFaces");

	for(a=0; a<totface; a++) {
		MFace *mf = mface+a;
		float bb[6];

		INIT_MINMAX(bb, bb+3);
		DO_MINMAX(verts[mf->v1], bb, bb+3);
		DO_MINMAX(verts[mf->v2], bb, bb+3);
		DO_MINMAX(verts[mf->v3], bb, bb+3);
		if(mf->v4) {
			DO_MINMAX(verts[mf->v4], bb, bb+3);
		}

		BLI_bvhtree_insert(sys->heat.bvhtree, a, bb, 2);
		
		//Setup inverse pointers to use on isect.orig
		sys->heat.vface[mf->v1]= mf;
		sys->heat.vface[mf->v2]= mf;
		sys->heat.vface[mf->v3]= mf;
		if(mf->v4) sys->heat.vface[mf->v4]= mf;
	}

	BLI_bvhtree_balance(sys->heat.bvhtree); 
}
示例#2
0
static void calc_ocval_face(float *v1, float *v2, float *v3, float *v4, short x, short y, short z, OcVal *ov)
{
	float min[3], max[3];
	int ocmin, ocmax;
	
	copy_v3_v3(min, v1);
	copy_v3_v3(max, v1);
	DO_MINMAX(v2, min, max);
	DO_MINMAX(v3, min, max);
	if(v4) {
		DO_MINMAX(v4, min, max);
	}
	
	ocmin= OCVALRES*(min[0]-x); 
	ocmax= OCVALRES*(max[0]-x);
	ov->ocx= BROW16(ocmin, ocmax);
	
	ocmin= OCVALRES*(min[1]-y); 
	ocmax= OCVALRES*(max[1]-y);
	ov->ocy= BROW16(ocmin, ocmax);
	
	ocmin= OCVALRES*(min[2]-z); 
	ocmax= OCVALRES*(max[2]-z);
	ov->ocz= BROW16(ocmin, ocmax);

}
示例#3
0
void RE_rayobject_merge_bb(RayObject *r, float *min, float *max)
{
	if (RE_rayobject_isRayFace(r)) {
		RayFace *face = (RayFace*) RE_rayobject_align(r);
		
		DO_MINMAX(face->v1, min, max);
		DO_MINMAX(face->v2, min, max);
		DO_MINMAX(face->v3, min, max);
		if (RE_rayface_isQuad(face)) DO_MINMAX(face->v4, min, max);
	}
	else if (RE_rayobject_isVlakPrimitive(r)) {
		VlakPrimitive *face = (VlakPrimitive*) RE_rayobject_align(r);
		RayFace nface;
		rayface_from_vlak(&nface, face->ob, face->face);

		DO_MINMAX(nface.v1, min, max);
		DO_MINMAX(nface.v2, min, max);
		DO_MINMAX(nface.v3, min, max);
		if (RE_rayface_isQuad(&nface)) DO_MINMAX(nface.v4, min, max);
	}
	else if (RE_rayobject_isRayAPI(r)) {
		r = RE_rayobject_align(r);
		r->api->bb(r, min, max);
	}
	else
		assert(0);
}
示例#4
0
/* find the bounding box of an objectinstance in global space */
void global_bounds_obi(Render *re, ObjectInstanceRen *obi, float *bbmin, float *bbmax)
{
	ObjectRen *obr = obi->obr;
	VolumePrecache *vp = obi->volume_precache;
	VertRen *ver= NULL;
	float co[3];
	int a;
	
	if (vp->bbmin != NULL && vp->bbmax != NULL) {
		copy_v3_v3(bbmin, vp->bbmin);
		copy_v3_v3(bbmax, vp->bbmax);
		return;
	}
	
	vp->bbmin = MEM_callocN(sizeof(float)*3, "volume precache min boundbox corner");
	vp->bbmax = MEM_callocN(sizeof(float)*3, "volume precache max boundbox corner");
	
	INIT_MINMAX(bbmin, bbmax);
	
	for(a=0; a<obr->totvert; a++) {
		if((a & 255)==0) ver= obr->vertnodes[a>>8].vert;
		else ver++;
		
		copy_v3_v3(co, ver->co);
		
		/* transformed object instance in camera space */
		if(obi->flag & R_TRANSFORMED)
			mul_m4_v3(obi->mat, co);
		
		/* convert to global space */
		mul_m4_v3(re->viewinv, co);
		
		DO_MINMAX(co, vp->bbmin, vp->bbmax);
	}
示例#5
0
static void hair_get_boundbox(ClothModifierData *clmd, float gmin[3], float gmax[3])
{
	Cloth *cloth = clmd->clothObject;
	Implicit_Data *data = cloth->implicit;
	unsigned int mvert_num = cloth->mvert_num;
	int i;
	
	INIT_MINMAX(gmin, gmax);
	for (i = 0; i < mvert_num; i++) {
		float x[3];
		BPH_mass_spring_get_motion_state(data, i, x, NULL);
		DO_MINMAX(x, gmin, gmax);
	}
}
static void RE_rayobject_instance_bb(RayObject *o, float *min, float *max)
{
    //TODO:
    // *better bb.. calculated without rotations of bb
    // *maybe cache that better-fitted-BB at the InstanceRayObject
    InstanceRayObject *obj = (InstanceRayObject *)o;

    float m[3], M[3], t[3];
    int i, j;
    INIT_MINMAX(m, M);
    RE_rayobject_merge_bb(obj->target, m, M);

    //There must be a faster way than rotating all the 8 vertexs of the BB
    for (i = 0; i < 8; i++) {
        for (j = 0; j < 3; j++) t[j] = (i & (1 << j)) ? M[j] : m[j];
        mul_m4_v3(obj->target2global, t);
        DO_MINMAX(t, min, max);
    }
}
示例#7
0
文件: sss.c 项目: mik0001/Blender
ScatterTree *scatter_tree_new(ScatterSettings *ss[3], float scale, float error,
	float (*co)[3], float (*color)[3], float *area, int totpoint)
{
	ScatterTree *tree;
	ScatterPoint *points, **refpoints;
	int i;

	/* allocate tree */
	tree= MEM_callocN(sizeof(ScatterTree), "ScatterTree");
	tree->scale= scale;
	tree->error= error;
	tree->totpoint= totpoint;

	tree->ss[0]= ss[0];
	tree->ss[1]= ss[1];
	tree->ss[2]= ss[2];

	points= MEM_callocN(sizeof(ScatterPoint)*totpoint, "ScatterPoints");
	refpoints= MEM_callocN(sizeof(ScatterPoint*)*totpoint, "ScatterRefPoints");

	tree->points= points;
	tree->refpoints= refpoints;

	/* build points */
	INIT_MINMAX(tree->min, tree->max);

	for(i=0; i<totpoint; i++) {
		copy_v3_v3(points[i].co, co[i]);
		copy_v3_v3(points[i].rad, color[i]);
		points[i].area= fabsf(area[i])/(tree->scale*tree->scale);
		points[i].back= (area[i] < 0.0f);

		mul_v3_fl(points[i].co, 1.0f/tree->scale);
		DO_MINMAX(points[i].co, tree->min, tree->max);

		refpoints[i]= points + i;
	}

	return tree;
}
示例#8
0
文件: mesh.c 项目: jinjoh/NOOR
void boundbox_mesh(Mesh *me, float *loc, float *size)
{
	MVert *mvert;
	BoundBox *bb;
	float min[3], max[3];
	float mloc[3], msize[3];
	int a;
	
	if(me->bb==0) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
	bb= me->bb;
	
	INIT_MINMAX(min, max);

	if (!loc) loc= mloc;
	if (!size) size= msize;
	
	mvert= me->mvert;
	for(a=0; a<me->totvert; a++, mvert++) {
		DO_MINMAX(mvert->co, min, max);
	}

	if(!me->totvert) {
		min[0] = min[1] = min[2] = -1.0f;
		max[0] = max[1] = max[2] = 1.0f;
	}

	loc[0]= (min[0]+max[0])/2.0f;
	loc[1]= (min[1]+max[1])/2.0f;
	loc[2]= (min[2]+max[2])/2.0f;
		
	size[0]= (max[0]-min[0])/2.0f;
	size[1]= (max[1]-min[1])/2.0f;
	size[2]= (max[2]-min[2])/2.0f;
	
	boundbox_set_from_min_max(bb, min, max);
}
示例#9
0
static void harmonic_coordinates_bind(Scene *UNUSED(scene), MeshDeformModifierData *mmd, MeshDeformBind *mdb)
{
	MDefBindInfluence *inf;
	MDefInfluence *mdinf;
	MDefCell *cell;
	float center[3], vec[3], maxwidth, totweight;
	int a, b, x, y, z, totinside, offset;

	/* compute bounding box of the cage mesh */
	INIT_MINMAX(mdb->min, mdb->max);

	for(a=0; a<mdb->totcagevert; a++)
		DO_MINMAX(mdb->cagecos[a], mdb->min, mdb->max);

	/* allocate memory */
	mdb->size= (2<<(mmd->gridsize-1)) + 2;
	mdb->size3= mdb->size*mdb->size*mdb->size;
	mdb->tag= MEM_callocN(sizeof(int)*mdb->size3, "MeshDeformBindTag");
	mdb->phi= MEM_callocN(sizeof(float)*mdb->size3, "MeshDeformBindPhi");
	mdb->totalphi= MEM_callocN(sizeof(float)*mdb->size3, "MeshDeformBindTotalPhi");
	mdb->boundisect= MEM_callocN(sizeof(*mdb->boundisect)*mdb->size3, "MDefBoundIsect");
	mdb->semibound= MEM_callocN(sizeof(int)*mdb->size3, "MDefSemiBound");

	mdb->inside= MEM_callocN(sizeof(int)*mdb->totvert, "MDefInside");

	if(mmd->flag & MOD_MDEF_DYNAMIC_BIND)
		mdb->dyngrid= MEM_callocN(sizeof(MDefBindInfluence*)*mdb->size3, "MDefDynGrid");
	else
		mdb->weights= MEM_callocN(sizeof(float)*mdb->totvert*mdb->totcagevert, "MDefWeights");

	mdb->memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");
	BLI_memarena_use_calloc(mdb->memarena);

	/* make bounding box equal size in all directions, add padding, and compute
	 * width of the cells */
	maxwidth = -1.0f;
	for(a=0; a<3; a++)
		if(mdb->max[a]-mdb->min[a] > maxwidth)
			maxwidth= mdb->max[a]-mdb->min[a];

	for(a=0; a<3; a++) {
		center[a]= (mdb->min[a]+mdb->max[a])*0.5f;
		mdb->min[a]= center[a] - maxwidth*0.5f;
		mdb->max[a]= center[a] + maxwidth*0.5f;

		mdb->width[a]= (mdb->max[a]-mdb->min[a])/(mdb->size-4);
		mdb->min[a] -= 2.1f*mdb->width[a];
		mdb->max[a] += 2.1f*mdb->width[a];

		mdb->width[a]= (mdb->max[a]-mdb->min[a])/mdb->size;
		mdb->halfwidth[a]= mdb->width[a]*0.5f;
	}

	progress_bar(0, "Setting up mesh deform system");

	totinside= 0;
	for(a=0; a<mdb->totvert; a++) {
		copy_v3_v3(vec, mdb->vertexcos[a]);
		mdb->inside[a]= meshdeform_inside_cage(mdb, vec);
		if(mdb->inside[a])
			totinside++;
	}

	/* free temporary MDefBoundIsects */
	BLI_memarena_free(mdb->memarena);
	mdb->memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "harmonic coords arena");

	/* start with all cells untyped */
	for(a=0; a<mdb->size3; a++)
		mdb->tag[a]= MESHDEFORM_TAG_UNTYPED;
	
	/* detect intersections and tag boundary cells */
	for(z=0; z<mdb->size; z++)
		for(y=0; y<mdb->size; y++)
			for(x=0; x<mdb->size; x++)
				meshdeform_add_intersections(mdb, x, y, z);

	/* compute exterior and interior tags */
	meshdeform_bind_floodfill(mdb);

	for(z=0; z<mdb->size; z++)
		for(y=0; y<mdb->size; y++)
			for(x=0; x<mdb->size; x++)
				meshdeform_check_semibound(mdb, x, y, z);

	/* solve */
	meshdeform_matrix_solve(mdb);

	/* assign results */
	if(mmd->flag & MOD_MDEF_DYNAMIC_BIND) {
		mmd->totinfluence= 0;
		for(a=0; a<mdb->size3; a++)
			for(inf=mdb->dyngrid[a]; inf; inf=inf->next)
				mmd->totinfluence++;

		/* convert MDefBindInfluences to smaller MDefInfluences */
		mmd->dyngrid= MEM_callocN(sizeof(MDefCell)*mdb->size3, "MDefDynGrid");
		mmd->dyninfluences= MEM_callocN(sizeof(MDefInfluence)*mmd->totinfluence, "MDefInfluence");
		offset= 0;
		for(a=0; a<mdb->size3; a++) {
			cell= &mmd->dyngrid[a];
			cell->offset= offset;

			totweight= 0.0f;
			mdinf= mmd->dyninfluences + cell->offset;
			for(inf=mdb->dyngrid[a]; inf; inf=inf->next, mdinf++) {
				mdinf->weight= inf->weight;
				mdinf->vertex= inf->vertex;
				totweight += mdinf->weight;
				cell->totinfluence++;
			}

			if(totweight > 0.0f) {
				mdinf= mmd->dyninfluences + cell->offset;
				for(b=0; b<cell->totinfluence; b++, mdinf++)
					mdinf->weight /= totweight;
			}

			offset += cell->totinfluence;
		}

		mmd->dynverts= mdb->inside;
		mmd->dyngridsize= mdb->size;
		copy_v3_v3(mmd->dyncellmin, mdb->min);
		mmd->dyncellwidth= mdb->width[0];
		MEM_freeN(mdb->dyngrid);
	}
	else {
		mmd->bindweights= mdb->weights;
		MEM_freeN(mdb->inside);
	}

	MEM_freeN(mdb->tag);
	MEM_freeN(mdb->phi);
	MEM_freeN(mdb->totalphi);
	MEM_freeN(mdb->boundisect);
	MEM_freeN(mdb->semibound);
	BLI_memarena_free(mdb->memarena);
}
示例#10
0
static void cuboid_do(
				   CastModifierData *cmd, Object *ob, DerivedMesh *dm,
	   float (*vertexCos)[3], int numVerts)
{
	MDeformVert *dvert = NULL;
	Object *ctrl_ob = NULL;

	int i, defgrp_index;
	int has_radius = 0;
	short flag;
	float fac, facm;
	float min[3], max[3], bb[8][3];
	float center[3] = {0.0f, 0.0f, 0.0f};
	float mat[4][4], imat[4][4];

	fac = cmd->fac;
	facm = 1.0f - fac;

	flag = cmd->flag;

	ctrl_ob = cmd->object;

	/* now we check which options the user wants */

	/* 1) (flag was checked in the "if (ctrl_ob)" block above) */
	/* 2) cmd->radius > 0.0f: only the vertices within this radius from
	* the center of the effect should be deformed */
	if (cmd->radius > FLT_EPSILON) has_radius = 1;

	/* 3) if we were given a vertex group name,
	* only those vertices should be affected */
	modifier_get_vgroup(ob, dm, cmd->defgrp_name, &dvert, &defgrp_index);

	if (ctrl_ob) {
		if(flag & MOD_CAST_USE_OB_TRANSFORM) {
			invert_m4_m4(ctrl_ob->imat, ctrl_ob->obmat);
			mul_m4_m4m4(mat, ob->obmat, ctrl_ob->imat);
			invert_m4_m4(imat, mat);
		}

		invert_m4_m4(ob->imat, ob->obmat);
		mul_v3_m4v3(center, ob->imat, ctrl_ob->obmat[3]);
	}

	if((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) {
		for(i = 0; i < 3; i++) {
			min[i] = -cmd->radius;
			max[i] = cmd->radius;
		}
	} else if(!(flag & MOD_CAST_SIZE_FROM_RADIUS) && cmd->size > 0) {
		for(i = 0; i < 3; i++) {
			min[i] = -cmd->size;
			max[i] = cmd->size;
		}
	} else {
		/* get bound box */
		/* We can't use the object's bound box because other modifiers
		* may have changed the vertex data. */
		INIT_MINMAX(min, max);

		/* Cast's center is the ob's own center in its local space,
		* by default, but if the user defined a control object, we use
		* its location, transformed to ob's local space. */
		if (ctrl_ob) {
			float vec[3];

			/* let the center of the ctrl_ob be part of the bound box: */
			DO_MINMAX(center, min, max);

			for (i = 0; i < numVerts; i++) {
				sub_v3_v3v3(vec, vertexCos[i], center);
				DO_MINMAX(vec, min, max);
			}
		}
		else {
			for (i = 0; i < numVerts; i++) {
				DO_MINMAX(vertexCos[i], min, max);
			}
		}

		/* we want a symmetric bound box around the origin */
		if (fabs(min[0]) > fabs(max[0])) max[0] = fabs(min[0]); 
		if (fabs(min[1]) > fabs(max[1])) max[1] = fabs(min[1]); 
		if (fabs(min[2]) > fabs(max[2])) max[2] = fabs(min[2]);
		min[0] = -max[0];
		min[1] = -max[1];
		min[2] = -max[2];
	}

	/* building our custom bounding box */
	bb[0][0] = bb[2][0] = bb[4][0] = bb[6][0] = min[0];
	bb[1][0] = bb[3][0] = bb[5][0] = bb[7][0] = max[0];
	bb[0][1] = bb[1][1] = bb[4][1] = bb[5][1] = min[1];
	bb[2][1] = bb[3][1] = bb[6][1] = bb[7][1] = max[1];
	bb[0][2] = bb[1][2] = bb[2][2] = bb[3][2] = min[2];
	bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2];

	/* ready to apply the effect, one vertex at a time;
	* tiny optimization: the code is separated (with parts repeated)
	 * in two possible cases:
	* with or w/o a vgroup. With lots of if's in the code below,
	* further optimizations are possible, if needed */
	if (dvert) { /* with a vgroup */
		float fac_orig = fac;
		for (i = 0; i < numVerts; i++) {
			MDeformWeight *dw = NULL;
			int j, octant, coord;
			float d[3], dmax, apex[3], fbb;
			float tmp_co[3];

			copy_v3_v3(tmp_co, vertexCos[i]);
			if(ctrl_ob) {
				if(flag & MOD_CAST_USE_OB_TRANSFORM) {
					mul_m4_v3(mat, tmp_co);
				} else {
					sub_v3_v3(tmp_co, center);
				}
			}

			if (has_radius) {
				if (fabsf(tmp_co[0]) > cmd->radius ||
								fabsf(tmp_co[1]) > cmd->radius ||
								fabsf(tmp_co[2]) > cmd->radius) continue;
			}

			for (j = 0; j < dvert[i].totweight; ++j) {
				if(dvert[i].dw[j].def_nr == defgrp_index) {
					dw = &dvert[i].dw[j];
					break;
				}
			}
			if (!dw) continue;

			fac = fac_orig * dw->weight;
			facm = 1.0f - fac;

			/* The algo used to project the vertices to their
			 * bounding box (bb) is pretty simple:
			 * for each vertex v:
			* 1) find in which octant v is in;
			* 2) find which outer "wall" of that octant is closer to v;
			* 3) calculate factor (var fbb) to project v to that wall;
			* 4) project. */

			/* find in which octant this vertex is in */
			octant = 0;
			if (tmp_co[0] > 0.0f) octant += 1;
			if (tmp_co[1] > 0.0f) octant += 2;
			if (tmp_co[2] > 0.0f) octant += 4;

			/* apex is the bb's vertex at the chosen octant */
			copy_v3_v3(apex, bb[octant]);

			/* find which bb plane is closest to this vertex ... */
			d[0] = tmp_co[0] / apex[0];
			d[1] = tmp_co[1] / apex[1];
			d[2] = tmp_co[2] / apex[2];

			/* ... (the closest has the higher (closer to 1) d value) */
			dmax = d[0];
			coord = 0;
			if (d[1] > dmax) {
				dmax = d[1];
				coord = 1;
			}
			if (d[2] > dmax) {
				/* dmax = d[2]; */ /* commented, we don't need it */
				coord = 2;
			}

			/* ok, now we know which coordinate of the vertex to use */

			if (fabsf(tmp_co[coord]) < FLT_EPSILON) /* avoid division by zero */
				continue;

			/* finally, this is the factor we wanted, to project the vertex
			* to its bounding box (bb) */
			fbb = apex[coord] / tmp_co[coord];

			/* calculate the new vertex position */
			if (flag & MOD_CAST_X)
				tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
			if (flag & MOD_CAST_Y)
				tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
			if (flag & MOD_CAST_Z)
				tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;

			if(ctrl_ob) {
				if(flag & MOD_CAST_USE_OB_TRANSFORM) {
					mul_m4_v3(imat, tmp_co);
				} else {
					add_v3_v3(tmp_co, center);
				}
			}

			copy_v3_v3(vertexCos[i], tmp_co);
		}
		return;
	}

	/* no vgroup (check previous case for comments about the code) */
	for (i = 0; i < numVerts; i++) {
		int octant, coord;
		float d[3], dmax, fbb, apex[3];
		float tmp_co[3];

		copy_v3_v3(tmp_co, vertexCos[i]);
		if(ctrl_ob) {
			if(flag & MOD_CAST_USE_OB_TRANSFORM) {
				mul_m4_v3(mat, tmp_co);
			} else {
				sub_v3_v3(tmp_co, center);
			}
		}

		if (has_radius) {
			if (fabsf(tmp_co[0]) > cmd->radius ||
						 fabsf(tmp_co[1]) > cmd->radius ||
						 fabsf(tmp_co[2]) > cmd->radius) continue;
		}

		octant = 0;
		if (tmp_co[0] > 0.0f) octant += 1;
		if (tmp_co[1] > 0.0f) octant += 2;
		if (tmp_co[2] > 0.0f) octant += 4;

		copy_v3_v3(apex, bb[octant]);

		d[0] = tmp_co[0] / apex[0];
		d[1] = tmp_co[1] / apex[1];
		d[2] = tmp_co[2] / apex[2];

		dmax = d[0];
		coord = 0;
		if (d[1] > dmax) {
			dmax = d[1];
			coord = 1;
		}
		if (d[2] > dmax) {
			/* dmax = d[2]; */ /* commented, we don't need it */
			coord = 2;
		}

		if (fabsf(tmp_co[coord]) < FLT_EPSILON)
			continue;

		fbb = apex[coord] / tmp_co[coord];

		if (flag & MOD_CAST_X)
			tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
		if (flag & MOD_CAST_Y)
			tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
		if (flag & MOD_CAST_Z)
			tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;

		if(ctrl_ob) {
			if(flag & MOD_CAST_USE_OB_TRANSFORM) {
				mul_m4_v3(imat, tmp_co);
			} else {
				add_v3_v3(tmp_co, center);
			}
		}

		copy_v3_v3(vertexCos[i], tmp_co);
	}
}
示例#11
0
static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event)
{
	ViewContext vc;
	EditVert *eve;
	float min[3], max[3];
	int done= 0;
	short use_proj;

	em_setup_viewcontext(C, &vc);

	use_proj= (vc.scene->toolsettings->snap_flag & SCE_SNAP) &&	(vc.scene->toolsettings->snap_mode==SCE_SNAP_MODE_FACE);
	
	invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); 
	
	INIT_MINMAX(min, max);
	
	for(eve= vc.em->verts.first; eve; eve= eve->next) {
		if(eve->f & SELECT) {
			DO_MINMAX(eve->co, min, max);
			done= 1;
		}
	}

	/* call extrude? */
	if(done) {
		const short rot_src= RNA_boolean_get(op->ptr, "rotate_source");
		EditEdge *eed;
		float vec[3], cent[3], mat[3][3];
		float nor[3]= {0.0, 0.0, 0.0};
		
		/* 2D normal calc */
		float mval_f[2];

		mval_f[0]= (float)event->mval[0];
		mval_f[1]= (float)event->mval[1];

		done= 0;

		/* calculate the normal for selected edges */
		for(eed= vc.em->edges.first; eed; eed= eed->next) {
			if(eed->f & SELECT) {
				float co1[3], co2[3];
				mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co);
				mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co);
				project_float_noclip(vc.ar, co1, co1);
				project_float_noclip(vc.ar, co2, co2);
				
				/* 2D rotate by 90d while adding.
				 *  (x, y) = (y, -x)
				 *
				 * accumulate the screenspace normal in 2D,
				 * with screenspace edge length weighting the result. */
				if(line_point_side_v2(co1, co2, mval_f) >= 0.0f) {
					nor[0] +=  (co1[1] - co2[1]);
					nor[1] += -(co1[0] - co2[0]);
				}
				else {
					nor[0] +=  (co2[1] - co1[1]);
					nor[1] += -(co2[0] - co1[0]);
				}
				done= 1;
			}
		}

		if(done) {
			float view_vec[3], cross[3];

			/* convert the 2D nomal into 3D */
			mul_mat3_m4_v3(vc.rv3d->viewinv, nor); /* worldspace */
			mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */
			
			/* correct the normal to be aligned on the view plane */
			copy_v3_v3(view_vec, vc.rv3d->viewinv[2]);
			mul_mat3_m4_v3(vc.obedit->imat, view_vec);
			cross_v3_v3v3(cross, nor, view_vec);
			cross_v3_v3v3(nor, view_vec, cross);
			normalize_v3(nor);
		}
		
		/* center */
		mid_v3_v3v3(cent, min, max);
		copy_v3_v3(min, cent);
		
		mul_m4_v3(vc.obedit->obmat, min);	// view space
		view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE);
		mul_m4_v3(vc.obedit->imat, min); // back in object space
		
		sub_v3_v3(min, cent);
		
		/* calculate rotation */
		unit_m3(mat);
		if(done) {
			float dot;
			
			copy_v3_v3(vec, min);
			normalize_v3(vec);
			dot= dot_v3v3(vec, nor);

			if( fabs(dot)<0.999) {
				float cross[3], si, q1[4];
				
				cross_v3_v3v3(cross, nor, vec);
				normalize_v3(cross);
				dot= 0.5f*saacos(dot);
				
				/* halve the rotation if its applied twice */
				if(rot_src) dot *= 0.5f;
				
				si= (float)sin(dot);
				q1[0]= (float)cos(dot);
				q1[1]= cross[0]*si;
				q1[2]= cross[1]*si;
				q1[3]= cross[2]*si;				
				quat_to_mat3( mat,q1);
			}
		}
		
		if(rot_src) {
			rotateflag(vc.em, SELECT, cent, mat);
			/* also project the source, for retopo workflow */
			if(use_proj)
				EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);
		}
		
		extrudeflag(vc.obedit, vc.em, SELECT, nor, 0);
		rotateflag(vc.em, SELECT, cent, mat);
		translateflag(vc.em, SELECT, min);
		
		recalc_editnormals(vc.em);
	}
	else if(vc.em->selectmode & SCE_SELECT_VERTEX) {

		float imat[4][4];
		const float *curs= give_cursor(vc.scene, vc.v3d);
		
		copy_v3_v3(min, curs);
		view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE);

		eve= addvertlist(vc.em, 0, NULL);

		invert_m4_m4(imat, vc.obedit->obmat);
		mul_v3_m4v3(eve->co, imat, min);
		
		eve->f= SELECT;
	}

	if(use_proj)
		EM_project_snap_verts(C, vc.ar, vc.obedit, vc.em);

	WM_event_add_notifier(C, NC_GEOM|ND_DATA, vc.obedit->data); 
	DAG_id_tag_update(vc.obedit->data, 0);
	
	return OPERATOR_FINISHED;
}
示例#12
0
文件: view3d_snap.c 项目: jinjoh/NOOR
/* mode: 1 = proportional, 2 = all joints (for bones only) */
static void make_trans_verts(Object *obedit, float *min, float *max, int mode)	
{
	Nurb *nu;
	BezTriple *bezt;
	BPoint *bp;
	TransVert *tv=NULL;
	MetaElem *ml;
	EditVert *eve;
	EditBone	*ebo;
	float total, center[3], centroid[3];
	int a;

	tottrans= 0; // global!
	
	INIT_MINMAX(min, max);
	centroid[0]=centroid[1]=centroid[2]= 0.0;
	
	if(obedit->type==OB_MESH) {
		Mesh *me= obedit->data;
		EditMesh *em= me->edit_mesh;
		int proptrans= 0;
		
		// transform now requires awareness for select mode, so we tag the f1 flags in verts
		tottrans= 0;
		if(em->selectmode & SCE_SELECT_VERTEX) {
			for(eve= em->verts.first; eve; eve= eve->next) {
				if(eve->h==0 && (eve->f & SELECT)) {
					eve->f1= SELECT;
					tottrans++;
				}
				else eve->f1= 0;
			}
		}
		else if(em->selectmode & SCE_SELECT_EDGE) {
			EditEdge *eed;
			for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
			for(eed= em->edges.first; eed; eed= eed->next) {
				if(eed->h==0 && (eed->f & SELECT)) eed->v1->f1= eed->v2->f1= SELECT;
			}
			for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
		}
		else {
			EditFace *efa;
			for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
			for(efa= em->faces.first; efa; efa= efa->next) {
				if(efa->h==0 && (efa->f & SELECT)) {
					efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
					if(efa->v4) efa->v4->f1= SELECT;
				}
			}
			for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
		}
		
		/* proportional edit exception... */
		if((mode & 1) && tottrans) {
			for(eve= em->verts.first; eve; eve= eve->next) {
				if(eve->h==0) {
					eve->f1 |= 2;
					proptrans++;
				}
			}
			if(proptrans>tottrans) tottrans= proptrans;
		}
		
		/* and now make transverts */
		if(tottrans) {
			tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");

			for(eve= em->verts.first; eve; eve= eve->next) {
				if(eve->f1) {
					VECCOPY(tv->oldloc, eve->co);
					tv->loc= eve->co;
					if(eve->no[0]!=0.0 || eve->no[1]!=0.0 ||eve->no[2]!=0.0)
						tv->nor= eve->no; // note this is a hackish signal (ton)
					tv->flag= eve->f1 & SELECT;
					tv++;
				}
			}
		}
	}
	else if (obedit->type==OB_ARMATURE){
		bArmature *arm= obedit->data;
		int totmalloc= BLI_countlist(arm->edbo);
		
		tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts armature");
		
		for (ebo= arm->edbo->first; ebo; ebo=ebo->next){
			if(ebo->layer & arm->layer) {
				short tipsel= (ebo->flag & BONE_TIPSEL);
				short rootsel= (ebo->flag & BONE_ROOTSEL);
				short rootok= (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && ebo->parent->flag & BONE_TIPSEL));
				
				if ((tipsel && rootsel) || (rootsel)) {
					/* Don't add the tip (unless mode & 2, for getting all joints), 
					 * otherwise we get zero-length bones as tips will snap to the same
					 * location as heads. 
					 */
					if (rootok) {
						VECCOPY (tv->oldloc, ebo->head);
						tv->loc= ebo->head;
						tv->nor= NULL;
						tv->flag= 1;
						tv++;
						tottrans++;
					}	
					
					if ((mode & 2) && (tipsel)) {
						VECCOPY (tv->oldloc, ebo->tail);
						tv->loc= ebo->tail;
						tv->nor= NULL;
						tv->flag= 1;
						tv++;
						tottrans++;
					}					
				}
				else if (tipsel) {
					VECCOPY (tv->oldloc, ebo->tail);
					tv->loc= ebo->tail;
					tv->nor= NULL;
					tv->flag= 1;
					tv++;
					tottrans++;
				}
			}			
		}
	}
	else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
		Curve *cu= obedit->data;
		int totmalloc= 0;
		
		for(nu= cu->editnurb->first; nu; nu= nu->next) {
			if(nu->type == CU_BEZIER)
				totmalloc += 3*nu->pntsu;
			else
				totmalloc += nu->pntsu*nu->pntsv;
		}
		tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts curve");

		nu= cu->editnurb->first;
		while(nu) {
			if(nu->type == CU_BEZIER) {
				a= nu->pntsu;
				bezt= nu->bezt;
				while(a--) {
					if(bezt->hide==0) {
						if((mode & 1) || (bezt->f1 & SELECT)) {
							VECCOPY(tv->oldloc, bezt->vec[0]);
							tv->loc= bezt->vec[0];
							tv->flag= bezt->f1 & SELECT;
							tv++;
							tottrans++;
						}
						if((mode & 1) || (bezt->f2 & SELECT)) {
							VECCOPY(tv->oldloc, bezt->vec[1]);
							tv->loc= bezt->vec[1];
							tv->val= &(bezt->alfa);
							tv->oldval= bezt->alfa;
							tv->flag= bezt->f2 & SELECT;
							tv++;
							tottrans++;
						}
						if((mode & 1) || (bezt->f3 & SELECT)) {
							VECCOPY(tv->oldloc, bezt->vec[2]);
							tv->loc= bezt->vec[2];
							tv->flag= bezt->f3 & SELECT;
							tv++;
							tottrans++;
						}
					}
					bezt++;
				}
			}
			else {
				a= nu->pntsu*nu->pntsv;
				bp= nu->bp;
				while(a--) {
					if(bp->hide==0) {
						if((mode & 1) || (bp->f1 & SELECT)) {
							VECCOPY(tv->oldloc, bp->vec);
							tv->loc= bp->vec;
							tv->val= &(bp->alfa);
							tv->oldval= bp->alfa;
							tv->flag= bp->f1 & SELECT;
							tv++;
							tottrans++;
						}
					}
					bp++;
				}
			}
			nu= nu->next;
		}
	}
	else if(obedit->type==OB_MBALL) {
		MetaBall *mb= obedit->data;
		int totmalloc= BLI_countlist(mb->editelems);
		
		tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts mball");
		
		ml= mb->editelems->first;
		while(ml) {
			if(ml->flag & SELECT) {
				tv->loc= &ml->x;
				VECCOPY(tv->oldloc, tv->loc);
				tv->val= &(ml->rad);
				tv->oldval= ml->rad;
				tv->flag= 1;
				tv++;
				tottrans++;
			}
			ml= ml->next;
		}
	}
	else if(obedit->type==OB_LATTICE) {
		Lattice *lt= obedit->data;
		
		bp= lt->editlatt->def;
		
		a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
		
		tv=transvmain= MEM_callocN(a*sizeof(TransVert), "maketransverts curve");
		
		while(a--) {
			if((mode & 1) || (bp->f1 & SELECT)) {
				if(bp->hide==0) {
					VECCOPY(tv->oldloc, bp->vec);
					tv->loc= bp->vec;
					tv->flag= bp->f1 & SELECT;
					tv++;
					tottrans++;
				}
			}
			bp++;
		}
	}
	
	/* cent etc */
	tv= transvmain;
	total= 0.0;
	for(a=0; a<tottrans; a++, tv++) {
		if(tv->flag & SELECT) {
			centroid[0]+= tv->oldloc[0];
			centroid[1]+= tv->oldloc[1];
			centroid[2]+= tv->oldloc[2];
			total+= 1.0;
			DO_MINMAX(tv->oldloc, min, max);
		}
	}
	if(total!=0.0) {
		centroid[0]/= total;
		centroid[1]/= total;
		centroid[2]/= total;
	}

	center[0]= (min[0]+max[0])/2.0;
	center[1]= (min[1]+max[1])/2.0;
	center[2]= (min[2]+max[2])/2.0;
	
}
/**
 * Iterates over ALL objects in the scene and all of its sets, including
 * making all duplis(not only metas). Copies metas to mainb array.
 * Computes bounding boxes for building BVH. */
static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob)
{
	Scene *sce_iter = scene;
	Base *base;
	Object *bob;
	MetaBall *mb;
	const MetaElem *ml;
	float obinv[4][4], obmat[4][4];
	unsigned int i;
	int obnr, zero_size = 0;
	char obname[MAX_ID_NAME];
	SceneBaseIter iter;

	copy_m4_m4(obmat, ob->obmat);   /* to cope with duplicators from BKE_scene_base_iter_next */
	invert_m4_m4(obinv, ob->obmat);

	BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');

	/* make main array */
	BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
	while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &bob)) {
		if (bob->type == OB_MBALL) {
			zero_size = 0;
			ml = NULL;

			if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) {
				mb = ob->data;

				if (mb->editelems) ml = mb->editelems->first;
				else ml = mb->elems.first;
			}
			else {
				char name[MAX_ID_NAME];
				int nr;

				BLI_split_name_num(name, &nr, bob->id.name + 2, '.');
				if (STREQ(obname, name)) {
					mb = bob->data;

					if (mb->editelems) ml = mb->editelems->first;
					else ml = mb->elems.first;
				}
			}

			/* when metaball object has zero scale, then MetaElem to this MetaBall
			 * will not be put to mainb array */
			if (has_zero_axis_m4(bob->obmat)) {
				zero_size = 1;
			}
			else if (bob->parent) {
				struct Object *pob = bob->parent;
				while (pob) {
					if (has_zero_axis_m4(pob->obmat)) {
						zero_size = 1;
						break;
					}
					pob = pob->parent;
				}
			}

			if (zero_size) {
				while (ml) {
					ml = ml->next;
				}
			}
			else {
				while (ml) {
					if (!(ml->flag & MB_HIDE)) {
						float pos[4][4], rot[4][4];
						float expx, expy, expz;
						float tempmin[3], tempmax[3];

						MetaElem *new_ml;

						/* make a copy because of duplicates */
						new_ml = BLI_memarena_alloc(process->pgn_elements, sizeof(MetaElem));
						*(new_ml) = *ml;
						new_ml->bb = BLI_memarena_alloc(process->pgn_elements, sizeof(BoundBox));
						new_ml->mat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float));
						new_ml->imat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float));

						/* too big stiffness seems only ugly due to linear interpolation
						* no need to have possibility for too big stiffness */
						if (ml->s > 10.0f) new_ml->s = 10.0f;
						else new_ml->s = ml->s;

						/* if metaball is negative, set stiffness negative */
						if (new_ml->flag & MB_NEGATIVE) new_ml->s = -new_ml->s;

						/* Translation of MetaElem */
						unit_m4(pos);
						pos[3][0] = ml->x;
						pos[3][1] = ml->y;
						pos[3][2] = ml->z;

						/* Rotation of MetaElem is stored in quat */
						quat_to_mat4(rot, ml->quat);

						/* basis object space -> world -> ml object space -> position -> rotation -> ml local space */
						mul_m4_series((float(*)[4])new_ml->mat, obinv, bob->obmat, pos, rot);
						/* ml local space -> basis object space */
						invert_m4_m4((float(*)[4])new_ml->imat, (float(*)[4])new_ml->mat);

						/* rad2 is inverse of squared radius */
						new_ml->rad2 = 1 / (ml->rad * ml->rad);

						/* initial dimensions = radius */
						expx = ml->rad;
						expy = ml->rad;
						expz = ml->rad;

						switch (ml->type) {
							case MB_BALL:
								break;
							case MB_CUBE: /* cube is "expanded" by expz, expy and expx */
								expz += ml->expz;
								/* fall through */
							case MB_PLANE: /* plane is "expanded" by expy and expx */
								expy += ml->expy;
								/* fall through */
							case MB_TUBE: /* tube is "expanded" by expx */
								expx += ml->expx;
								break;
							case MB_ELIPSOID: /* ellipsoid is "stretched" by exp* */
								expx *= ml->expx;
								expy *= ml->expy;
								expz *= ml->expz;
								break;
						}

						/* untransformed Bounding Box of MetaElem */
						/* TODO, its possible the elem type has been changed and the exp* values can use a fallback */
						copy_v3_fl3(new_ml->bb->vec[0], -expx, -expy, -expz);  /* 0 */
						copy_v3_fl3(new_ml->bb->vec[1], +expx, -expy, -expz);  /* 1 */
						copy_v3_fl3(new_ml->bb->vec[2], +expx, +expy, -expz);  /* 2 */
						copy_v3_fl3(new_ml->bb->vec[3], -expx, +expy, -expz);  /* 3 */
						copy_v3_fl3(new_ml->bb->vec[4], -expx, -expy, +expz);  /* 4 */
						copy_v3_fl3(new_ml->bb->vec[5], +expx, -expy, +expz);  /* 5 */
						copy_v3_fl3(new_ml->bb->vec[6], +expx, +expy, +expz);  /* 6 */
						copy_v3_fl3(new_ml->bb->vec[7], -expx, +expy, +expz);  /* 7 */

						/* transformation of Metalem bb */
						for (i = 0; i < 8; i++)
							mul_m4_v3((float(*)[4])new_ml->mat, new_ml->bb->vec[i]);

						/* find max and min of transformed bb */
						INIT_MINMAX(tempmin, tempmax);
						for (i = 0; i < 8; i++) {
							DO_MINMAX(new_ml->bb->vec[i], tempmin, tempmax);
						}

						/* set only point 0 and 6 - AABB of Metaelem */
						copy_v3_v3(new_ml->bb->vec[0], tempmin);
						copy_v3_v3(new_ml->bb->vec[6], tempmax);

						/* add new_ml to mainb[] */
						if (UNLIKELY(process->totelem == process->mem)) {
							process->mem = process->mem * 2 + 10;
							process->mainb = MEM_reallocN(process->mainb, sizeof(MetaElem *) * process->mem);
						}
						process->mainb[process->totelem++] = new_ml;
					}
					ml = ml->next;
				}
			}
		}
	}

	/* compute AABB of all Metaelems */
	if (process->totelem > 0) {
		copy_v3_v3(process->allbb.min, process->mainb[0]->bb->vec[0]);
		copy_v3_v3(process->allbb.max, process->mainb[0]->bb->vec[6]);
		for (i = 1; i < process->totelem; i++)
			make_box_union(process->mainb[i]->bb, &process->allbb, &process->allbb);
	}
}
示例#14
0
void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, char *vgroup, short defaxis)
{
	Curve *cu;
	int a, flag;
	CurveDeform cd;
	int use_vgroups;

	if(cuOb->type != OB_CURVE)
		return;

	cu = cuOb->data;
	flag = cu->flag;
	cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist

	init_curve_deform(cuOb, target, &cd, (cu->flag & CU_STRETCH)==0);

	/* dummy bounds, keep if CU_DEFORM_BOUNDS_OFF is set */
	if(defaxis < 3) {
		cd.dmin[0]= cd.dmin[1]= cd.dmin[2]= 0.0f;
		cd.dmax[0]= cd.dmax[1]= cd.dmax[2]= 1.0f;
	}
	else {
		/* negative, these bounds give a good rest position */
		cd.dmin[0]= cd.dmin[1]= cd.dmin[2]= -1.0f;
		cd.dmax[0]= cd.dmax[1]= cd.dmax[2]=  0.0f;
	}
	
	/* check whether to use vertex groups (only possible if target is a Mesh)
	 * we want either a Mesh with no derived data, or derived data with
	 * deformverts
	 */
	if(target && target->type==OB_MESH) {
		/* if there's derived data without deformverts, don't use vgroups */
		if(dm && !dm->getVertData(dm, 0, CD_MDEFORMVERT))
			use_vgroups = 0;
		else
			use_vgroups = 1;
	} else
		use_vgroups = 0;
	
	if(vgroup && vgroup[0] && use_vgroups) {
		Mesh *me= target->data;
		int index= defgroup_name_index(target, vgroup);

		if(index != -1 && (me->dvert || dm)) {
			MDeformVert *dvert = me->dvert;
			float vec[3];
			float weight;
	

			if(cu->flag & CU_DEFORM_BOUNDS_OFF) {
				/* dummy bounds */
				cd.dmin[0]= cd.dmin[1]= cd.dmin[2]= 0.0f;
				cd.dmax[0]= cd.dmax[1]= cd.dmax[2]= 1.0f;
				
				dvert = me->dvert;
				for(a = 0; a < numVerts; a++, dvert++) {
					if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
					weight= defvert_find_weight(dvert, index);
	
					if(weight > 0.0f) {
						mul_m4_v3(cd.curvespace, vertexCos[a]);
						copy_v3_v3(vec, vertexCos[a]);
						calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
						interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
						mul_m4_v3(cd.objectspace, vertexCos[a]);
					}
				}
			}
			else {
				/* set mesh min/max bounds */
				INIT_MINMAX(cd.dmin, cd.dmax);
	
				for(a = 0; a < numVerts; a++, dvert++) {
					if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
					
					if(defvert_find_weight(dvert, index) > 0.0f) {
						mul_m4_v3(cd.curvespace, vertexCos[a]);
						DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
					}
				}
	
				dvert = me->dvert;
				for(a = 0; a < numVerts; a++, dvert++) {
					if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
					
					weight= defvert_find_weight(dvert, index);
	
					if(weight > 0.0f) {
						copy_v3_v3(vec, vertexCos[a]);
						calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
						interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
						mul_m4_v3(cd.objectspace, vertexCos[a]);
					}
				}
			}
		}
	}
	else {
		if(cu->flag & CU_DEFORM_BOUNDS_OFF) {
			for(a = 0; a < numVerts; a++) {
				mul_m4_v3(cd.curvespace, vertexCos[a]);
				calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL);
				mul_m4_v3(cd.objectspace, vertexCos[a]);
			}
		}
		else {
			/* set mesh min max bounds */
			INIT_MINMAX(cd.dmin, cd.dmax);
				
			for(a = 0; a < numVerts; a++) {
				mul_m4_v3(cd.curvespace, vertexCos[a]);
				DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
			}
	
			for(a = 0; a < numVerts; a++) {
				calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL);
				mul_m4_v3(cd.objectspace, vertexCos[a]);
			}
		}
	}
	cu->flag = flag;
}