[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [60186] trunk/blender/source/blender/ editors: fix [#36246] Weight tools do not mirror properly in vertex selection mask mode.

Campbell Barton ideasman42 at gmail.com
Tue Sep 17 09:03:13 CEST 2013


Revision: 60186
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=60186
Author:   campbellbarton
Date:     2013-09-17 07:03:13 +0000 (Tue, 17 Sep 2013)
Log Message:
-----------
fix [#36246] Weight tools do not mirror properly in vertex selection mask mode.

Weight mirror is now supported by invert/clean/levels/blend.

Modified Paths:
--------------
    trunk/blender/source/blender/editors/include/ED_mesh.h
    trunk/blender/source/blender/editors/mesh/meshtools.c
    trunk/blender/source/blender/editors/object/object_vgroup.c

Modified: trunk/blender/source/blender/editors/include/ED_mesh.h
===================================================================
--- trunk/blender/source/blender/editors/include/ED_mesh.h	2013-09-17 06:47:47 UTC (rev 60185)
+++ trunk/blender/source/blender/editors/include/ED_mesh.h	2013-09-17 07:03:13 UTC (rev 60186)
@@ -246,6 +246,14 @@
 bool                 ED_vgroup_array_copy(struct Object *ob, struct Object *ob_from);
 bool                 ED_vgroup_parray_alloc(struct ID *id, struct MDeformVert ***dvert_arr, int *dvert_tot,
                                             const bool use_vert_sel);
+void                 ED_vgroup_parray_mirror_sync(struct Object *ob,
+                                                  struct MDeformVert **dvert_array, const int dvert_tot,
+                                                  const bool *vgroup_validmap, const int vgroup_tot);
+void                 ED_vgroup_parray_mirror_assign(struct Object *ob,
+                                                    struct MDeformVert **dvert_array, const int dvert_tot);
+void                 ED_vgroup_parray_remove_zero(struct MDeformVert **dvert_array, const int dvert_tot,
+                                                  const bool *vgroup_validmap, const int vgroup_tot,
+                                                  const float epsilon, const bool keep_single);
 void                 ED_vgroup_mirror(struct Object *ob,
                                       const bool mirror_weights, const bool flip_vgroups,
                                       const bool all_vgroups, const bool use_topology,
@@ -319,6 +327,8 @@
                                            int index, const bool use_topology);
 int           *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
 
+int ED_mesh_mirror_get_vert(struct Object *ob, int index);
+
 bool ED_mesh_pick_vert(struct bContext *C,      struct Object *ob, const int mval[2], unsigned int *index, int size, bool use_zbuf);
 bool ED_mesh_pick_face(struct bContext *C,      struct Object *ob, const int mval[2], unsigned int *index, int size);
 bool ED_mesh_pick_face_vert(struct bContext *C, struct Object *ob, const int mval[2], unsigned int *index, int size);

Modified: trunk/blender/source/blender/editors/mesh/meshtools.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/meshtools.c	2013-09-17 06:47:47 UTC (rev 60185)
+++ trunk/blender/source/blender/editors/mesh/meshtools.c	2013-09-17 07:03:13 UTC (rev 60186)
@@ -1011,6 +1011,31 @@
 	}
 }
 
+/**
+ * Wrapper for objectmode/editmode.
+ *
+ * call #EDBM_index_arrays_ensure first for editmesh.
+ */
+int ED_mesh_mirror_get_vert(Object *ob, int index)
+{
+	Mesh *me = ob->data;
+	BMEditMesh *em = me->edit_btmesh;
+	bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+	int index_mirr;
+
+	if (em) {
+		BMVert *eve, *eve_mirr;
+		eve = EDBM_vert_at_index(em, index);
+		eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, index, use_topology);
+		index_mirr = eve_mirr ? BM_elem_index_get(eve_mirr) : -1;
+	}
+	else {
+		 index_mirr = mesh_get_x_mirror_vert(ob, index, use_topology);
+	}
+
+	return index_mirr;
+}
+
 #if 0
 
 static float *editmesh_get_mirror_uv(BMEditMesh *em, int axis, float *uv, float *mirrCent, float *face_cent)

Modified: trunk/blender/source/blender/editors/object/object_vgroup.c
===================================================================
--- trunk/blender/source/blender/editors/object/object_vgroup.c	2013-09-17 06:47:47 UTC (rev 60185)
+++ trunk/blender/source/blender/editors/object/object_vgroup.c	2013-09-17 07:03:13 UTC (rev 60186)
@@ -326,6 +326,119 @@
 	return false;
 }
 
