[Bf-blender-cvs] [d9d3ed16a8c] master: Fix T53206: Array modifier doesn't merge vgroups

Campbell Barton noreply at git.blender.org
Tue Mar 6 00:09:55 CET 2018


Commit: d9d3ed16a8c61bb1c780d81a2cf398be92cd16c1
Author: Campbell Barton
Date:   Tue Mar 6 09:57:41 2018 +1100
Branches: master
https://developer.blender.org/rBd9d3ed16a8c61bb1c780d81a2cf398be92cd16c1

Fix T53206: Array modifier doesn't merge vgroups

Vertex group remapping utility function,
now shared between object join and array modifier cap-ends.

Weights which don't exist are removed.

D3092 by @Foaly

===================================================================

M	source/blender/blenkernel/BKE_object_deform.h
M	source/blender/blenkernel/intern/object_deform.c
M	source/blender/editors/mesh/meshtools.c
M	source/blender/modifiers/intern/MOD_array.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_object_deform.h b/source/blender/blenkernel/BKE_object_deform.h
index 19a2220006a..ab54330cf53 100644
--- a/source/blender/blenkernel/BKE_object_deform.h
+++ b/source/blender/blenkernel/BKE_object_deform.h
@@ -54,7 +54,8 @@ void BKE_object_defgroup_remove(struct Object *ob, struct bDeformGroup *defgroup
 void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked);
 void BKE_object_defgroup_remove_all(struct Object *ob);
 
-
+int *BKE_object_defgroup_index_map_create(struct Object *ob_src, struct Object *ob_dst, int *r_map_len);
+void BKE_object_defgroup_index_map_apply(struct MDeformVert *dvert, int dvert_len, const int *map, int map_len);
 
 /* Select helpers */
 enum eVGroupSelect;
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index 2726064d634..61533e13d7a 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -457,6 +457,70 @@ void BKE_object_defgroup_remove_all(struct Object *ob)
 	BKE_object_defgroup_remove_all_ex(ob, false);
 }
 
+/**
+ * Compute mapping for vertex groups with matching name, -1 is used for no remapping.
+ * Returns null if no remapping is required.
+ * The returned array has to be freed.
+ */
+int *BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
+{
+	/* Build src to merged mapping of vgroup indices. */
+	if (BLI_listbase_is_empty(&ob_src->defbase) || BLI_listbase_is_empty(&ob_dst->defbase)) {
+		*r_map_len = 0;
+		return NULL;
+	}
+
+	bDeformGroup *dg_src;
+	*r_map_len = BLI_listbase_count(&ob_src->defbase);
+	int *vgroup_index_map = MEM_malloc_arrayN(*r_map_len, sizeof(*vgroup_index_map), "defgroup index map create");
+	bool is_vgroup_remap_needed = false;
+	int i;
+
+	for (dg_src = ob_src->defbase.first, i = 0; dg_src; dg_src = dg_src->next, i++) {
+		vgroup_index_map[i] = defgroup_name_index(ob_dst, dg_src->name);
+		is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[i] != i);
+	}
+
+	if (!is_vgroup_remap_needed) {
+		MEM_freeN(vgroup_index_map);
+		vgroup_index_map = NULL;
+		*r_map_len = 0;
+	}
+
+	return vgroup_index_map;
+}
+
+void BKE_object_defgroup_index_map_apply(MDeformVert *dvert, int dvert_len, const int *map, int map_len)
+{
+	if (map == NULL || map_len == 0) {
+		return;
+	}
+
+	MDeformVert *dv = dvert;
+	for (int i = 0; i < dvert_len; i++, dv++) {
+		int totweight = dv->totweight;
+		for (int j = 0; j < totweight; j++) {
+			int def_nr = dv->dw[j].def_nr;
+			if ((uint)def_nr < (uint)map_len && map[def_nr] != -1) {
+				dv->dw[j].def_nr = map[def_nr];
+			}
+			else {
+				totweight--;
+				dv->dw[j] = dv->dw[totweight];
+				j--;
+			}
+		}
+		if (totweight != dv->totweight) {
+			if (totweight) {
+				dv->dw = MEM_reallocN(dv->dw, sizeof(*dv->dw) * totweight);
+			}
+			else {
+				MEM_SAFE_FREE(dv->dw);
+			}
+			dv->totweight = totweight;
+		}
+	}
+}
 
 /**
  * Get MDeformVert vgroup data from given object. Should only be used in Object mode.
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index c900373a59c..fa1c935e2ff 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -58,6 +58,7 @@
 #include "BKE_mesh.h"
 #include "BKE_material.h"
 #include "BKE_object.h"
+#include "BKE_object_deform.h"
 #include "BKE_report.h"
 #include "BKE_editmesh.h"
 #include "BKE_multires.h"
@@ -111,21 +112,12 @@ static void join_mesh_single(
 			BLI_assert(dvert != NULL);
 
 			/* Build src to merged mapping of vgroup indices. */
-			bDeformGroup *dg_src;
-			int *vgroup_index_map = alloca(sizeof(*vgroup_index_map) * BLI_listbase_count(&ob_src->defbase));
-			bool is_vgroup_remap_needed = false;
-
-			for (dg_src = ob_src->defbase.first, b = 0; dg_src; dg_src = dg_src->next, b++) {
-				vgroup_index_map[b] = defgroup_name_index(ob_dst, dg_src->name);
-				is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[b] != b);
-			}
-
-			if (is_vgroup_remap_needed) {
-				for (a = 0; a < me->totvert; a++) {
-					for (b = 0; b < dvert[a].totweight; b++) {
-						dvert[a].dw[b].def_nr = vgroup_index_map[dvert_src[a].dw[b].def_nr];
-					}
-				}
+			int *vgroup_index_map;
+			int vgroup_index_map_len;
+			vgroup_index_map = BKE_object_defgroup_index_map_create(ob_src, ob_dst, &vgroup_index_map_len);
+			BKE_object_defgroup_index_map_apply(dvert, me->totvert, vgroup_index_map, vgroup_index_map_len);
+			if (vgroup_index_map != NULL) {
+				MEM_freeN(vgroup_index_map);
 			}
 		}
 
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 053957d89e2..b781c47ac56 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -51,6 +51,7 @@
 #include "BKE_library_query.h"
 #include "BKE_modifier.h"
 #include "BKE_mesh.h"
