diff options
author | Ton Roosendaal <ton@blender.org> | 2005-10-04 19:00:28 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2005-10-04 19:00:28 +0400 |
commit | 772459f15c054ae88c06da6209871f6749e8040a (patch) | |
tree | 71cfbe3ea2d1f563046d3a23765350ed963e1b93 | |
parent | e5eea31629777dc0ca2fbd797ef1b5d6bf2fa5f0 (diff) |
Shape Keys now can be controlled with Vertex Weight groups as well!
Just fill in the name of a Vertex group in the Shape Panel, and this
Shape will then become blended with the reference Shape.
It is useful for example for a symmetrical modeled head, make a
copy of that Shape, and use two Vertex Groups to make it asymetric.
Of course the Shapes update nicely while Weight Painting.
Also new; since the Vertex group names reside on Object level, you might
want to copy these names to the other Objects that have the same Mesh.
That's a new button "Copy to Linked" in the first Edit Panel.
-rw-r--r-- | source/blender/blenkernel/intern/key.c | 145 | ||||
-rw-r--r-- | source/blender/include/butspace.h | 1 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_key_types.h | 2 | ||||
-rw-r--r-- | source/blender/src/buttons_editing.c | 32 |
4 files changed, 138 insertions, 42 deletions
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index d0c0b1f9927..10a7e111a49 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -405,14 +405,23 @@ static void flerp(int aantal, float *in, float *f0, float *f1, float *f2, float } } -static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *k, int mode) +static void rel_flerp(int aantal, float *in, float *ref, float *out, float fac) +{ + int a; + + for(a=0; a<aantal; a++) { + in[a]-= fac*(ref[a]-out[a]); + } +} + +static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *k, float *weights, int mode) { float ktot = 0.0, kd = 0.0; int elemsize, poinsize = 0, a, *ofsp, ofs[32], flagflo=0; - char *k1; + char *k1, *kref; char *cp, elemstr[8]; - if(key->from==0) return; + if(key->from==NULL) return; if( GS(key->from->name)==ID_ME ) { ofs[0]= sizeof(MVert); @@ -436,7 +445,8 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * if(end>tot) end= tot; k1= k->data; - + kref= key->refkey->data; + if(tot != k->totelem) { ktot= 0.0; flagflo= 1; @@ -462,7 +472,6 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * else k1+= start*key->elemsize; } - if(mode==KEY_BEZTRIPLE) { elemstr[0]= 1; elemstr[1]= IPO_BEZTRIPLE; @@ -484,7 +493,15 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * switch(cp[1]) { case IPO_FLOAT: - memcpy(poin, k1, 4*cp[0]); + if(weights) { + memcpy(poin, kref, 4*cp[0]); + if(*weights!=0.0f) + rel_flerp(cp[0], (float *)poin, (float *)kref, (float *)k1, *weights); + weights++; + } + else + memcpy(poin, k1, 4*cp[0]); + poin+= ofsp[0]; break; @@ -511,9 +528,13 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * while(ktot>=1.0) { ktot-= 1.0; k1+= elemsize; + kref+= elemsize; } } - else k1+= elemsize; + else { + k1+= elemsize; + kref+= elemsize; + } if(mode==KEY_BEZTRIPLE) a+=2; } @@ -540,7 +561,7 @@ void cp_cu_key(Curve *cu, KeyBlock *kb, int start, int end) a1= MAX2(a, start); a2= MIN2(a+step, end); - if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, KEY_BPOINT); + if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, NULL, KEY_BPOINT); } else if(nu->bezt) { @@ -552,7 +573,7 @@ void cp_cu_key(Curve *cu, KeyBlock *kb, int start, int end) a1= MAX2(a, start); a2= MIN2(a+step, end); - if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, KEY_BEZTRIPLE); + if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, NULL, KEY_BEZTRIPLE); } a+= step; @@ -561,22 +582,11 @@ void cp_cu_key(Curve *cu, KeyBlock *kb, int start, int end) } -static void rel_flerp(int aantal, float *in, float *ref, float *out, float fac) -{ - int a; - - for(a=0; a<aantal; a++) { - in[a]-= fac*(ref[a]-out[a]); - } -} - - - static void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, float ctime, int mode) { KeyBlock *kb; IpoCurve *icu; - int *ofsp, ofs[3], elemsize, a, b; + int *ofsp, ofs[3], elemsize, b; char *cp, *poin, *reffrom, *from, elemstr[8]; if(key->from==0) return; @@ -609,22 +619,23 @@ static void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, f if(mode==KEY_BEZTRIPLE) elemsize*= 3; /* step 1 init */ - cp_key(start, end, tot, basispoin, key, key->refkey, mode); + cp_key(start, end, tot, basispoin, key, key->refkey, NULL, mode); /* step 2: do it */ - a= 1; kb= key->block.first; while(kb) { if(kb!=key->refkey) { + float icuval= 0.0f; + icu= find_ipocurve(key->ipo, kb->adrcode); + if(icu) + icuval= icu->curval; - a++; - if(a==64) break; - - /* only with ipocurve, and no difference allowed */ - if(icu && kb->totelem==tot) { + /* only with value or weights, and no difference allowed */ + if((icuval!=0.0f || (icu==NULL && kb->weights)) && kb->totelem==tot) { + float weight, *weights= kb->weights; poin= basispoin; reffrom= key->refkey->data; @@ -636,6 +647,11 @@ static void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, f for(b=start; b<end; b++) { + if(weights) + weight= *weights * (icu?icuval:1.0f); + else + weight= icuval; + cp= key->elemstr; if(mode==KEY_BEZTRIPLE) cp= elemstr; @@ -645,16 +661,16 @@ static void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, f switch(cp[1]) { case IPO_FLOAT: - rel_flerp(cp[0], (float *)poin, (float *)reffrom, (float *)from, icu->curval); + rel_flerp(cp[0], (float *)poin, (float *)reffrom, (float *)from, weight); break; case IPO_BPOINT: - rel_flerp(3, (float *)poin, (float *)reffrom, (float *)from, icu->curval); - rel_flerp(1, (float *)(poin+16), (float *)(reffrom+16), (float *)(from+16), icu->curval); + rel_flerp(3, (float *)poin, (float *)reffrom, (float *)from, icuval); + rel_flerp(1, (float *)(poin+16), (float *)(reffrom+16), (float *)(from+16), icuval); break; case IPO_BEZTRIPLE: - rel_flerp(9, (float *)poin, (float *)reffrom, (float *)from, icu->curval); + rel_flerp(9, (float *)poin, (float *)reffrom, (float *)from, icuval); break; } @@ -669,6 +685,7 @@ static void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, f from+= elemsize; if(mode==KEY_BEZTRIPLE) b+= 2; + if(weights) weights++; } } } @@ -888,7 +905,40 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * } } -static int do_mesh_key(Mesh *me) +static float *get_weights_array(Object *ob, Mesh *me, char *vgroup) +{ + bDeformGroup *curdef; + int index= 0; + + if(vgroup[0]==0) return NULL; + if(me->dvert==NULL) return NULL; + + /* find the group (weak loop-in-loop) */ + for (curdef = ob->defbase.first; curdef; curdef=curdef->next, index++) + if (!strcmp(curdef->name, vgroup)) + break; + + if(curdef) { + MDeformVert *dvert= me->dvert; + float *weights; + int i, j; + + weights= MEM_callocN(me->totvert*sizeof(float), "weights"); + + for (i=0; i < me->totvert; i++, dvert++) { + for(j=0; j<dvert->totweight; j++) { + if (dvert->dw[j].def_nr == index) { + weights[i]= dvert->dw[j].weight; + break; + } + } + } + return weights; + } + return NULL; +} + +static int do_mesh_key(Object *ob, Mesh *me) { KeyBlock *k[4]; float cfra, ctime, t[4], delta, loc[3], size[3]; @@ -925,7 +975,7 @@ static int do_mesh_key(Mesh *me) do_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k, t, 0); } else { - cp_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k[2], 0); + cp_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k[2], NULL, 0); } } @@ -943,17 +993,25 @@ static int do_mesh_key(Mesh *me) } if(me->key->type==KEY_RELATIVE) { + KeyBlock *kb; + + for(kb= me->key->block.first; kb; kb= kb->next) + kb->weights= get_weights_array(ob, me, kb->vgroup); + do_rel_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, ctime, 0); + + for(kb= me->key->block.first; kb; kb= kb->next) { + if(kb->weights) MEM_freeN(kb->weights); + kb->weights= NULL; + } } else { flag= setkeys(ctime, &me->key->block, k, t, 0); if(flag==0) { - do_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k, t, 0); } else { - cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k[2], 0); - + cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k[2], NULL, 0); } if(flag && k[2]==me->key->refkey) tex_space_mesh(me); @@ -1136,7 +1194,7 @@ static int do_latt_key(Lattice *lt) do_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k, t, 0); } else { - cp_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k[2], 0); + cp_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k[2], NULL, 0); } } } @@ -1157,7 +1215,7 @@ static int do_latt_key(Lattice *lt) do_key(0, tot, tot, (char *)lt->def->vec, lt->key, k, t, 0); } else { - cp_key(0, tot, tot, (char *)lt->def->vec, lt->key, k[2], 0); + cp_key(0, tot, tot, (char *)lt->def->vec, lt->key, k[2], NULL, 0); } } } @@ -1182,14 +1240,17 @@ int do_ob_key(Object *ob) if(ob->type==OB_MESH) { Mesh *me= ob->data; + float *weights= get_weights_array(ob, me, kb->vgroup); + + cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, key, kb, weights, 0); - cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, key, kb, 0); + if(weights) MEM_freeN(weights); } else if(ob->type==OB_LATTICE) { Lattice *lt= ob->data; int tot= lt->pntsu*lt->pntsv*lt->pntsw; - cp_key(0, tot, tot, (char *)lt->def->vec, key, kb, 0); + cp_key(0, tot, tot, (char *)lt->def->vec, key, kb, NULL, 0); } else if ELEM(ob->type, OB_CURVE, OB_SURF) { Curve *cu= ob->data; @@ -1201,7 +1262,7 @@ int do_ob_key(Object *ob) } } else { - if(ob->type==OB_MESH) return do_mesh_key( ob->data); + if(ob->type==OB_MESH) return do_mesh_key(ob, ob->data); else if(ob->type==OB_CURVE) return do_curve_key( ob->data); else if(ob->type==OB_SURF) return do_curve_key( ob->data); else if(ob->type==OB_LATTICE) return do_latt_key( ob->data); diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 0557a6110bd..39182debc67 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -374,6 +374,7 @@ enum { #define B_CHROMADEPTH 2084 #define B_DRAWEDGES 2087 #define B_DRAWCREASES 2088 +#define B_LINKEDVGROUP 2089 /* *********************** */ #define B_CURVEBUTS 2200 diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h index a41d93997c1..91a45dba77d 100644 --- a/source/blender/makesdna/DNA_key_types.h +++ b/source/blender/makesdna/DNA_key_types.h @@ -48,7 +48,9 @@ typedef struct KeyBlock { int totelem; void *data; + float *weights; char name[32]; + char vgroup[32]; float slidermin; float slidermax; diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index aaa8f64d11a..6570724d07d 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -73,6 +73,7 @@ #include "DNA_world_types.h" #include "DNA_packedFile_types.h" +#include "BKE_blender.h" #include "BKE_curve.h" #include "BKE_depsgraph.h" #include "BKE_global.h" @@ -1454,7 +1455,11 @@ static void editing_panel_shapes(Object *ob) make_rvk_slider(block, key, ob->shapenr-1, 10, 120, 150, 20, "Key value, when used it inserts an animation curve point"); uiDefButF(block, NUM, B_REDR, "Min ", 160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider"); uiDefButF(block, NUM, B_REDR, "Max ", 235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider"); + uiBlockEndAlign(block); } + if(key->type && ob->shapenr!=1) + uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", 10, 90, 150,19, &kb->vgroup, 0.0, 31.0, 0, 0, "Vertex Weight Group name, to blend with Basis Shape"); + } /* *************************** FONT ******************************** */ @@ -2848,6 +2853,25 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm) /* *************************** MESH ******************************** */ +/* from this object to all objects with same ob->data */ +static void copy_linked_vgroup_channels(Object *ob) +{ + Base *base; + + for(base=FIRSTBASE; base; base= base->next) { + if(base->object->type==ob->type) { + if(base->object!=ob) { + BLI_freelistN(&base->object->defbase); + duplicatelist(&base->object->defbase, &ob->defbase); + base->object->actdef= ob->actdef; + DAG_object_flush_update(G.scene, base->object, OB_RECALC_DATA); + } + } + } + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); +} + void do_meshbuts(unsigned short event) { Object *ob; @@ -2894,6 +2918,9 @@ void do_meshbuts(unsigned short event) allqueue (REDRAWVIEW3D, 1); allqueue(REDRAWOOPS, 0); break; + case B_LINKEDVGROUP: + copy_linked_vgroup_channels(ob); + break; case B_DELSTICKY: if(me->msticky) MEM_freeN(me->msticky); @@ -3257,6 +3284,7 @@ static void editing_panel_links(Object *ob) /* vertex group... partially editmode... */ if(ob->type==OB_MESH) { + Mesh *me= ob->data; uiBut *but; int defCount; bDeformGroup *defGroup; @@ -3295,6 +3323,10 @@ static void editing_panel_links(Object *ob) uiDefBut(block, BUT,B_DESELVGROUP,"Desel.", 213,48,70,21, 0, 0, 0, 0, 0, "Deselects vertices belonging to the current vertex group"); uiBlockEndAlign(block); } + else { + if(me->id.us>1) + uiDefBut(block, BUT,B_LINKEDVGROUP, "Copy To Linked", 143,69,140,20, 0, 0, 0, 0, 0, "Creates identical vertex group names in other Objects using this Mesh"); + } } |