static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist,
                                    bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
                                    float (*root)[3], float (*tip)[3], const int *selected, float scale)
{
	/* Create vertex group weights from envelopes */

	Bone *bone;
	bDeformGroup *dgroup;
	float distance;
	int i, iflip, j;
	bool use_topology = (mesh->editflag & ME_EDIT_MIRROR_TOPO) != 0;
	bool use_mask = false;

	if ((ob->mode & OB_MODE_WEIGHT_PAINT) &&
	    (mesh->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)))
	{
		use_mask = true;
	}

	/* for each vertex in the mesh */
	for (i = 0; i < mesh->totvert; i++) {

		if (use_mask && !(mesh->mvert[i].flag & SELECT)) {
			continue;
		}

		iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, NULL, i, use_topology) : -1;
		
		/* for each skinnable bone */
		for (j = 0; j < numbones; ++j) {
			if (!selected[j])
				continue;
			
			bone = bonelist[j];
			dgroup = dgrouplist[j];
			
			/* store the distance-factor from the vertex to the bone */
			distance = distfactor_to_bone(verts[i], root[j], tip[j],
			                              bone->rad_head * scale, bone->rad_tail * scale, bone->dist * scale);
			
			/* add the vert to the deform group if (weight != 0.0) */
			if (distance != 0.0f)
				ED_vgroup_vert_add(ob, dgroup, i, distance, WEIGHT_REPLACE);
			else
				ED_vgroup_vert_remove(ob, dgroup, i);
			
			/* do same for mirror */
			if (dgroupflip && dgroupflip[j] && iflip != -1) {
				if (distance != 0.0f)
					ED_vgroup_vert_add(ob, dgroupflip[j], iflip, distance,
					                   WEIGHT_REPLACE);
				else
					ED_vgroup_vert_remove(ob, dgroupflip[j], iflip);
			}
		}
	}
}
Exemplo n.º 2
0
/* removes from active defgroup, if allverts==0 only selected vertices */
static void vgroup_active_remove_verts(Object *ob, int allverts)
{
	EditVert *eve;
	MDeformVert *dvert;
	MDeformWeight *newdw;
	bDeformGroup *dg, *eg;
	int	i;

	dg=BLI_findlink(&ob->defbase, ob->actdef-1);
	if(!dg)
		return;

	if(ob->type == OB_MESH) {
		Mesh *me= ob->data;
		EditMesh *em = BKE_mesh_get_editmesh(me);

		for(eve=em->verts.first; eve; eve=eve->next){
			dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
		
			if(dvert && dvert->dw && ((eve->f & 1) || allverts)){
				for(i=0; i<dvert->totweight; i++){
					/* Find group */
					eg = BLI_findlink(&ob->defbase, dvert->dw[i].def_nr);
					if(eg == dg){
						dvert->totweight--;
						if(dvert->totweight){
							newdw = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), "deformWeight");
							
							if(dvert->dw){
								memcpy(newdw, dvert->dw, sizeof(MDeformWeight)*i);
								memcpy(newdw+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
								MEM_freeN(dvert->dw);
							}
							dvert->dw=newdw;
						}
						else{
							MEM_freeN(dvert->dw);
							dvert->dw=NULL;
							break;
						}
					}
				}
			}
		}
		BKE_mesh_end_editmesh(me, em);
	}
	else if(ob->type == OB_LATTICE) {
		Lattice *lt= vgroup_edit_lattice(ob);
		
		if(lt->dvert) {
			BPoint *bp;
			int a, tot= lt->pntsu*lt->pntsv*lt->pntsw;
				
			for(a=0, bp= lt->def; a<tot; a++, bp++) {
				if(allverts || (bp->f1 & SELECT))
					ED_vgroup_vert_remove(ob, dg, a);
			}
		}
	}
}
Exemplo n.º 3
0
static void vgroup_delete_object_mode(Object *ob)
{
	bDeformGroup *dg;
	MDeformVert *dvert, *dvert_array=NULL;
	int i, e, dvert_tot=0;
	
	dg = BLI_findlink(&ob->defbase, (ob->actdef-1));
	if(!dg)
		return;
	
	ED_vgroup_give_array(ob->data, &dvert_array, &dvert_tot);

	if(dvert_array) {
		for(i = 0; i < dvert_tot; i++) {
			dvert = dvert_array + i;
			if(dvert) {
				if(ED_vgroup_weight_get(dvert, (ob->actdef-1)))
					ED_vgroup_vert_remove(ob, dg, i);
			}
		}

		for(i = 0; i < dvert_tot; i++) {
			dvert = dvert_array+i;
			if(dvert) {
				for(e = 0; e < dvert->totweight; e++) {
					if(dvert->dw[e].def_nr > (ob->actdef-1))
						dvert->dw[e].def_nr--;
				}
			}
		}
	}

	vgroup_delete_update_users(ob, ob->actdef);

	/* Update the active deform index if necessary */
	if(ob->actdef == BLI_countlist(&ob->defbase))
		ob->actdef--;
  
	/* Remove the group */
	BLI_freelinkN(&ob->defbase, dg);
}
void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
                         bDeformGroup **dgrouplist, bDeformGroup **dgroupflip,
                         float (*root)[3], float (*tip)[3], int *selected, const char **err_str)
{
	LaplacianSystem *sys;
	MLoopTri *mlooptri;
	MPoly *mp;
	MLoop *ml;
	float solution, weight;
	int *vertsflipped = NULL, *mask = NULL;
	int a, tottri, j, bbone, firstsegment, lastsegment;
	bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;

	MVert *mvert = me->mvert;
	bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
	bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;

	*err_str = NULL;

	/* bone heat needs triangulated faces */
	tottri = poly_to_tri_count(me->totpoly, me->totloop);

	/* count triangles and create mask */
	if (ob->mode & OB_MODE_WEIGHT_PAINT &&
	    (use_face_sel || use_vert_sel))
	{
		mask = MEM_callocN(sizeof(int) * me->totvert, "heat_bone_weighting mask");

		/*  (added selectedVerts content for vertex mask, they used to just equal 1) */
		if (use_vert_sel) {
			for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) {
				for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) {
					mask[ml->v] = (mvert[ml->v].flag & SELECT) != 0;
				}
			}
		}
		else if (use_face_sel) {
			for (a = 0, mp = me->mpoly; a < me->totpoly; mp++, a++) {
				if (mp->flag & ME_FACE_SEL) {
					for (j = 0, ml = me->mloop + mp->loopstart; j < mp->totloop; j++, ml++) {
						mask[ml->v] = 1;
					}
				}
			}
		}
	}

	/* create laplacian */
	sys = laplacian_system_construct_begin(me->totvert, tottri, 1);

	sys->heat.tottri = poly_to_tri_count(me->totpoly, me->totloop);
	mlooptri = MEM_mallocN(sizeof(*sys->heat.mlooptri) * sys->heat.tottri, __func__);

	BKE_mesh_recalc_looptri(
	        me->mloop, me->mpoly,
	        me->mvert,
	        me->totloop, me->totpoly,
	        mlooptri);

	sys->heat.mlooptri = mlooptri;
	sys->heat.mloop = me->mloop;
	sys->heat.totvert = me->totvert;
	sys->heat.verts = verts;
	sys->heat.root = root;
	sys->heat.tip = tip;
	sys->heat.numsource = numsource;

	heat_ray_tree_create(sys);
	heat_laplacian_create(sys);

	laplacian_system_construct_end(sys);

	if (dgroupflip) {
		vertsflipped = MEM_callocN(sizeof(int) * me->totvert, "vertsflipped");
		for (a = 0; a < me->totvert; a++)
			vertsflipped[a] = mesh_get_x_mirror_vert(ob, NULL, a, use_topology);
	}
	
	/* compute weights per bone */
	for (j = 0; j < numsource; j++) {
		if (!selected[j])
			continue;

		firstsegment = (j == 0 || dgrouplist[j - 1] != dgrouplist[j]);
		lastsegment = (j == numsource - 1 || dgrouplist[j] != dgrouplist[j + 1]);
		bbone = !(firstsegment && lastsegment);

		/* clear weights */
		if (bbone && firstsegment) {
			for (a = 0; a < me->totvert; a++) {
				if (mask && !mask[a])
					continue;

				ED_vgroup_vert_remove(ob, dgrouplist[j], a);
				if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0)
					ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
			}
		}

		/* fill right hand side */
		laplacian_begin_solve(sys, -1);

		for (a = 0; a < me->totvert; a++)
			if (heat_source_closest(sys, a, j))
				laplacian_add_right_hand_side(sys, a,
				                              sys->heat.H[a] * sys->heat.p[a]);

		/* solve */
		if (laplacian_system_solve(sys)) {
			/* load solution into vertex groups */
			for (a = 0; a < me->totvert; a++) {
				if (mask && !mask[a])
					continue;

				solution = laplacian_system_get_solution(sys, a);
				
				if (bbone) {
					if (solution > 0.0f)
						ED_vgroup_vert_add(ob, dgrouplist[j], a, solution,
						                   WEIGHT_ADD);
				}
				else {
					weight = heat_limit_weight(solution);
					if (weight > 0.0f)
						ED_vgroup_vert_add(ob, dgrouplist[j], a, weight,
						                   WEIGHT_REPLACE);
					else
						ED_vgroup_vert_remove(ob, dgrouplist[j], a);
				}

				/* do same for mirror */
				if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
					if (bbone) {
						if (solution > 0.0f)
							ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a],
							                   solution, WEIGHT_ADD);
					}
					else {
						weight = heat_limit_weight(solution);
						if (weight > 0.0f)
							ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a],
							                   weight, WEIGHT_REPLACE);
						else
							ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
					}
				}
			}
		}
		else if (*err_str == NULL) {
			*err_str = N_("Bone Heat Weighting: failed to find solution for one or more bones");
			break;
		}

		/* remove too small vertex weights */
		if (bbone && lastsegment) {
			for (a = 0; a < me->totvert; a++) {
				if (mask && !mask[a])
					continue;

				weight = ED_vgroup_vert_weight(ob, dgrouplist[j], a);
				weight = heat_limit_weight(weight);
				if (weight <= 0.0f)
					ED_vgroup_vert_remove(ob, dgrouplist[j], a);

				if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
					weight = ED_vgroup_vert_weight(ob, dgroupflip[j], vertsflipped[a]);
					weight = heat_limit_weight(weight);
					if (weight <= 0.0f)
						ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
				}
			}
		}
	}

	/* free */
	if (vertsflipped) MEM_freeN(vertsflipped);
	if (mask) MEM_freeN(mask);

	heat_system_free(sys);

	laplacian_system_delete(sys);
}
Exemplo n.º 5
0
void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected, const char **err_str)
{
	LaplacianSystem *sys;
	MFace *mface;
	float solution, weight;
	int *vertsflipped = NULL, *mask= NULL;
	int a, totface, j, bbone, firstsegment, lastsegment;

	*err_str= NULL;

	/* count triangles and create mask */
	if(me->editflag & ME_EDIT_PAINT_MASK)
		mask= MEM_callocN(sizeof(int)*me->totvert, "heat_bone_weighting mask");

	for(totface=0, a=0, mface=me->mface; a<me->totface; a++, mface++) {
		totface++;
		if(mface->v4) totface++;

		if(mask && (mface->flag & ME_FACE_SEL)) {
			mask[mface->v1]= 1;
			mask[mface->v2]= 1;
			mask[mface->v3]= 1;
			if(mface->v4)
				mask[mface->v4]= 1;
		}
	}

	/* create laplacian */
	sys = laplacian_system_construct_begin(me->totvert, totface, 1);

	sys->heat.mface= me->mface;
	sys->heat.totface= me->totface;
	sys->heat.totvert= me->totvert;
	sys->heat.verts= verts;
	sys->heat.root= root;
	sys->heat.tip= tip;
	sys->heat.numsource= numsource;

	heat_ray_tree_create(sys);
	heat_laplacian_create(sys);

	laplacian_system_construct_end(sys);

	if(dgroupflip) {
		vertsflipped = MEM_callocN(sizeof(int)*me->totvert, "vertsflipped");
		for(a=0; a<me->totvert; a++)
			vertsflipped[a] = mesh_get_x_mirror_vert(ob, a);
	}

	/* compute weights per bone */
	for(j=0; j<numsource; j++) {
		if(!selected[j])
			continue;

		firstsegment= (j == 0 || dgrouplist[j-1] != dgrouplist[j]);
		lastsegment= (j == numsource-1 || dgrouplist[j] != dgrouplist[j+1]);
		bbone= !(firstsegment && lastsegment);

		/* clear weights */
		if(bbone && firstsegment) {
			for(a=0; a<me->totvert; a++) {
				if(mask && !mask[a])
					continue;

				ED_vgroup_vert_remove(ob, dgrouplist[j], a);
				if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0)
					ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
			}
		}

		/* fill right hand side */
		laplacian_begin_solve(sys, -1);

		for(a=0; a<me->totvert; a++)
			if(heat_source_closest(sys, a, j))
				laplacian_add_right_hand_side(sys, a,
					sys->heat.H[a]*sys->heat.p[a]);

		/* solve */
		if(laplacian_system_solve(sys)) {
			/* load solution into vertex groups */
			for(a=0; a<me->totvert; a++) {
				if(mask && !mask[a])
					continue;

				solution= laplacian_system_get_solution(a);
				
				if(bbone) {
					if(solution > 0.0f)
						ED_vgroup_vert_add(ob, dgrouplist[j], a, solution,
							WEIGHT_ADD);
				}
				else {
					weight= heat_limit_weight(solution);
					if(weight > 0.0f)
						ED_vgroup_vert_add(ob, dgrouplist[j], a, weight,
							WEIGHT_REPLACE);
					else
						ED_vgroup_vert_remove(ob, dgrouplist[j], a);
				}

				/* do same for mirror */
				if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
					if(bbone) {
						if(solution > 0.0f)
							ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a],
								solution, WEIGHT_ADD);
					}
					else {
						weight= heat_limit_weight(solution);
						if(weight > 0.0f)
							ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a],
								weight, WEIGHT_REPLACE);
						else
							ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
					}
				}
			}
		}
		else if(*err_str == NULL) {
			*err_str= "Bone Heat Weighting: failed to find solution for one or more bones";
			break;
		}

		/* remove too small vertex weights */
		if(bbone && lastsegment) {
			for(a=0; a<me->totvert; a++) {
				if(mask && !mask[a])
					continue;

				weight= ED_vgroup_vert_weight(ob, dgrouplist[j], a);
				weight= heat_limit_weight(weight);
				if(weight <= 0.0f)
					ED_vgroup_vert_remove(ob, dgrouplist[j], a);

				if(vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
					weight= ED_vgroup_vert_weight(ob, dgroupflip[j], vertsflipped[a]);
					weight= heat_limit_weight(weight);
					if(weight <= 0.0f)
						ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
				}
			}
		}
	}

	/* free */
	if(vertsflipped) MEM_freeN(vertsflipped);
	if(mask) MEM_freeN(mask);

	heat_system_free(sys);

	laplacian_system_delete(sys);
}
Exemplo n.º 6
0
static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event)
{
	Main *bmain= CTX_data_main(C);
	Scene *scene= CTX_data_scene(C);
//	Object *obedit= CTX_data_edit_object(C);
	View3D *v3d= CTX_wm_view3d(C);
//	BoundBox *bb;
	Object *ob= OBACT;
	TransformProperties *tfp= v3d->properties_storage;
	
	switch(event) {
	
	case B_REDR:
		ED_area_tag_redraw(CTX_wm_area(C));
		return; /* no notifier! */
		
	case B_OBJECTPANEL:
		DAG_id_tag_update(&ob->id, OB_RECALC_OB);
		break;

	
	case B_OBJECTPANELMEDIAN:
		if(ob) {
			v3d_editvertex_buts(NULL, v3d, ob, 1.0);
			DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
		}
		break;
		
		/* note; this case also used for parbone */
	case B_OBJECTPANELPARENT:
		if(ob) {
			if(ob->id.lib || test_parent_loop(ob->parent, ob) ) 
				ob->parent= NULL;
			else {
				DAG_scene_sort(bmain, scene);
				DAG_id_tag_update(&ob->id, OB_RECALC_OB);
			}
		}
		break;
		

	case B_ARMATUREPANEL3:  // rotate button on channel
		{
			bPoseChannel *pchan;
			float eul[3];
			
			pchan= get_active_posechannel(ob);
			if (!pchan) return;
			
			/* make a copy to eul[3], to allow TAB on buttons to work */
			eul[0]= (float)M_PI*tfp->ob_eul[0]/180.0f;
			eul[1]= (float)M_PI*tfp->ob_eul[1]/180.0f;
			eul[2]= (float)M_PI*tfp->ob_eul[2]/180.0f;
			
			if (pchan->rotmode == ROT_MODE_AXISANGLE) {
				float quat[4];
				/* convert to axis-angle, passing through quats  */
				eul_to_quat( quat,eul);
				quat_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,quat);
			}
			else if (pchan->rotmode == ROT_MODE_QUAT)
				eul_to_quat( pchan->quat,eul);
			else
				copy_v3_v3(pchan->eul, eul);
		}
		/* no break, pass on */
	case B_ARMATUREPANEL2:
		{
			ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
			DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
		}
		break;
	case B_TRANSFORMSPACEADD:
	{
		char names[sizeof(((TransformOrientation *)NULL)->name)]= "";
		BIF_createTransformOrientation(C, NULL, names, 1, 0);
		break;
	}
	case B_TRANSFORMSPACECLEAR:
		BIF_clearTransformOrientation(C);
		break;
		
#if 0 // XXX
	case B_WEIGHT0_0:
		wpaint->weight = 0.0f;
		break;
		
	case B_WEIGHT1_4:
		wpaint->weight = 0.25f;
		break;
	case B_WEIGHT1_2:
		wpaint->weight = 0.5f;
		break;
	case B_WEIGHT3_4:
		wpaint->weight = 0.75f;
		break;
	case B_WEIGHT1_0:
		wpaint->weight = 1.0f;
		break;
		
	case B_OPA1_8:
		wpaint->a = 0.125f;
		break;
	case B_OPA1_4:
		wpaint->a = 0.25f;
		break;
	case B_OPA1_2:
		wpaint->a = 0.5f;
		break;
	case B_OPA3_4:
		wpaint->a = 0.75f;
		break;
	case B_OPA1_0:
		wpaint->a = 1.0f;
		break;
#endif
	case B_CLR_WPAINT:
//		if(!multires_level1_test()) {
		{
			bDeformGroup *defGroup = BLI_findlink(&ob->defbase, ob->actdef-1);
			if(defGroup) {
				Mesh *me= ob->data;
				int a;
				for(a=0; a<me->totvert; a++)
					ED_vgroup_vert_remove (ob, defGroup, a);
				DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
			}
		}
		break;
	case B_RV3D_LOCKED:
	case B_RV3D_BOXVIEW:
	case B_RV3D_BOXCLIP:
		{
			ScrArea *sa= CTX_wm_area(C);
			ARegion *ar= sa->regionbase.last;
			RegionView3D *rv3d;
			short viewlock;
			
			ar= ar->prev;
			rv3d= ar->regiondata;
			viewlock= rv3d->viewlock;
			
			if((viewlock & RV3D_LOCKED)==0)
				viewlock= 0;
			else if((viewlock & RV3D_BOXVIEW)==0)
				viewlock &= ~RV3D_BOXCLIP;
			
			for(; ar; ar= ar->prev) {
				if(ar->alignment==RGN_ALIGN_QSPLIT) {
					rv3d= ar->regiondata;
					rv3d->viewlock= viewlock;
				}
			}
			
			if(rv3d->viewlock & RV3D_BOXVIEW)
				view3d_boxview_copy(sa, sa->regionbase.last);
			
			ED_area_tag_redraw(sa);
		}
		break;
	}

	/* default for now */
	WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, ob);
}