[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [60185] trunk/blender/source/blender/ editors: vertex group blend, support for blending multiple groups at once.

Campbell Barton ideasman42 at gmail.com
Tue Sep 17 08:47:48 CEST 2013


Revision: 60185
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=60185
Author:   campbellbarton
Date:     2013-09-17 06:47:47 +0000 (Tue, 17 Sep 2013)
Log Message:
-----------
vertex group blend, support for blending multiple groups at once.

Modified Paths:
--------------
    trunk/blender/source/blender/editors/include/ED_object.h
    trunk/blender/source/blender/editors/object/object_vgroup.c

Modified: trunk/blender/source/blender/editors/include/ED_object.h
===================================================================
--- trunk/blender/source/blender/editors/include/ED_object.h	2013-09-17 04:19:45 UTC (rev 60184)
+++ trunk/blender/source/blender/editors/include/ED_object.h	2013-09-17 06:47:47 UTC (rev 60185)
@@ -208,6 +208,8 @@
 
 bool *ED_vgroup_subset_from_select_type(struct Object *ob, enum eVGroupSelect subset_type,
                                         int *r_vgroup_tot, int *r_subset_count);
+void ED_vgroup_subset_to_index_array(const bool *vgroup_validmap, const int vgroup_tot,
+                                     int *r_vgroup_subset_map);
 
 struct EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
         const struct bContext *C,

Modified: trunk/blender/source/blender/editors/object/object_vgroup.c
===================================================================
--- trunk/blender/source/blender/editors/object/object_vgroup.c	2013-09-17 04:19:45 UTC (rev 60184)
+++ trunk/blender/source/blender/editors/object/object_vgroup.c	2013-09-17 06:47:47 UTC (rev 60185)
@@ -51,6 +51,7 @@
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
 #include "BLI_utildefines.h"
+#include "BLI_linklist_stack.h"
 
 #include "BLF_translation.h"
 
@@ -1418,6 +1419,20 @@
 	return vgroup_validmap;
 }
 
+/**
+ * store indices from the vgroup_validmap (faster lookups in some cases)
+ */
+void ED_vgroup_subset_to_index_array(const bool *vgroup_validmap, const int vgroup_tot,
+                                     int *r_vgroup_subset_map)
+{
+	int i, j = 0;
+	for (i = 0; i < vgroup_tot; i++) {
+		if (vgroup_validmap[i]) {
+			r_vgroup_subset_map[j++] = i;
+		}
+	}
+}
+
 static void vgroup_normalize(Object *ob)
 {
 	MDeformWeight *dw;
@@ -2003,138 +2018,120 @@
 	}
 }
 
-static void vgroup_blend(Object *ob, const float fac)
+static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot,
+                                const int subset_count,
+                                const float fac)
 {
-	MDeformVert *dv;
-	MDeformWeight *dw;
+	const float ifac = 1.0f - fac;
+	MDeformVert **dvert_array = NULL;
 	int i, dvert_tot = 0;
-	const int def_nr = ob->actdef - 1;
+	int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count);
+	float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count);
 
-	BLI_assert(fac >= 0.0f && fac <= 1.0f);
+	BMEditMesh *em = BKE_editmesh_from_object(ob);
+	BMesh *bm = em ? em->bm : NULL;
+	Mesh  *me = em ? NULL   : ob->data;
 
-	if (ob->type != OB_MESH) {
-		return;
-	}
+	MeshElemMap *emap ;
+	int *emap_mem;
 
-	if (BLI_findlink(&ob->defbase, def_nr)) {
-		const float ifac = 1.0f - fac;
+	BLI_SMALLSTACK_DECLARE(dv_stack, MDeformVert *);
 
-		BMEditMesh *em = BKE_editmesh_from_object(ob);
-		BMesh *bm = em ? em->bm : NULL;
-		Mesh  *me = em ? NULL   : ob->data;
+	ED_vgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
+	ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
+	memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count);
 
