Blender  V2.59
deform.c
Go to the documentation of this file.
00001 /*  deform.c   June 2001
00002  *  
00003  *  support for deformation groups
00004  * 
00005  *      Reevan McKay
00006  *
00007  * $Id: deform.c 37239 2011-06-06 06:40:09Z campbellbarton $
00008  *
00009  * ***** BEGIN GPL LICENSE BLOCK *****
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00024  *
00025  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00026  * All rights reserved.
00027  *
00028  * The Original Code is: all of this file.
00029  *
00030  * Contributor(s): none yet.
00031  *
00032  * ***** END GPL LICENSE BLOCK *****
00033  */
00034 
00040 #include <string.h>
00041 #include <math.h>
00042 #include "ctype.h"
00043 
00044 #include "MEM_guardedalloc.h"
00045 
00046 #include "DNA_meshdata_types.h"
00047 #include "DNA_object_types.h"
00048 
00049 #include "BKE_deform.h"
00050 
00051 #include "BLI_blenlib.h"
00052 
00053 
00054 void defgroup_copy_list (ListBase *outbase, ListBase *inbase)
00055 {
00056         bDeformGroup *defgroup, *defgroupn;
00057 
00058         outbase->first= outbase->last= NULL;
00059 
00060         for (defgroup = inbase->first; defgroup; defgroup=defgroup->next){
00061                 defgroupn= defgroup_duplicate(defgroup);
00062                 BLI_addtail(outbase, defgroupn);
00063         }
00064 }
00065 
00066 bDeformGroup *defgroup_duplicate (bDeformGroup *ingroup)
00067 {
00068         bDeformGroup *outgroup;
00069 
00070         if (!ingroup)
00071                 return NULL;
00072 
00073         outgroup=MEM_callocN(sizeof(bDeformGroup), "copy deformGroup");
00074         
00075         /* For now, just copy everything over. */
00076         memcpy (outgroup, ingroup, sizeof(bDeformGroup));
00077 
00078         outgroup->next=outgroup->prev=NULL;
00079 
00080         return outgroup;
00081 }
00082 
00083 /* copy & overwrite weights */
00084 void defvert_copy (MDeformVert *dvert_r, const MDeformVert *dvert)
00085 {
00086         if(dvert_r->totweight == dvert->totweight) {
00087                 if(dvert->totweight)
00088                         memcpy(dvert_r->dw, dvert->dw, dvert->totweight * sizeof(MDeformWeight));
00089         }
00090         else {
00091                 if(dvert_r->dw)
00092                         MEM_freeN(dvert_r->dw);
00093 
00094                 if(dvert->totweight)
00095                         dvert_r->dw= MEM_dupallocN(dvert->dw);
00096                 else
00097                         dvert_r->dw= NULL;
00098 
00099                 dvert_r->totweight = dvert->totweight;
00100         }
00101 }
00102 
00103 /* only sync over matching weights, don't add or remove groups
00104  * warning, loop within loop.
00105  */
00106 void defvert_sync (MDeformVert *dvert_r, const MDeformVert *dvert, int use_verify)
00107 {
00108         if(dvert->totweight && dvert_r->totweight) {
00109                 int i;
00110                 MDeformWeight *dw;
00111                 for(i=0, dw=dvert->dw; i < dvert->totweight; i++, dw++) {
00112                         MDeformWeight *dw_r;
00113                         if(use_verify)  dw_r= defvert_find_index(dvert_r, dw->def_nr);
00114                         else                    dw_r= defvert_verify_index(dvert_r, dw->def_nr);
00115 
00116                         if(dw_r) {
00117                                 dw_r->weight= dw->weight;
00118                         }
00119                 }
00120         }
00121 }
00122 
00123 /* be sure all flip_map values are valid */
00124 void defvert_sync_mapped (MDeformVert *dvert_r, const MDeformVert *dvert, const int *flip_map, int use_verify)
00125 {
00126         if(dvert->totweight && dvert_r->totweight) {
00127                 int i;
00128                 MDeformWeight *dw;
00129                 for(i=0, dw=dvert->dw; i < dvert->totweight; i++, dw++) {
00130                         MDeformWeight *dw_r;
00131                         if(use_verify)  dw_r= defvert_find_index(dvert_r, flip_map[dw->def_nr]);
00132                         else                    dw_r= defvert_verify_index(dvert_r, flip_map[dw->def_nr]);
00133 
00134                         if(dw_r) {
00135                                 dw_r->weight= dw->weight;
00136                         }
00137                 }
00138         }
00139 }
00140 
00141 /* be sure all flip_map values are valid */
00142 void defvert_remap (MDeformVert *dvert, int *map)
00143 {
00144         MDeformWeight *dw;
00145         int i;
00146         for(i=0, dw=dvert->dw; i<dvert->totweight; i++, dw++) {
00147                 dw->def_nr= map[dw->def_nr];
00148         }
00149 }
00150 
00151 void defvert_normalize (MDeformVert *dvert)
00152 {
00153         if(dvert->totweight<=0) {
00154                 /* nothing */
00155         }
00156         else if (dvert->totweight==1) {
00157                 dvert->dw[0].weight= 1.0f;
00158         }
00159         else {
00160                 int i;
00161                 float tot= 0.0f;
00162                 MDeformWeight *dw;
00163                 for(i=0, dw=dvert->dw; i < dvert->totweight; i++, dw++)
00164                         tot += dw->weight;
00165 
00166                 if(tot > 0.0f) {
00167                         for(i=0, dw=dvert->dw; i < dvert->totweight; i++, dw++)
00168                                 dw->weight /= tot;
00169                 }
00170         }
00171 }
00172 
00173 void defvert_flip (MDeformVert *dvert, const int *flip_map)
00174 {
00175         MDeformWeight *dw;
00176         int i;
00177 
00178         for(dw= dvert->dw, i=0; i<dvert->totweight; dw++, i++)
00179                 if(flip_map[dw->def_nr] >= 0)
00180                         dw->def_nr= flip_map[dw->def_nr];
00181 }
00182 
00183 
00184 bDeformGroup *defgroup_find_name (Object *ob, const char *name)
00185 {
00186         /* return a pointer to the deform group with this name
00187          * or return NULL otherwise.
00188          */
00189         bDeformGroup *curdef;
00190 
00191         for (curdef = ob->defbase.first; curdef; curdef=curdef->next) {
00192                 if (!strcmp(curdef->name, name)) {
00193                         return curdef;
00194                 }
00195         }
00196         return NULL;
00197 }
00198 
00199 int defgroup_name_index (Object *ob, const char *name)
00200 {
00201         /* Return the location of the named deform group within the list of
00202          * deform groups. This function is a combination of defgroup_find_index and
00203          * defgroup_find_name. The other two could be called instead, but that
00204          * require looping over the vertexgroups twice.
00205          */
00206         bDeformGroup *curdef;
00207         int def_nr;
00208         
00209         if(name && name[0] != '\0') {
00210                 for (curdef=ob->defbase.first, def_nr=0; curdef; curdef=curdef->next, def_nr++) {
00211                         if (!strcmp(curdef->name, name))
00212                                 return def_nr;
00213                 }
00214         }
00215 
00216         return -1;
00217 }
00218 
00219 int defgroup_find_index (Object *ob, bDeformGroup *dg)
00220 {
00221         /* Fetch the location of this deform group
00222          * within the linked list of deform groups.
00223          * (this number is stored in the deform
00224          * weights of the deform verts to link them
00225          * to this deform group).
00226          *
00227          * note: this is zero based, ob->actdef starts at 1.
00228          */
00229 
00230         bDeformGroup *eg;
00231         int def_nr;
00232 
00233         eg = ob->defbase.first;
00234         def_nr = 0;
00235 
00236         /* loop through all deform groups */
00237         while (eg != NULL) {
00238 
00239                 /* if the current deform group is
00240                  * the one we are after, return
00241                  * def_nr
00242                  */
00243                 if (eg == dg) {
00244                         break;
00245                 }
00246                 ++def_nr;
00247                 eg = eg->next;
00248         }
00249 
00250         /* if there was no deform group found then
00251          * return -1 (should set up a nice symbolic
00252          * constant for this)
00253          */
00254         if (eg == NULL) return -1;
00255         
00256         return def_nr;
00257 }
00258 
00259 /* note, must be freed */
00260 int *defgroup_flip_map(Object *ob, int use_default)
00261 {
00262         bDeformGroup *dg;
00263         int totdg= BLI_countlist(&ob->defbase);
00264 
00265         if(totdg==0) {
00266                 return NULL;
00267         }
00268         else {
00269                 char name[sizeof(dg->name)];
00270                 int i, flip_num, *map= MEM_mallocN(totdg * sizeof(int), "get_defgroup_flip_map");
00271 
00272                 memset(map, -1, totdg * sizeof(int));
00273 
00274                 for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
00275                         if(map[i] == -1) { /* may be calculated previously */
00276 
00277                                 /* incase no valid value is found, use this */
00278                                 if(use_default)
00279                                         map[i]= i;
00280 
00281                                 flip_side_name(name, dg->name, 0);
00282                                 if(strcmp(name, dg->name)) {
00283                                         flip_num= defgroup_name_index(ob, name);
00284                                         if(flip_num >= 0) {
00285                                                 map[i]= flip_num;
00286                                                 map[flip_num]= i; /* save an extra lookup */
00287                                         }
00288                                 }
00289                         }
00290                 }
00291                 return map;
00292         }
00293 }
00294 
00295 int defgroup_flip_index(Object *ob, int index, int use_default)
00296 {
00297         bDeformGroup *dg= BLI_findlink(&ob->defbase, index);
00298         int flip_index = -1;
00299 
00300         if(dg) {
00301                 char name[sizeof(dg->name)];
00302                 flip_side_name(name, dg->name, 0);
00303 
00304                 if(strcmp(name, dg->name))
00305                         flip_index= defgroup_name_index(ob, name);
00306         }
00307 
00308         return (flip_index==-1 && use_default) ? index : flip_index;
00309 }
00310 
00311 static int defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
00312 {
00313         bDeformGroup *curdef;
00314         
00315         for (curdef = ob->defbase.first; curdef; curdef=curdef->next) {
00316                 if (dg!=curdef) {
00317                         if (!strcmp(curdef->name, name)) {
00318                                 return 1;
00319                         }
00320                 }
00321         }
00322 
00323         return 0;
00324 }
00325 
00326 static int defgroup_unique_check(void *arg, const char *name)
00327 {
00328         struct {Object *ob; void *dg;} *data= arg;
00329         return defgroup_find_name_dupe(name, data->dg, data->ob);
00330 }
00331 
00332 void defgroup_unique_name (bDeformGroup *dg, Object *ob)
00333 {
00334         struct {Object *ob; void *dg;} data;
00335         data.ob= ob;
00336         data.dg= dg;
00337 
00338         BLI_uniquename_cb(defgroup_unique_check, &data, "Group", '.', dg->name, sizeof(dg->name));
00339 }
00340 
00341 /* finds the best possible flipped name. For renaming; check for unique names afterwards */
00342 /* if strip_number: removes number extensions
00343  * note: dont use sizeof() for 'name' or 'from_name' */
00344 void flip_side_name (char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME], int strip_number)
00345 {
00346         int     len;
00347         char    prefix[MAX_VGROUP_NAME]=  "";   /* The part before the facing */
00348         char    suffix[MAX_VGROUP_NAME]=  "";   /* The part after the facing */
00349         char    replace[MAX_VGROUP_NAME]= "";   /* The replacement string */
00350         char    number[MAX_VGROUP_NAME]=  "";   /* The number extension string */
00351         char    *index=NULL;
00352 
00353         len= BLI_strnlen(from_name, MAX_VGROUP_NAME);
00354         if(len<3) return; // we don't do names like .R or .L
00355 
00356         BLI_strncpy(name, from_name, MAX_VGROUP_NAME);
00357 
00358         /* We first check the case with a .### extension, let's find the last period */
00359         if(isdigit(name[len-1])) {
00360                 index= strrchr(name, '.'); // last occurrence
00361                 if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
00362                         if(strip_number==0)
00363                                 BLI_strncpy(number, index, sizeof(number));
00364                         *index= 0;
00365                         len= BLI_strnlen(name, MAX_VGROUP_NAME);
00366                 }
00367         }
00368 
00369         BLI_strncpy(prefix, name, sizeof(prefix));
00370 
00371 #define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')
00372 
00373         /* first case; separator . - _ with extensions r R l L  */
00374         if( IS_SEPARATOR(name[len-2]) ) {
00375                 switch(name[len-1]) {
00376                         case 'l':
00377                                 prefix[len-1]= 0;
00378                                 strcpy(replace, "r");
00379                                 break;
00380                         case 'r':
00381                                 prefix[len-1]= 0;
00382                                 strcpy(replace, "l");
00383                                 break;
00384                         case 'L':
00385                                 prefix[len-1]= 0;
00386                                 strcpy(replace, "R");
00387                                 break;
00388                         case 'R':
00389                                 prefix[len-1]= 0;
00390                                 strcpy(replace, "L");
00391                                 break;
00392                 }
00393         }
00394         /* case; beginning with r R l L , with separator after it */
00395         else if( IS_SEPARATOR(name[1]) ) {
00396                 switch(name[0]) {
00397                         case 'l':
00398                                 strcpy(replace, "r");
00399                                 strcpy(suffix, name+1);
00400                                 prefix[0]= 0;
00401                                 break;
00402                         case 'r':
00403                                 strcpy(replace, "l");
00404                                 strcpy(suffix, name+1);
00405                                 prefix[0]= 0;
00406                                 break;
00407                         case 'L':
00408                                 strcpy(replace, "R");
00409                                 strcpy(suffix, name+1);
00410                                 prefix[0]= 0;
00411                                 break;
00412                         case 'R':
00413                                 strcpy(replace, "L");
00414                                 strcpy(suffix, name+1);
00415                                 prefix[0]= 0;
00416                                 break;
00417                 }
00418         }
00419         else if(len > 5) {
00420                 /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
00421                 index = BLI_strcasestr(prefix, "right");
00422                 if (index==prefix || index==prefix+len-5) {
00423                         if(index[0]=='r')
00424                                 strcpy (replace, "left");
00425                         else {
00426                                 if(index[1]=='I')
00427                                         strcpy (replace, "LEFT");
00428                                 else
00429                                         strcpy (replace, "Left");
00430                         }
00431                         *index= 0;
00432                         strcpy (suffix, index+5);
00433                 }
00434                 else {
00435                         index = BLI_strcasestr(prefix, "left");
00436                         if (index==prefix || index==prefix+len-4) {
00437                                 if(index[0]=='l')
00438                                         strcpy (replace, "right");
00439                                 else {
00440                                         if(index[1]=='E')
00441                                                 strcpy (replace, "RIGHT");
00442                                         else
00443                                                 strcpy (replace, "Right");
00444                                 }
00445                                 *index= 0;
00446                                 strcpy (suffix, index+4);
00447                         }
00448                 }
00449         }
00450 
00451 #undef IS_SEPARATOR
00452 
00453         BLI_snprintf (name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
00454 }
00455 
00456 float defvert_find_weight(const struct MDeformVert *dvert, const int group_num)
00457 {
00458         MDeformWeight *dw= defvert_find_index(dvert, group_num);
00459         return dw ? dw->weight : 0.0f;
00460 }
00461 
00462 float defvert_array_find_weight_safe(const struct MDeformVert *dvert, int index, int group_num)
00463 {
00464         if(group_num == -1 || dvert == NULL)
00465                 return 1.0f;
00466 
00467         return defvert_find_weight(dvert+index, group_num);
00468 }
00469 
00470 
00471 MDeformWeight *defvert_find_index(const MDeformVert *dvert, const int defgroup)
00472 {
00473         if(dvert && defgroup >= 0) {
00474                 MDeformWeight *dw = dvert->dw;
00475                 int i;
00476 
00477                 for(i=dvert->totweight; i>0; i--, dw++)
00478                         if(dw->def_nr == defgroup)
00479                                 return dw;
00480         }
00481 
00482         return NULL;
00483 }
00484 
00485 /* Ensures that mv has a deform weight entry for the specified defweight group */
00486 /* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
00487 MDeformWeight *defvert_verify_index(MDeformVert *dv, const int defgroup)
00488 {
00489         MDeformWeight *newdw;
00490 
00491         /* do this check always, this function is used to check for it */
00492         if(!dv || defgroup<0)
00493                 return NULL;
00494 
00495         newdw = defvert_find_index(dv, defgroup);
00496         if(newdw)
00497                 return newdw;
00498 
00499         newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
00500         if(dv->dw) {
00501                 memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
00502                 MEM_freeN(dv->dw);
00503         }
00504         dv->dw=newdw;
00505 
00506         dv->dw[dv->totweight].weight=0.0f;
00507         dv->dw[dv->totweight].def_nr=defgroup;
00508         /* Group index */
00509 
00510         dv->totweight++;
00511 
00512         return dv->dw+(dv->totweight-1);
00513 }