[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15210] trunk/blender/source/blender: Patch #8613 - Vertex groups in the mirror modifier.

Ben Batt benbatt at gmail.com
Thu Jun 12 17:44:15 CEST 2008


Revision: 15210
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15210
Author:   artificer
Date:     2008-06-12 17:43:55 +0200 (Thu, 12 Jun 2008)

Log Message:
-----------
Patch #8613 - Vertex groups in the mirror modifier.
This patch re-assigns the mirrored data to use vertex groups with "mirrored"
names (e.g. L_arm -> R_arm, Leg.R -> Leg.L etc.). Vertex groups with the
"mirrored" names must already exist in the base mesh.

This means that it is no longer necessary to apply the mirror modifier in order
to rig the mirrored data independently.

Thanks to Michael Fox for the patch!

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/modifier.c
    trunk/blender/source/blender/makesdna/DNA_modifier_types.h
    trunk/blender/source/blender/src/buttons_editing.c

Modified: trunk/blender/source/blender/blenkernel/intern/modifier.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/modifier.c	2008-06-12 15:05:52 UTC (rev 15209)
+++ trunk/blender/source/blender/blenkernel/intern/modifier.c	2008-06-12 15:43:55 UTC (rev 15210)
@@ -40,6 +40,7 @@
 #include "stdarg.h"
 #include "math.h"
 #include "float.h"
+#include "ctype.h"
 
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
@@ -1269,7 +1270,7 @@
 {
 	MirrorModifierData *mmd = (MirrorModifierData*) md;
 
-	mmd->flag |= MOD_MIR_AXIS_X;
+	mmd->flag |= (MOD_MIR_AXIS_X | MOD_MIR_VGROUP);
 	mmd->tolerance = 0.001;
 	mmd->mirror_ob = NULL;
 }
@@ -1308,6 +1309,118 @@
 	}
 }
 
+/* finds the best possible flipped name. For renaming; check for unique names afterwards */
+/* if strip_number: removes number extensions */
+void vertgroup_flip_name (char *name, int strip_number)
+{
+	int     len;
+	char    prefix[128]={""};   /* The part before the facing */
+	char    suffix[128]={""};   /* The part after the facing */
+	char    replace[128]={""};  /* The replacement string */
+	char    number[128]={""};   /* The number extension string */
+	char    *index=NULL;
+
+	len= strlen(name);
+	if(len<3) return; // we don't do names like .R or .L
+
+	/* We first check the case with a .### extension, let's find the last period */
+	if(isdigit(name[len-1])) {
+		index= strrchr(name, '.'); // last occurrance
+		if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
+			if(strip_number==0) 
+				strcpy(number, index);
+			*index= 0;
+			len= strlen(name);
+		}
+	}
+
+	strcpy (prefix, name);
+
+#define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')
+
+	/* first case; separator . - _ with extensions r R l L  */
+	if( IS_SEPARATOR(name[len-2]) ) {
+		switch(name[len-1]) {
+			case 'l':
+				prefix[len-1]= 0;
+				strcpy(replace, "r");
+				break;
+			case 'r':
+				prefix[len-1]= 0;
+				strcpy(replace, "l");
+				break;
+			case 'L':
+				prefix[len-1]= 0;
+				strcpy(replace, "R");
+				break;
+			case 'R':
+				prefix[len-1]= 0;
+				strcpy(replace, "L");
+				break;
+		}
+	}
+	/* case; beginning with r R l L , with separator after it */
+	else if( IS_SEPARATOR(name[1]) ) {
+		switch(name[0]) {
+			case 'l':
+				strcpy(replace, "r");
+				strcpy(suffix, name+1);
+				prefix[0]= 0;
+				break;
+			case 'r':
+				strcpy(replace, "l");
+				strcpy(suffix, name+1);
+				prefix[0]= 0;
+				break;
+			case 'L':
+				strcpy(replace, "R");
+				strcpy(suffix, name+1);
+				prefix[0]= 0;
+				break;
+			case 'R':
+				strcpy(replace, "L");
+				strcpy(suffix, name+1);
+				prefix[0]= 0;
+				break;
+		}
+	}
+	else if(len > 5) {
+		/* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
+		index = BLI_strcasestr(prefix, "right");
+		if (index==prefix || index==prefix+len-5) {
+			if(index[0]=='r') 
+				strcpy (replace, "left");
+			else {
+				if(index[1]=='I') 
+					strcpy (replace, "LEFT");
+				else
+					strcpy (replace, "Left");
+			}
+			*index= 0;
+			strcpy (suffix, index+5);
+		}
+		else {
+			index = BLI_strcasestr(prefix, "left");
+			if (index==prefix || index==prefix+len-4) {
+				if(index[0]=='l') 
+					strcpy (replace, "right");
+				else {
+					if(index[1]=='E') 
+						strcpy (replace, "RIGHT");
+					else
+						strcpy (replace, "Right");
+				}
+				*index= 0;
+				strcpy (suffix, index+4);
+			}
+		}
+	}
+
+#undef IS_SEPARATOR
+
+	sprintf (name, "%s%s%s%s", prefix, replace, suffix, number);
+}
+
 static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
 				   Object *ob,
        DerivedMesh *dm,
@@ -1321,6 +1434,9 @@
 	int maxVerts = dm->getNumVerts(dm);
 	int maxEdges = dm->getNumEdges(dm);
 	int maxFaces = dm->getNumFaces(dm);
+	int vector_size, j, a, b;
+	bDeformGroup *def, *defb;
+	bDeformGroup **vector_def = NULL;
 	int (*indexMap)[2];
 	float mtx[4][4], imtx[4][4];
 
@@ -1330,6 +1446,21 @@
 
 	result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
 
+
+	if (mmd->flag & MOD_MIR_VGROUP) {
+		/* calculate the number of deformedGroups */
+		for(vector_size = 0, def = ob->defbase.first; def;
+		    def = def->next, vector_size++);
+
+		/* load the deformedGroups for fast access */
+		vector_def =
+		    (bDeformGroup **)MEM_mallocN(sizeof(bDeformGroup*) * vector_size,
+		                                 "group_index");
+		for(a = 0, def = ob->defbase.first; def; def = def->next, a++) {
+			vector_def[a] = def;
+		}
+	}
+
 	if (mmd->mirror_ob) {
 		float obinv[4][4];
 
@@ -1374,16 +1505,48 @@
 			mv->flag |= ME_VERT_MERGED;
 		} else {
 			MVert *mv2 = CDDM_get_vert(result, numVerts);
+			MDeformVert *dvert = NULL;
 
 			DM_copy_vert_data(dm, result, i, numVerts, 1);
 			*mv2 = *mv;
-			numVerts++;
 
 			co[axis] = -co[axis];
 			if (mmd->mirror_ob) {
 				VecMat4MulVecfl(co, imtx, co);
 			}
 			VecCopyf(mv2->co, co);
+
+			if (mmd->flag & MOD_MIR_VGROUP){
+				dvert = DM_get_vert_data(result, numVerts, CD_MDEFORMVERT);
+
+				if (dvert)
+				{
+					for(j = 0; j < dvert[0].totweight; ++j)
+					{
+						char tmpname[32];
+
+						if(dvert->dw[j].def_nr < 0 ||
+						   dvert->dw[j].def_nr >= vector_size)
+							continue;
+
+						def = vector_def[dvert->dw[j].def_nr];
+						strcpy(tmpname, def->name);
+						vertgroup_flip_name(tmpname,0);
+
+						for(b = 0, defb = ob->defbase.first; defb;
+						    defb = defb->next, b++)
+						{
+							if(!strcmp(defb->name, tmpname))
+							{
+								dvert->dw[j].def_nr = b;
+								break;
+							}
+						}
+					}
+				}
+			}
+
+			numVerts++;
 		}
 	}
 