+#include "BKE_object_deform.h"
 
 #include "MOD_util.h"
 
@@ -312,7 +313,7 @@ static void dm_mvert_map_doubles(
 static void dm_merge_transform(
         DerivedMesh *result, DerivedMesh *cap_dm, float cap_offset[4][4],
         unsigned int cap_verts_index, unsigned int cap_edges_index, int cap_loops_index, int cap_polys_index,
-        int cap_nverts, int cap_nedges, int cap_nloops, int cap_npolys)
+        int cap_nverts, int cap_nedges, int cap_nloops, int cap_npolys, int *remap, int remap_len)
 {
 	int *index_orig;
 	int i;
@@ -320,6 +321,7 @@ static void dm_merge_transform(
 	MEdge *me;
 	MLoop *ml;
 	MPoly *mp;
+	MDeformVert *dvert;
 
 	/* needed for subsurf so arrays are allocated */
 	cap_dm->getVertArray(cap_dm);
@@ -340,6 +342,12 @@ static void dm_merge_transform(
 		mv->flag = mv->bweight = 0;
 	}
 
+	/* remap the vertex groups if necessary */
+	dvert = DM_get_vert_data(result, cap_verts_index, CD_MDEFORMVERT);
+	if (dvert != NULL) {
+		BKE_object_defgroup_index_map_apply(dvert, cap_nverts, remap, remap_len);
+	}
+
 	/* adjust cap edge vertex indices */
 	me = CDDM_get_edges(result) + cap_edges_index;
 	for (i = 0; i < cap_nedges; i++, me++) {
@@ -417,6 +425,11 @@ static DerivedMesh *arrayModifier_doArray(
 
 	DerivedMesh *result, *start_cap_dm = NULL, *end_cap_dm = NULL;
 
+	int *vgroup_start_cap_remap = NULL;
+	int vgroup_start_cap_remap_len = 0;
+	int *vgroup_end_cap_remap = NULL;
+	int vgroup_end_cap_remap_len = 0;
+
 	chunk_nverts = dm->getNumVerts(dm);
 	chunk_nedges = dm->getNumEdges(dm);
 	chunk_nloops = dm->getNumLoops(dm);
@@ -425,6 +438,8 @@ static DerivedMesh *arrayModifier_doArray(
 	count = amd->count;
 
 	if (amd->start_cap && amd->start_cap != ob && amd->start_cap->type == OB_MESH) {
+		vgroup_start_cap_remap = BKE_object_defgroup_index_map_create(amd->start_cap, ob, &vgroup_start_cap_remap_len);
+
 		start_cap_dm = get_dm_for_modifier(amd->start_cap, flag);
 		if (start_cap_dm) {
 			start_cap_nverts = start_cap_dm->getNumVerts(start_cap_dm);
@@ -434,6 +449,8 @@ static DerivedMesh *arrayModifier_doArray(
 		}
 	}
 	if (amd->end_cap && amd->end_cap != ob && amd->end_cap->type == OB_MESH) {
+		vgroup_end_cap_remap = BKE_object_defgroup_index_map_create(amd->end_cap, ob, &vgroup_end_cap_remap_len);
+
 		end_cap_dm = get_dm_for_modifier(amd->end_cap, flag);
 		if (end_cap_dm) {
 			end_cap_nverts = end_cap_dm->getNumVerts(end_cap_dm);
@@ -696,7 +713,8 @@ static DerivedMesh *arrayModifier_doArray(
 		        result_nedges - start_cap_nedges - end_cap_nedges,
 		        result_nloops - start_cap_nloops - end_cap_nloops,
 		        result_npolys - start_cap_npolys - end_cap_npolys,
-		        start_cap_nverts, start_cap_nedges, start_cap_nloops, start_cap_npolys);
+		        start_cap_nverts, start_cap_nedges, start_cap_nloops, start_cap_npolys,
+		        vgroup_start_cap_remap, vgroup_start_cap_remap_len);
 		/* Identify doubles with first chunk */
 		if (use_merge) {
 			dm_mvert_map_doubles(
@@ -720,7 +738,8 @@ static DerivedMesh *arrayModifier_doArray(
 		        result_nedges - end_cap_nedges,
 		        result_nloops - end_cap_nloops,
 		        result_npolys - end_cap_npolys,
-		        end_cap_nverts, end_cap_nedges, end_cap_nloops, end_cap_npolys);
+		        end_cap_nverts, end_cap_nedges, end_cap_nloops, end_cap_npolys,
+		        vgroup_end_cap_remap, vgroup_end_cap_remap_len);
 		/* Identify doubles with last chunk */
 		if (use_merge) {
 			dm_mvert_map_doubles(
@@ -768,6 +787,13 @@ static DerivedMesh *arrayModifier_doArray(
 		result->dirty |= DM_DIRTY_NORMALS;
 	}
 
+	if (vgroup_start_cap_remap) {
+		MEM_freeN(vgroup_start_cap_remap);
+	}
+	if (vgroup_end_cap_remap) {
+		MEM_freeN(vgroup_end_cap_remap);
+	}
+
 	return result;
 }



More information about the Bf-blender-cvs mailing list