-		/* bmesh only*/
-		BMEdge *eed;
-		BMVert *eve;
-		BMIter iter;
+	if (bm) {
+		emap = NULL;
+		emap_mem = NULL;
+	}
+	else {
+		BKE_mesh_vert_edge_map_create(&emap, &emap_mem,
+		                              me->medge, me->totvert, me->totedge);
+	}
 
-		/* mesh only */
-		MDeformVert *dvert_array = NULL;
 
+	for (i = 0; i < dvert_tot; i++) {
+		MDeformVert *dv;
+		int dv_stack_tot = 0;
+		int j;
+		/* in case its not selected */
 
-		float *vg_weights;
-		float *vg_users;
-		int sel1, sel2;
-
 		if (bm) {
-			BM_mesh_elem_index_ensure(bm, BM_VERT);
-			dvert_tot = bm->totvert;
-		}
-		else {
-			dvert_tot = me->totvert;
-			dvert_array = me->dvert;
-		}
+			BMVert *v = EDBM_vert_at_index(em, i);
+			if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+				BMIter eiter;
+				BMEdge *e;
+				BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+					BMVert *v_other = BM_edge_other_vert(e, v);
+					const int i_other = BM_elem_index_get(v_other);
 
-		vg_weights = MEM_callocN(sizeof(float) * dvert_tot, "vgroup_blend_f");
-		vg_users = MEM_callocN(sizeof(int) * dvert_tot, "vgroup_blend_i");
-
-		if (bm) {
-			const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
-
-			BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
-				sel1 = BM_elem_flag_test(eed->v1, BM_ELEM_SELECT);
-				sel2 = BM_elem_flag_test(eed->v2, BM_ELEM_SELECT);
-
-				if (sel1 != sel2) {
-					int i1 /* , i2 */;
-					/* i1 is always the selected one */
-					if (sel1) {
-						i1 = BM_elem_index_get(eed->v1);
-						/* i2 = BM_elem_index_get(eed->v2); */ /* UNUSED */
-						eve = eed->v2;
+					if (BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) {
+						dv = dvert_array[i_other];
+						BLI_SMALLSTACK_PUSH(dv_stack, dv);
+						dv_stack_tot++;
 					}
-					else {
-						/* i2 = BM_elem_index_get(eed->v1); */ /* UNUSED */
-						i1 = BM_elem_index_get(eed->v2);
-						eve = eed->v1;
-					}
-
-					dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
-					dw = defvert_find_index(dv, def_nr);
-					if (dw) {
-						vg_weights[i1] += dw->weight;
-					}
-					vg_users[i1]++;
 				}
 			}
+		}
+		else {
+			MVert *v = &me->mvert[i];
+			if (v->flag & SELECT) {
+				for (j = 0; j < emap[i].count; j++) {
+					MEdge *e = &me->medge[emap[i].indices[j]];
+					const int i_other = (e->v1 == i ? e->v2 : e->v1);
+					MVert *v_other = &me->mvert[i_other];
 
-			BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
-				if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && vg_users[i] > 0) {
-					dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
-
-					dw = defvert_verify_index(dv, def_nr);
-					dw->weight = (fac * (vg_weights[i] / (float)vg_users[i])) + (ifac * dw->weight);
-					/* in case of division errors */
-					CLAMP(dw->weight, 0.0f, 1.0f);
+					if ((v_other->flag & SELECT) == 0) {
+						dv = dvert_array[i_other];
+						BLI_SMALLSTACK_PUSH(dv_stack, dv);
+						dv_stack_tot++;
+					}
 				}
 			}
 		}
-		else {
-			MEdge *ed = me->medge;
-			MVert *mv;
 
-			for (i = 0; i < me->totedge; i++, ed++) {
-				sel1 = me->mvert[ed->v1].flag & SELECT;
-				sel2 = me->mvert[ed->v2].flag & SELECT;
+		if (dv_stack_tot) {
+			const float dv_mul = 1.0f / (float)dv_stack_tot;
 
-				if (sel1 != sel2) {
-					int i1, i2;
-					/* i1 is always the selected one */
-					if (sel1) {
-						i1 = ed->v1;
-						i2 = ed->v2;
-					}
-					else {
-						i2 = ed->v1;
-						i1 = ed->v2;
-					}
-
-					dv = &dvert_array[i2];
-					dw = defvert_find_index(dv, def_nr);
-					if (dw) {
-						vg_weights[i1] += dw->weight;
-					}
-					vg_users[i1]++;
+			/* vgroup_subset_weights is zero'd at this point */
+			while ((dv = BLI_SMALLSTACK_POP(dv_stack))) {
+				for (j = 0; j < subset_count; j++) {
+					vgroup_subset_weights[j] += dv_mul * defvert_find_weight(dv, vgroup_subset_map[j]);
 				}
 			}
 
-			mv = me->mvert;
-			dv = dvert_array;
+			dv = dvert_array[i];
+			for (j = 0; j < subset_count; j++) {
+				MDeformWeight *dw;
+				if (vgroup_subset_weights[j] > 0.0f) {
+					dw = defvert_verify_index(dv, vgroup_subset_map[j]);
+				}
+				else {
+					dw = defvert_find_index(dv, vgroup_subset_map[j]);
+				}
 
-			for (i = 0; i < dvert_tot; i++, mv++, dv++) {
-				if ((mv->flag & SELECT) && (vg_users[i] > 0)) {
-					dw = defvert_verify_index(dv, def_nr);
-					dw->weight = (fac * (vg_weights[i] / (float)vg_users[i])) + (ifac * dw->weight);
-
-					/* in case of division errors */
+				if (dw) {
+					dw->weight = (fac * vgroup_subset_weights[j]) + (ifac * dw->weight);
 					CLAMP(dw->weight, 0.0f, 1.0f);
 				}
+
+				/* zero for next iteration */
+				vgroup_subset_weights[j] = 0.0f;
 			}
 		}
+	}
 
-		MEM_freeN(vg_weights);
-		MEM_freeN(vg_users);
+	if (bm) {
+		/* pass */
 	}
+	else {
+		MEM_freeN(emap);
+		MEM_freeN(emap_mem);
+	}
+
+	MEM_freeN(dvert_array);
+	BLI_SMALLSTACK_FREE(dv_stack);
 }
 
 static int inv_cmp_mdef_vert_weights(const void *a1, const void *a2)
@@ -3506,9 +3503,14 @@
 {
 	Object *ob = ED_object_context(C);
 	float fac = RNA_float_get(op->ptr, "factor");
+	eVGroupSelect subset_type  = RNA_enum_get(op->ptr, "group_select_mode");
 
-	vgroup_blend(ob, fac);
+	int subset_count, vgroup_tot;
 
+	const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
+	vgroup_blend_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac);
+	MEM_freeN((void *)vgroup_validmap);
+
 	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
 	WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -3525,10 +3527,14 @@
 	if (!(ob && !ob->id.lib && data && !data->lib))
 		return false;
 
+	if (ob->type != OB_MESH) {
+		return false;
+	}
+
 	if (BKE_object_is_in_editmode_vgroup(ob)) {
 		return true;
 	}
-	else if ((ob->type == OB_MESH) && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
+	else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
 		if (ME_EDIT_PAINT_SEL_MODE(((Mesh *)data)) == SCE_SELECT_VERTEX) {
 			return true;
 		}
@@ -3559,6 +3565,7 @@
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
+	vgroup_operator_subset_select_props(ot, true);
 	prop = RNA_def_property(ot->srna, "factor", PROP_FLOAT, PROP_FACTOR);
 	RNA_def_property_ui_text(prop, "Factor", "");
 	RNA_def_property_range(prop, 0.0f, 1.0f);




More information about the Bf-blender-cvs mailing list