Blender V2.61 - r43446

deform.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Reevan McKay
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <string.h>
00034 #include <math.h>
00035 #include "ctype.h"
00036 
00037 #include "MEM_guardedalloc.h"
00038 
00039 #include "DNA_meshdata_types.h"
00040 #include "DNA_object_types.h"
00041 
00042 #include "BKE_deform.h"
00043 
00044 #include "BLI_blenlib.h"
00045 #include "BLI_utildefines.h"
00046 
00047 
00048 void defgroup_copy_list(ListBase *outbase, ListBase *inbase)
00049 {
00050     bDeformGroup *defgroup, *defgroupn;
00051 
00052     outbase->first= outbase->last= NULL;
00053 
00054     for (defgroup = inbase->first; defgroup; defgroup=defgroup->next){
00055         defgroupn= defgroup_duplicate(defgroup);
00056         BLI_addtail(outbase, defgroupn);
00057     }
00058 }
00059 
00060 bDeformGroup *defgroup_duplicate(bDeformGroup *ingroup)
00061 {
00062     bDeformGroup *outgroup;
00063 
00064     if (!ingroup)
00065         return NULL;
00066 
00067     outgroup=MEM_callocN(sizeof(bDeformGroup), "copy deformGroup");
00068 
00069     /* For now, just copy everything over. */
00070     memcpy (outgroup, ingroup, sizeof(bDeformGroup));
00071 
00072     outgroup->next=outgroup->prev=NULL;
00073 
00074     return outgroup;
00075 }
00076 
00077 /* copy & overwrite weights */
00078 void defvert_copy(MDeformVert *dvert_dst, const MDeformVert *dvert_src)
00079 {
00080     if (dvert_dst->totweight == dvert_src->totweight) {
00081         if (dvert_src->totweight)
00082             memcpy(dvert_dst->dw, dvert_src->dw, dvert_src->totweight * sizeof(MDeformWeight));
00083     }
00084     else {
00085         if (dvert_dst->dw)
00086             MEM_freeN(dvert_dst->dw);
00087 
00088         if (dvert_src->totweight)
00089             dvert_dst->dw= MEM_dupallocN(dvert_src->dw);
00090         else
00091             dvert_dst->dw= NULL;
00092 
00093         dvert_dst->totweight = dvert_src->totweight;
00094     }
00095 }
00096 
00097 /* copy an index from one dvert to another
00098  * - do nothing if neither are set.
00099  * - add destination weight if needed.
00100  */
00101 void defvert_copy_index(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const int defgroup)
00102 {
00103     MDeformWeight *dw_src, *dw_dst;
00104 
00105     dw_src= defvert_find_index(dvert_src, defgroup);
00106 
00107     if (dw_src) {
00108         /* source is valid, verify destination */
00109         dw_dst= defvert_verify_index(dvert_dst, defgroup);
00110         dw_dst->weight= dw_src->weight;
00111     }
00112     else {
00113         /* source was NULL, assign zero, could also remove */
00114         dw_dst= defvert_find_index(dvert_dst, defgroup);
00115 
00116         if (dw_dst) {
00117             dw_dst->weight= 0.0f;
00118         }
00119     }
00120 }
00121 
00122 /* only sync over matching weights, don't add or remove groups
00123  * warning, loop within loop.
00124  */
00125 void defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, int use_verify)
00126 {
00127     if (dvert_src->totweight && dvert_dst->totweight) {
00128         int i;
00129         MDeformWeight *dw_src;
00130         for (i=0, dw_src=dvert_src->dw; i < dvert_src->totweight; i++, dw_src++) {
00131             MDeformWeight *dw_dst;
00132             if (use_verify) dw_dst= defvert_verify_index(dvert_dst, dw_src->def_nr);
00133             else            dw_dst= defvert_find_index(dvert_dst, dw_src->def_nr);
00134 
00135             if (dw_dst) {
00136                 dw_dst->weight= dw_src->weight;
00137             }
00138         }
00139     }
00140 }
00141 
00142 /* be sure all flip_map values are valid */
00143 void defvert_sync_mapped(MDeformVert *dvert_dst, const MDeformVert *dvert_src,
00144                          const int *flip_map, const int flip_map_len, const int use_verify)
00145 {
00146     if (dvert_src->totweight && dvert_dst->totweight) {
00147         int i;
00148         MDeformWeight *dw_src;
00149         for (i=0, dw_src=dvert_src->dw; i < dvert_src->totweight; i++, dw_src++) {
00150             if (dw_src->def_nr < flip_map_len) {
00151                 MDeformWeight *dw_dst;
00152                 if (use_verify) dw_dst= defvert_verify_index(dvert_dst, flip_map[dw_src->def_nr]);
00153                 else            dw_dst= defvert_find_index(dvert_dst, flip_map[dw_src->def_nr]);
00154 
00155                 if (dw_dst) {
00156                     dw_dst->weight= dw_src->weight;
00157                 }
00158             }
00159         }
00160     }
00161 }
00162 
00163 /* be sure all flip_map values are valid */
00164 void defvert_remap(MDeformVert *dvert, int *map, const int map_len)
00165 {
00166     MDeformWeight *dw= dvert->dw;
00167     unsigned int i;
00168     for (i= dvert->totweight; i != 0; i--, dw++) {
00169         if (dw->def_nr < map_len) {
00170             dw->def_nr= map[dw->def_nr];
00171 
00172             /* just incase */
00173             BLI_assert(dw->def_nr >= 0);
00174         }
00175     }
00176 }
00177 
00178 void defvert_normalize(MDeformVert *dvert)
00179 {
00180     if (dvert->totweight <= 0) {
00181         /* nothing */
00182     }
00183     else if (dvert->totweight==1) {
00184         dvert->dw[0].weight= 1.0f;
00185     }
00186     else {
00187         MDeformWeight *dw;
00188         unsigned int i;
00189         float tot_weight= 0.0f;
00190 
00191         for (i= dvert->totweight, dw= dvert->dw; i != 0; i--, dw++) {
00192             tot_weight += dw->weight;
00193         }
00194 
00195         if (tot_weight > 0.0f) {
00196             float scalar= 1.0f / tot_weight;
00197             for (i= dvert->totweight, dw= dvert->dw; i != 0; i--, dw++) {
00198                 dw->weight *= scalar;
00199 
00200                 /* incase of division errors with very low weights */
00201                 CLAMP(dw->weight, 0.0f, 1.0f);
00202             }
00203         }
00204     }
00205 }
00206 
00207 void defvert_normalize_lock(MDeformVert *dvert, const int def_nr_lock)
00208 {
00209     if (dvert->totweight <= 0) {
00210         /* nothing */
00211     }
00212     else if (dvert->totweight==1) {
00213         dvert->dw[0].weight= 1.0f;
00214     }
00215     else {
00216         MDeformWeight *dw_lock = NULL;
00217         MDeformWeight *dw;
00218         unsigned int i;
00219         float tot_weight= 0.0f;
00220         float lock_iweight= 1.0f;
00221 
00222         for (i= dvert->totweight, dw= dvert->dw; i != 0; i--, dw++) {
00223             if(dw->def_nr != def_nr_lock) {
00224                 tot_weight += dw->weight;
00225             }
00226             else {
00227                 dw_lock= dw;
00228                 lock_iweight = (1.0f - dw_lock->weight);
00229                 CLAMP(lock_iweight, 0.0f, 1.0f);
00230             }
00231         }
00232 
00233         if (tot_weight > 0.0f) {
00234             /* paranoid, should be 1.0 but incase of float error clamp anyway */
00235 
00236             float scalar= (1.0f / tot_weight) * lock_iweight;
00237             for (i= dvert->totweight, dw= dvert->dw; i != 0; i--, dw++) {
00238                 if(dw != dw_lock) {
00239                     dw->weight *= scalar;
00240 
00241                     /* incase of division errors with very low weights */
00242                     CLAMP(dw->weight, 0.0f, 1.0f);
00243                 }
00244             }
00245         }
00246     }
00247 }
00248 
00249 void defvert_flip(MDeformVert *dvert, const int *flip_map, const int flip_map_len)
00250 {
00251     MDeformWeight *dw;
00252     int i;
00253 
00254     for (dw= dvert->dw, i=0; i<dvert->totweight; dw++, i++) {
00255         if (dw->def_nr < flip_map_len) {
00256             if (flip_map[dw->def_nr] >= 0) {
00257                 dw->def_nr= flip_map[dw->def_nr];
00258             }
00259         }
00260     }
00261 }
00262 
00263 
00264 bDeformGroup *defgroup_find_name(Object *ob, const char *name)
00265 {
00266     /* return a pointer to the deform group with this name
00267      * or return NULL otherwise.
00268      */
00269     bDeformGroup *curdef;
00270 
00271     for (curdef = ob->defbase.first; curdef; curdef=curdef->next) {
00272         if (!strcmp(curdef->name, name)) {
00273             return curdef;
00274         }
00275     }
00276     return NULL;
00277 }
00278 
00279 int defgroup_name_index(Object *ob, const char *name)
00280 {
00281     /* Return the location of the named deform group within the list of
00282      * deform groups. This function is a combination of BLI_findlink and
00283      * defgroup_find_name. The other two could be called instead, but that
00284      * require looping over the vertexgroups twice.
00285      */
00286     bDeformGroup *curdef;
00287     int def_nr;
00288 
00289     if (name && name[0] != '\0') {
00290         for (curdef=ob->defbase.first, def_nr=0; curdef; curdef=curdef->next, def_nr++) {
00291             if (!strcmp(curdef->name, name))
00292                 return def_nr;
00293         }
00294     }
00295 
00296     return -1;
00297 }
00298 
00299 /* note, must be freed */
00300 int *defgroup_flip_map(Object *ob, int *flip_map_len, int use_default)
00301 {
00302     int defbase_tot= *flip_map_len= BLI_countlist(&ob->defbase);
00303 
00304     if (defbase_tot==0) {
00305         return NULL;
00306     }
00307     else {
00308         bDeformGroup *dg;
00309         char name[sizeof(dg->name)];
00310         int i, flip_num, *map= MEM_mallocN(defbase_tot * sizeof(int), __func__);
00311 
00312         for (i=0; i < defbase_tot; i++) {
00313             map[i]= -1;
00314         }
00315 
00316         for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
00317             if (map[i] == -1) { /* may be calculated previously */
00318 
00319                 /* incase no valid value is found, use this */
00320                 if (use_default)
00321                     map[i]= i;
00322 
00323                 flip_side_name(name, dg->name, FALSE);
00324                 if (strcmp(name, dg->name)) {
00325                     flip_num= defgroup_name_index(ob, name);
00326                     if (flip_num >= 0) {
00327                         map[i]= flip_num;
00328                         map[flip_num]= i; /* save an extra lookup */
00329                     }
00330                 }
00331             }
00332         }
00333         return map;
00334     }
00335 }
00336 
00337 /* note, must be freed */
00338 int *defgroup_flip_map_single(Object *ob, int *flip_map_len, int use_default, int defgroup)
00339 {
00340     int defbase_tot= *flip_map_len= BLI_countlist(&ob->defbase);
00341 
00342     if (defbase_tot==0) {
00343         return NULL;
00344     }
00345     else {
00346         bDeformGroup *dg;
00347         char name[sizeof(dg->name)];
00348         int i, flip_num, *map= MEM_mallocN(defbase_tot * sizeof(int), __func__);
00349 
00350         for (i=0; i < defbase_tot; i++) {
00351             if (use_default) map[i]= i;
00352             else             map[i]= -1;
00353         }
00354 
00355         dg= BLI_findlink(&ob->defbase, defgroup);
00356 
00357         flip_side_name(name, dg->name, FALSE);
00358         if (strcmp(name, dg->name)) {
00359             flip_num= defgroup_name_index(ob, name);
00360 
00361             if (flip_num >= 0) {
00362                 map[defgroup]= flip_num;
00363                 map[flip_num]= defgroup;
00364             }
00365         }
00366 
00367         return map;
00368     }
00369 }
00370 
00371 int defgroup_flip_index(Object *ob, int index, int use_default)
00372 {
00373     bDeformGroup *dg= BLI_findlink(&ob->defbase, index);
00374     int flip_index = -1;
00375 
00376     if (dg) {
00377         char name[sizeof(dg->name)];
00378         flip_side_name(name, dg->name, 0);
00379 
00380         if (strcmp(name, dg->name))
00381             flip_index= defgroup_name_index(ob, name);
00382     }
00383 
00384     return (flip_index==-1 && use_default) ? index : flip_index;
00385 }
00386 
00387 static int defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
00388 {
00389     bDeformGroup *curdef;
00390 
00391     for (curdef = ob->defbase.first; curdef; curdef=curdef->next) {
00392         if (dg!=curdef) {
00393             if (!strcmp(curdef->name, name)) {
00394                 return 1;
00395             }
00396         }
00397     }
00398 
00399     return 0;
00400 }
00401 
00402 static int defgroup_unique_check(void *arg, const char *name)
00403 {
00404     struct {Object *ob; void *dg;} *data= arg;
00405     return defgroup_find_name_dupe(name, data->dg, data->ob);
00406 }
00407 
00408 void defgroup_unique_name(bDeformGroup *dg, Object *ob)
00409 {
00410     struct {Object *ob; void *dg;} data;
00411     data.ob= ob;
00412     data.dg= dg;
00413 
00414     BLI_uniquename_cb(defgroup_unique_check, &data, "Group", '.', dg->name, sizeof(dg->name));
00415 }
00416 
00417 /* finds the best possible flipped name. For renaming; check for unique names afterwards */
00418 /* if strip_number: removes number extensions
00419  * note: dont use sizeof() for 'name' or 'from_name' */
00420 void flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME], int strip_number)
00421 {
00422     int     len;
00423     char    prefix[MAX_VGROUP_NAME]=  "";   /* The part before the facing */
00424     char    suffix[MAX_VGROUP_NAME]=  "";   /* The part after the facing */
00425     char    replace[MAX_VGROUP_NAME]= "";   /* The replacement string */
00426     char    number[MAX_VGROUP_NAME]=  "";   /* The number extension string */
00427     char    *index=NULL;
00428 
00429     /* always copy the name, since this can be called with an uninitialized string */
00430     BLI_strncpy(name, from_name, MAX_VGROUP_NAME);
00431 
00432     len= BLI_strnlen(from_name, MAX_VGROUP_NAME);
00433     if (len < 3) {
00434         /* we don't do names like .R or .L */
00435         return;
00436     }
00437 
00438     /* We first check the case with a .### extension, let's find the last period */
00439     if (isdigit(name[len-1])) {
00440         index= strrchr(name, '.'); // last occurrence
00441         if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
00442             if (strip_number==0)
00443                 BLI_strncpy(number, index, sizeof(number));
00444             *index= 0;
00445             len= BLI_strnlen(name, MAX_VGROUP_NAME);
00446         }
00447     }
00448 
00449     BLI_strncpy(prefix, name, sizeof(prefix));
00450 
00451 #define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')
00452 
00453     /* first case; separator . - _ with extensions r R l L  */
00454     if (IS_SEPARATOR(name[len-2]) ) {
00455         switch(name[len-1]) {
00456             case 'l':
00457                 prefix[len-1]= 0;
00458                 strcpy(replace, "r");
00459                 break;
00460             case 'r':
00461                 prefix[len-1]= 0;
00462                 strcpy(replace, "l");
00463                 break;
00464             case 'L':
00465                 prefix[len-1]= 0;
00466                 strcpy(replace, "R");
00467                 break;
00468             case 'R':
00469                 prefix[len-1]= 0;
00470                 strcpy(replace, "L");
00471                 break;
00472         }
00473     }
00474     /* case; beginning with r R l L , with separator after it */
00475     else if (IS_SEPARATOR(name[1]) ) {
00476         switch(name[0]) {
00477             case 'l':
00478                 strcpy(replace, "r");
00479                 BLI_strncpy(suffix, name+1, sizeof(suffix));
00480                 prefix[0]= 0;
00481                 break;
00482             case 'r':
00483                 strcpy(replace, "l");
00484                 BLI_strncpy(suffix, name+1, sizeof(suffix));
00485                 prefix[0]= 0;
00486                 break;
00487             case 'L':
00488                 strcpy(replace, "R");
00489                 BLI_strncpy(suffix, name+1, sizeof(suffix));
00490                 prefix[0]= 0;
00491                 break;
00492             case 'R':
00493                 strcpy(replace, "L");
00494                 BLI_strncpy(suffix, name+1, sizeof(suffix));
00495                 prefix[0]= 0;
00496                 break;
00497         }
00498     }
00499     else if (len > 5) {
00500         /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
00501         index = BLI_strcasestr(prefix, "right");
00502         if (index==prefix || index==prefix+len-5) {
00503             if (index[0]=='r')
00504                 strcpy(replace, "left");
00505             else {
00506                 if (index[1]=='I')
00507                     strcpy(replace, "LEFT");
00508                 else
00509                     strcpy(replace, "Left");
00510             }
00511             *index= 0;
00512             BLI_strncpy(suffix, index+5, sizeof(suffix));
00513         }
00514         else {
00515             index = BLI_strcasestr(prefix, "left");
00516             if (index==prefix || index==prefix+len-4) {
00517                 if (index[0]=='l')
00518                     strcpy(replace, "right");
00519                 else {
00520                     if (index[1]=='E')
00521                         strcpy(replace, "RIGHT");
00522                     else
00523                         strcpy(replace, "Right");
00524                 }
00525                 *index= 0;
00526                 BLI_strncpy(suffix, index + 4, sizeof(suffix));
00527             }
00528         }
00529     }
00530 
00531 #undef IS_SEPARATOR
00532 
00533     BLI_snprintf (name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
00534 }
00535 
00536 float defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
00537 {
00538     MDeformWeight *dw= defvert_find_index(dvert, defgroup);
00539     return dw ? dw->weight : 0.0f;
00540 }
00541 
00542 /* take care with this the rationale is:
00543  * - if the object has no vertex group. act like vertex group isnt set and return 1.0,
00544  * - if the vertex group exists but the 'defgroup' isnt found on this vertex, _still_ return 0.0
00545  *
00546  * This is a bit confusing, just saves some checks from the caller.
00547  */
00548 float defvert_array_find_weight_safe(const struct MDeformVert *dvert, const int index, const int defgroup)
00549 {
00550     if (defgroup == -1 || dvert == NULL)
00551         return 1.0f;
00552 
00553     return defvert_find_weight(dvert+index, defgroup);
00554 }
00555 
00556 
00557 MDeformWeight *defvert_find_index(const MDeformVert *dvert, const int defgroup)
00558 {
00559     if (dvert && defgroup >= 0) {
00560         MDeformWeight *dw = dvert->dw;
00561         unsigned int i;
00562 
00563         for (i= dvert->totweight; i != 0; i--, dw++) {
00564             if (dw->def_nr == defgroup) {
00565                 return dw;
00566             }
00567         }
00568     }
00569 
00570     return NULL;
00571 }
00572 
00573 /* Ensures that mv has a deform weight entry for the specified defweight group */
00574 /* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
00575 MDeformWeight *defvert_verify_index(MDeformVert *dvert, const int defgroup)
00576 {
00577     MDeformWeight *dw_new;
00578 
00579     /* do this check always, this function is used to check for it */
00580     if (!dvert || defgroup < 0)
00581         return NULL;
00582 
00583     dw_new= defvert_find_index(dvert, defgroup);
00584     if (dw_new)
00585         return dw_new;
00586 
00587     dw_new= MEM_callocN(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
00588     if (dvert->dw) {
00589         memcpy(dw_new, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
00590         MEM_freeN(dvert->dw);
00591     }
00592     dvert->dw= dw_new;
00593     dw_new += dvert->totweight;
00594     dw_new->weight= 0.0f;
00595     dw_new->def_nr= defgroup;
00596     /* Group index */
00597 
00598     dvert->totweight++;
00599 
00600     return dw_new;
00601 }
00602 
00603 /* TODO. merge with code above! */
00604 
00605 /* Adds the given vertex to the specified vertex group, with given weight.
00606  * warning, this does NOT check for existign, assume caller already knows its not there */
00607 void defvert_add_index_notest(MDeformVert *dvert, int defgroup, const float weight)
00608 {
00609     MDeformWeight *dw_new;
00610 
00611     /* do this check always, this function is used to check for it */
00612     if (!dvert || defgroup < 0)
00613         return;
00614 
00615     dw_new = MEM_callocN(sizeof(MDeformWeight)*(dvert->totweight+1), "defvert_add_to group, new deformWeight");
00616     if(dvert->dw) {
00617         memcpy(dw_new, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
00618         MEM_freeN(dvert->dw);
00619     }
00620     dvert->dw = dw_new;
00621     dw_new += dvert->totweight;
00622     dw_new->weight = weight;
00623     dw_new->def_nr = defgroup;
00624     dvert->totweight++;
00625 }
00626 
00627 
00628 /* Removes the given vertex from the vertex group.
00629  * WARNING: This function frees the given MDeformWeight, do not use it afterward! */
00630 void defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
00631 {
00632     if (dvert && dw) {
00633         MDeformWeight *dw_new;
00634         int i = dw - dvert->dw;
00635 
00636         /* Security check! */
00637         if(i < 0 || i >= dvert->totweight) {
00638             return;
00639         }
00640 
00641         dvert->totweight--;
00642         /* If there are still other deform weights attached to this vert then remove
00643          * this deform weight, and reshuffle the others.
00644          */
00645         if (dvert->totweight) {
00646             dw_new = MEM_mallocN(sizeof(MDeformWeight)*(dvert->totweight), __func__);
00647             if (dvert->dw) {
00648 #if 1           /* since we dont care about order, swap this with the last, save a memcpy */
00649                 if (i != dvert->totweight) {
00650                     dvert->dw[i]= dvert->dw[dvert->totweight];
00651                 }
00652                 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
00653                 MEM_freeN(dvert->dw);
00654 #else
00655                 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight)*i);
00656                 memcpy(dw_new+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
00657 #endif
00658             }
00659             dvert->dw = dw_new;
00660         }
00661         else {
00662             /* If there are no other deform weights left then just remove this one. */
00663             MEM_freeN(dvert->dw);
00664             dvert->dw = NULL;
00665         }
00666     }
00667 }