@@ -1467,6 +1630,8 @@
 				 }
 	}
 
+	if (vector_def) MEM_freeN(vector_def);
+
 	MEM_freeN(indexMap);
 
 	CDDM_lower_num_verts(result, numVerts);

Modified: trunk/blender/source/blender/makesdna/DNA_modifier_types.h
===================================================================
--- trunk/blender/source/blender/makesdna/DNA_modifier_types.h	2008-06-12 15:05:52 UTC (rev 15209)
+++ trunk/blender/source/blender/makesdna/DNA_modifier_types.h	2008-06-12 15:43:55 UTC (rev 15210)
@@ -176,6 +176,7 @@
 #define MOD_MIR_AXIS_X		1<<3
 #define MOD_MIR_AXIS_Y		1<<4
 #define MOD_MIR_AXIS_Z		1<<5
+#define MOD_MIR_VGROUP		1<<6
 
 typedef struct EdgeSplitModifierData {
 	ModifierData modifier;

Modified: trunk/blender/source/blender/src/buttons_editing.c
===================================================================
--- trunk/blender/source/blender/src/buttons_editing.c	2008-06-12 15:05:52 UTC (rev 15209)
+++ trunk/blender/source/blender/src/buttons_editing.c	2008-06-12 15:43:55 UTC (rev 15210)
@@ -1767,7 +1767,7 @@
 		} else if (md->type==eModifierType_Build) {
 			height = 86;
 		} else if (md->type==eModifierType_Mirror) {
-			height = 86;
+			height = 105;
 		} else if (md->type==eModifierType_Bevel) {
 			BevelModifierData *bmd = (BevelModifierData*) md;
 			height = 105; /* height = 124; */
@@ -1899,6 +1899,7 @@
 			uiDefButBitS(block, TOG, MOD_MIR_AXIS_Y, B_MODIFIER_RECALC, "Y",	lx+20,cy,20,19,    &mmd->flag, 0, 0, 0, 0, "Enable Y axis mirror");
 			uiDefButBitS(block, TOG, MOD_MIR_AXIS_Z, B_MODIFIER_RECALC, "Z",	lx+40,cy,20,19,    &mmd->flag, 0, 0, 0, 0, "Enable Z axis mirror");
 			uiDefButBitS(block, TOG, MOD_MIR_CLIPPING, B_MODIFIER_RECALC, "Do Clipping",	lx+60, cy, buttonWidth-60,19, &mmd->flag, 1, 2, 0, 0, "Prevents during Transform vertices to go through Mirror");
+			uiDefButBitS(block, TOG, MOD_MIR_VGROUP, B_MODIFIER_RECALC, "Mirror Vgroups",	lx, (cy-=19), buttonWidth,19, &mmd->flag, 1, 2, 0, 0, "Mirror vertex groups (e.g. .R->.L)");
 			uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
 			             "Mirror U",
 			             lx, (cy-=19), buttonWidth/2, 19,





More information about the Bf-blender-cvs mailing list