+/**
+ * For use with tools that use ED_vgroup_parray_alloc with \a use_vert_sel == true.
+ * This finds the unselected mirror deform verts and copys the weights to them from the selected.
+ *
+ * \note \a dvert_array has mirrored weights filled in, incase cleanup operations are needed on both.
+ */
+void ED_vgroup_parray_mirror_sync(Object *ob,
+                                  MDeformVert **dvert_array, const int dvert_tot,
+                                  const bool *vgroup_validmap, const int vgroup_tot)
+{
+	BMEditMesh *em = BKE_editmesh_from_object(ob);
+	MDeformVert **dvert_array_all = NULL;
+	int dvert_tot_all;
+	int i;
+
+	/* get an array of all verts, not only selected */
+	if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
+		BLI_assert(0);
+		return;
+	}
+	if (em) {
+		EDBM_index_arrays_ensure(em, BM_VERT);
+	}
+
+	for (i = 0; i < dvert_tot; i++) {
+		if (dvert_array[i] == NULL) {
+			/* its unselected, check if its mirror is */
+			int i_sel = ED_mesh_mirror_get_vert(ob, i);
+			if ((i_sel != -1) && (i_sel != i) && (dvert_array[i_sel])) {
+				/* we found a match! */
+				MDeformVert *dv_src = dvert_array[i_sel];
+				MDeformVert *dv_dst = dvert_array_all[i];
+
+				defvert_copy_subset(dv_dst, dv_src, vgroup_validmap, vgroup_tot);
+
+				dvert_array[i] = dvert_array_all[i];
+			}
+		}
+	}
+
+	MEM_freeN(dvert_array_all);
+}
+
+/**
+ * Fill in the pointers for mirror verts (as if all mirror verts were selected too).
+ *
+ * similar to #ED_vgroup_parray_mirror_sync but only fill in mirror points.
+ */
+void ED_vgroup_parray_mirror_assign(Object *ob,
+                                    MDeformVert **dvert_array, const int dvert_tot)
+{
+	BMEditMesh *em = BKE_editmesh_from_object(ob);
+	MDeformVert **dvert_array_all = NULL;
+	int dvert_tot_all;
+	int i;
+
+	/* get an array of all verts, not only selected */
+	if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
+		BLI_assert(0);
+		return;
+	}
+	BLI_assert(dvert_tot == dvert_tot_all);
+	if (em) {
+		EDBM_index_arrays_ensure(em, BM_VERT);
+	}
+
+	for (i = 0; i < dvert_tot; i++) {
+		if (dvert_array[i] == NULL) {
+			/* its unselected, check if its mirror is */
+			int i_sel = ED_mesh_mirror_get_vert(ob, i);
+			if ((i_sel != -1) && (i_sel != i) && (dvert_array[i_sel])) {
+				/* we found a match! */
+				dvert_array[i] = dvert_array_all[i];
+			}
+		}
+	}
+
+	MEM_freeN(dvert_array_all);
+}
+
+void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array, const int dvert_tot,
+                                  const bool *vgroup_validmap, const int vgroup_tot,
+                                  const float epsilon, const bool keep_single)
+{
+	MDeformVert *dv;
+	int i;
+
+	for (i = 0; i < dvert_tot; i++) {
+		int j;
+
+		/* in case its not selected */
+		if (!(dv = dvert_array[i])) {
+			continue;
+		}
+
+		j = dv->totweight;
+
+		while (j--) {
+			MDeformWeight *dw;
+
+			if (keep_single && dv->totweight == 1)
+				break;
+
+			dw = dv->dw + j;
+			if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
+				if (dw->weight <= epsilon) {
+					defvert_remove_group(dv, dw);
+				}
+			}
+		}
+	}
+}
+
 /* returns true if the id type supports weights */
 bool ED_vgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot)
 {
@@ -1850,7 +1963,8 @@
 	MDeformVert *dv, **dvert_array = NULL;
 	int i, dvert_tot = 0;
 
-	const int use_vert_sel = vertex_group_use_vert_sel(ob);
+	const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+	const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
 
 	ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
 
@@ -1877,6 +1991,11 @@
 			}
 		}
 
+		if (use_mirror && use_vert_sel) {
+			ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot,
+			                             vgroup_validmap, vgroup_tot);
+		}
+
 		MEM_freeN(dvert_array);
 	}
 }
@@ -1980,7 +2099,8 @@
 	MDeformWeight *dw;
 	MDeformVert *dv, **dvert_array = NULL;
 	int i, dvert_tot = 0;
-	const int use_vert_sel = vertex_group_use_vert_sel(ob);
+	const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+	const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
 
 	ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
 
@@ -2006,14 +2126,23 @@
 
 					if (dw) {
 						dw->weight = 1.0f - dw->weight;
-						if (auto_remove && dw->weight <= 0.0f) {
-							defvert_remove_group(dv, dw);
-						}
+						CLAMP(dw->weight, 0.0f, 1.0f);
 					}
 				}
 			}
 		}
 
+		if (use_mirror && use_vert_sel) {
+			ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot,
+			                             vgroup_validmap, vgroup_tot);
+
+			if (auto_remove) {
+				ED_vgroup_parray_remove_zero(dvert_array, dvert_tot,
+				                             vgroup_validmap, vgroup_tot,
+				                             0.0f, false);
+			}
+		}
+
 		MEM_freeN(dvert_array);
 	}
 }
@@ -2027,6 +2156,7 @@
 	int i, dvert_tot = 0;
 	int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count);
 	float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count);
+	const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
 
 	BMEditMesh *em = BKE_editmesh_from_object(ob);
 	BMesh *bm = em ? em->bm : NULL;
@@ -2042,6 +2172,8 @@
 	memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count);
 
 	if (bm) {
+		EDBM_index_arrays_ensure(em, BM_VERT);
+
 		emap = NULL;
 		emap_mem = NULL;
 	}
@@ -2132,6 +2264,14 @@
 
 	MEM_freeN(dvert_array);
 	BLI_SMALLSTACK_FREE(dv_stack);
+
+	/* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */
+	if (use_mirror) {
+		ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, true);
+		ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot,
+		                             vgroup_validmap, vgroup_tot);
+		MEM_freeN(dvert_array);
+	}
 }
 
 static int inv_cmp_mdef_vert_weights(const void *a1, const void *a2)
@@ -2227,39 +2367,24 @@
                                 const float epsilon, const bool keep_single)
 {
 	MDeformVert **dvert_array = NULL;
-	int i, dvert_tot = 0;
-	const int use_vert_sel = vertex_group_use_vert_sel(ob);
+	int dvert_tot = 0;
+	const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+	const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
 
 	ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
 
 	if (dvert_array) {
-		MDeformVert *dv;
-		MDeformWeight *dw;
+		if (use_mirror && use_vert_sel) {
+			/* correct behavior in this case isn't well defined

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list