2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): Reevan McKay
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/blenkernel/intern/deform.c
37 #include "MEM_guardedalloc.h"
39 #include "DNA_meshdata_types.h"
40 #include "DNA_object_types.h"
42 #include "BKE_deform.h"
44 #include "BLI_blenlib.h"
45 #include "BLI_utildefines.h"
48 #include "BLI_cellalloc.h"
51 void defgroup_copy_list(ListBase *outbase, ListBase *inbase)
53 bDeformGroup *defgroup, *defgroupn;
55 outbase->first= outbase->last= NULL;
57 for (defgroup = inbase->first; defgroup; defgroup=defgroup->next){
58 defgroupn= defgroup_duplicate(defgroup);
59 BLI_addtail(outbase, defgroupn);
63 bDeformGroup *defgroup_duplicate(bDeformGroup *ingroup)
65 bDeformGroup *outgroup;
70 outgroup=MEM_callocN(sizeof(bDeformGroup), "copy deformGroup");
72 /* For now, just copy everything over. */
73 memcpy (outgroup, ingroup, sizeof(bDeformGroup));
75 outgroup->next=outgroup->prev=NULL;
80 /* copy & overwrite weights */
81 void defvert_copy(MDeformVert *dvert_dst, const MDeformVert *dvert_src)
83 if (dvert_dst->totweight == dvert_src->totweight) {
84 if (dvert_src->totweight)
85 memcpy(dvert_dst->dw, dvert_src->dw, dvert_src->totweight * sizeof(MDeformWeight));
89 BLI_cellalloc_free(dvert_dst->dw);
91 if (dvert_src->totweight)
92 dvert_dst->dw= BLI_cellalloc_dupalloc(dvert_src->dw);
96 dvert_dst->totweight = dvert_src->totweight;
100 /* copy an index from one dvert to another
101 * - do nothing if neither are set.
102 * - add destination weight if needed.
104 void defvert_copy_index(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const int defgroup)
106 MDeformWeight *dw_src, *dw_dst;
108 dw_src= defvert_find_index(dvert_src, defgroup);
111 /* source is valid, verify destination */
112 dw_dst= defvert_verify_index(dvert_dst, defgroup);
113 dw_dst->weight= dw_src->weight;
116 /* source was NULL, assign zero, could also remove */
117 dw_dst= defvert_find_index(dvert_dst, defgroup);
120 dw_dst->weight= 0.0f;
125 /* only sync over matching weights, don't add or remove groups
126 * warning, loop within loop.
128 void defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, int use_verify)
130 if (dvert_src->totweight && dvert_dst->totweight) {
132 MDeformWeight *dw_src;
133 for (i=0, dw_src=dvert_src->dw; i < dvert_src->totweight; i++, dw_src++) {
134 MDeformWeight *dw_dst;
135 if (use_verify) dw_dst= defvert_verify_index(dvert_dst, dw_src->def_nr);
136 else dw_dst= defvert_find_index(dvert_dst, dw_src->def_nr);
139 dw_dst->weight= dw_src->weight;
145 /* be sure all flip_map values are valid */
146 void defvert_sync_mapped(MDeformVert *dvert_dst, const MDeformVert *dvert_src,
147 const int *flip_map, const int flip_map_len, const int use_verify)
149 if (dvert_src->totweight && dvert_dst->totweight) {
151 MDeformWeight *dw_src;
152 for (i=0, dw_src=dvert_src->dw; i < dvert_src->totweight; i++, dw_src++) {
153 if (dw_src->def_nr < flip_map_len) {
154 MDeformWeight *dw_dst;
155 if (use_verify) dw_dst= defvert_verify_index(dvert_dst, flip_map[dw_src->def_nr]);
156 else dw_dst= defvert_find_index(dvert_dst, flip_map[dw_src->def_nr]);
159 dw_dst->weight= dw_src->weight;
166 /* be sure all flip_map values are valid */
167 void defvert_remap(MDeformVert *dvert, int *map, const int map_len)
169 MDeformWeight *dw= dvert->dw;
171 for (i= dvert->totweight; i != 0; i--, dw++) {
172 if (dw->def_nr < map_len) {
173 dw->def_nr= map[dw->def_nr];
176 BLI_assert(dw->def_nr >= 0);
181 void defvert_normalize(MDeformVert *dvert)
183 if (dvert->totweight <= 0) {
186 else if (dvert->totweight==1) {
187 dvert->dw[0].weight= 1.0f;
192 float tot_weight= 0.0f;
194 for (i= dvert->totweight, dw= dvert->dw; i != 0; i--, dw++) {
195 tot_weight += dw->weight;
198 if (tot_weight > 0.0f) {
199 float scalar= 1.0f / tot_weight;
200 for (i= dvert->totweight, dw= dvert->dw; i != 0; i--, dw++) {
201 dw->weight *= scalar;
203 /* incase of division errors with very low weights */
204 CLAMP(dw->weight, 0.0f, 1.0f);
210 void defvert_normalize_lock(MDeformVert *dvert, const int def_nr_lock)
212 if (dvert->totweight <= 0) {
215 else if (dvert->totweight==1) {
216 dvert->dw[0].weight= 1.0f;
219 MDeformWeight *dw_lock = NULL;
222 float tot_weight= 0.0f;
223 float lock_iweight= 1.0f;
225 for (i= dvert->totweight, dw= dvert->dw; i != 0; i--, dw++) {
226 if(dw->def_nr != def_nr_lock) {
227 tot_weight += dw->weight;
231 lock_iweight = (1.0f - dw_lock->weight);
232 CLAMP(lock_iweight, 0.0f, 1.0f);
236 if (tot_weight > 0.0f) {
237 /* paranoid, should be 1.0 but incase of float error clamp anyway */
239 float scalar= (1.0f / tot_weight) * lock_iweight;
240 for (i= dvert->totweight, dw= dvert->dw; i != 0; i--, dw++) {
242 dw->weight *= scalar;
244 /* incase of division errors with very low weights */
245 CLAMP(dw->weight, 0.0f, 1.0f);
252 void defvert_flip(MDeformVert *dvert, const int *flip_map, const int flip_map_len)
257 for (dw= dvert->dw, i=0; i<dvert->totweight; dw++, i++) {
258 if (dw->def_nr < flip_map_len) {
259 if (flip_map[dw->def_nr] >= 0) {
260 dw->def_nr= flip_map[dw->def_nr];
267 bDeformGroup *defgroup_find_name(Object *ob, const char *name)
269 /* return a pointer to the deform group with this name
270 * or return NULL otherwise.
272 bDeformGroup *curdef;
274 for (curdef = ob->defbase.first; curdef; curdef=curdef->next) {
275 if (!strcmp(curdef->name, name)) {
282 int defgroup_name_index(Object *ob, const char *name)
284 /* Return the location of the named deform group within the list of
285 * deform groups. This function is a combination of BLI_findlink and
286 * defgroup_find_name. The other two could be called instead, but that
287 * require looping over the vertexgroups twice.
289 bDeformGroup *curdef;
292 if (name && name[0] != '\0') {
293 for (curdef=ob->defbase.first, def_nr=0; curdef; curdef=curdef->next, def_nr++) {
294 if (!strcmp(curdef->name, name))
302 /* note, must be freed */
303 int *defgroup_flip_map(Object *ob, int *flip_map_len, int use_default)
305 int defbase_tot= *flip_map_len= BLI_countlist(&ob->defbase);
307 if (defbase_tot==0) {
312 char name[sizeof(dg->name)];
313 int i, flip_num, *map= MEM_mallocN(defbase_tot * sizeof(int), __func__);
315 for (i=0; i < defbase_tot; i++) {
319 for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
320 if (map[i] == -1) { /* may be calculated previously */
322 /* incase no valid value is found, use this */
326 flip_side_name(name, dg->name, FALSE);
327 if (strcmp(name, dg->name)) {
328 flip_num= defgroup_name_index(ob, name);
331 map[flip_num]= i; /* save an extra lookup */
340 /* note, must be freed */
341 int *defgroup_flip_map_single(Object *ob, int *flip_map_len, int use_default, int defgroup)
343 int defbase_tot= *flip_map_len= BLI_countlist(&ob->defbase);
345 if (defbase_tot==0) {
350 char name[sizeof(dg->name)];
351 int i, flip_num, *map= MEM_mallocN(defbase_tot * sizeof(int), __func__);
353 for (i=0; i < defbase_tot; i++) {
354 if (use_default) map[i]= i;
358 dg= BLI_findlink(&ob->defbase, defgroup);
360 flip_side_name(name, dg->name, FALSE);
361 if (strcmp(name, dg->name)) {
362 flip_num= defgroup_name_index(ob, name);
365 map[defgroup]= flip_num;
366 map[flip_num]= defgroup;
374 int defgroup_flip_index(Object *ob, int index, int use_default)
376 bDeformGroup *dg= BLI_findlink(&ob->defbase, index);
380 char name[sizeof(dg->name)];
381 flip_side_name(name, dg->name, 0);
383 if (strcmp(name, dg->name))
384 flip_index= defgroup_name_index(ob, name);
387 return (flip_index==-1 && use_default) ? index : flip_index;
390 static int defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
392 bDeformGroup *curdef;
394 for (curdef = ob->defbase.first; curdef; curdef=curdef->next) {
396 if (!strcmp(curdef->name, name)) {
405 static int defgroup_unique_check(void *arg, const char *name)
407 struct {Object *ob; void *dg;} *data= arg;
408 return defgroup_find_name_dupe(name, data->dg, data->ob);
411 void defgroup_unique_name(bDeformGroup *dg, Object *ob)
413 struct {Object *ob; void *dg;} data;
417 BLI_uniquename_cb(defgroup_unique_check, &data, "Group", '.', dg->name, sizeof(dg->name));
420 /* finds the best possible flipped name. For renaming; check for unique names afterwards */
421 /* if strip_number: removes number extensions
422 * note: dont use sizeof() for 'name' or 'from_name' */
423 void flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME], int strip_number)
426 char prefix[MAX_VGROUP_NAME]= ""; /* The part before the facing */
427 char suffix[MAX_VGROUP_NAME]= ""; /* The part after the facing */
428 char replace[MAX_VGROUP_NAME]= ""; /* The replacement string */
429 char number[MAX_VGROUP_NAME]= ""; /* The number extension string */
432 /* always copy the name, since this can be called with an uninitialized string */
433 BLI_strncpy(name, from_name, MAX_VGROUP_NAME);
435 len= BLI_strnlen(from_name, MAX_VGROUP_NAME);
437 /* we don't do names like .R or .L */
441 /* We first check the case with a .### extension, let's find the last period */
442 if (isdigit(name[len-1])) {
443 index= strrchr(name, '.'); // last occurrence
444 if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
446 BLI_strncpy(number, index, sizeof(number));
448 len= BLI_strnlen(name, MAX_VGROUP_NAME);
452 BLI_strncpy(prefix, name, sizeof(prefix));
454 #define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')
456 /* first case; separator . - _ with extensions r R l L */
457 if (IS_SEPARATOR(name[len-2]) ) {
458 switch(name[len-1]) {
461 strcpy(replace, "r");
465 strcpy(replace, "l");
469 strcpy(replace, "R");
473 strcpy(replace, "L");
477 /* case; beginning with r R l L , with separator after it */
478 else if (IS_SEPARATOR(name[1]) ) {
481 strcpy(replace, "r");
482 BLI_strncpy(suffix, name+1, sizeof(suffix));
486 strcpy(replace, "l");
487 BLI_strncpy(suffix, name+1, sizeof(suffix));
491 strcpy(replace, "R");
492 BLI_strncpy(suffix, name+1, sizeof(suffix));
496 strcpy(replace, "L");
497 BLI_strncpy(suffix, name+1, sizeof(suffix));
503 /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
504 index = BLI_strcasestr(prefix, "right");
505 if (index==prefix || index==prefix+len-5) {
507 strcpy(replace, "left");
510 strcpy(replace, "LEFT");
512 strcpy(replace, "Left");
515 BLI_strncpy(suffix, index+5, sizeof(suffix));
518 index = BLI_strcasestr(prefix, "left");
519 if (index==prefix || index==prefix+len-4) {
521 strcpy(replace, "right");
524 strcpy(replace, "RIGHT");
526 strcpy(replace, "Right");
529 BLI_strncpy(suffix, index + 4, sizeof(suffix));
536 BLI_snprintf (name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
539 float defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
541 MDeformWeight *dw= defvert_find_index(dvert, defgroup);
542 return dw ? dw->weight : 0.0f;
545 /* take care with this the rationale is:
546 * - if the object has no vertex group. act like vertex group isnt set and return 1.0,
547 * - if the vertex group exists but the 'defgroup' isnt found on this vertex, _still_ return 0.0
549 * This is a bit confusing, just saves some checks from the caller.
551 float defvert_array_find_weight_safe(const struct MDeformVert *dvert, const int index, const int defgroup)
553 if (defgroup == -1 || dvert == NULL)
556 return defvert_find_weight(dvert+index, defgroup);
560 MDeformWeight *defvert_find_index(const MDeformVert *dvert, const int defgroup)
562 if (dvert && defgroup >= 0) {
563 MDeformWeight *dw = dvert->dw;
566 for (i= dvert->totweight; i != 0; i--, dw++) {
567 if (dw->def_nr == defgroup) {
576 /* Ensures that mv has a deform weight entry for the specified defweight group */
577 /* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
578 MDeformWeight *defvert_verify_index(MDeformVert *dvert, const int defgroup)
580 MDeformWeight *dw_new;
582 /* do this check always, this function is used to check for it */
583 if (!dvert || defgroup < 0)
586 dw_new= defvert_find_index(dvert, defgroup);
590 dw_new= BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dvert->totweight+1), "deformWeight");
592 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
593 BLI_cellalloc_free(dvert->dw);
596 dw_new += dvert->totweight;
597 dw_new->weight= 0.0f;
598 dw_new->def_nr= defgroup;
606 /* TODO. merge with code above! */
608 /* Adds the given vertex to the specified vertex group, with given weight.
609 * warning, this does NOT check for existign, assume caller already knows its not there */
610 void defvert_add_index_notest(MDeformVert *dvert, int defgroup, const float weight)
612 MDeformWeight *dw_new;
614 /* do this check always, this function is used to check for it */
615 if (!dvert || defgroup < 0)
618 dw_new = BLI_cellalloc_calloc(sizeof(MDeformWeight)*(dvert->totweight+1), "defvert_add_to group, new deformWeight");
620 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight)*dvert->totweight);
621 BLI_cellalloc_free(dvert->dw);
624 dw_new += dvert->totweight;
625 dw_new->weight = weight;
626 dw_new->def_nr = defgroup;
631 /* Removes the given vertex from the vertex group.
632 * WARNING: This function frees the given MDeformWeight, do not use it afterward! */
633 void defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
636 MDeformWeight *dw_new;
637 int i = dw - dvert->dw;
639 /* Security check! */
640 if(i < 0 || i >= dvert->totweight) {
645 /* If there are still other deform weights attached to this vert then remove
646 * this deform weight, and reshuffle the others.
648 if (dvert->totweight) {
649 dw_new = BLI_cellalloc_malloc(sizeof(MDeformWeight)*(dvert->totweight), __func__);
651 #if 1 /* since we dont care about order, swap this with the last, save a memcpy */
652 if (i != dvert->totweight) {
653 dvert->dw[i]= dvert->dw[dvert->totweight];
655 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
657 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight)*i);
658 memcpy(dw_new+i, dvert->dw+i+1, sizeof(MDeformWeight)*(dvert->totweight-i));
660 BLI_cellalloc_free(dvert->dw);
665 /* If there are no other deform weights left then just remove this one. */
666 BLI_cellalloc_free(dvert->dw);