|
Blender
V2.59
|
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 }