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!
This commit is contained in:
Ben Batt
2008-06-12 15:43:55 +00:00
parent 1091db8f9b
commit 7ffd70f39a
3 changed files with 170 additions and 3 deletions

View File

@@ -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 @@ static void mirrorModifier_initData(ModifierData *md)
{
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 @@ static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest,
}
}
/* 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 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
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 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
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 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
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 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
}
}
if (vector_def) MEM_freeN(vector_def);
MEM_freeN(indexMap);
CDDM_lower_num_verts(result, numVerts);

View File

@@ -176,6 +176,7 @@ typedef struct MirrorModifierData {
#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;

View File

@@ -1767,7 +1767,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
} 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 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
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,