7967013c2d4211b2929829684bdb2a22f076d4f8
[blender.git] / source / blender / blenkernel / intern / deform.c
1 /*  deform.c   June 2001
2  *  
3  *  support for deformation groups
4  * 
5  *      Reevan McKay
6  *
7  * $Id$
8  *
9  * ***** BEGIN GPL LICENSE BLOCK *****
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26  * All rights reserved.
27  *
28  * The Original Code is: all of this file.
29  *
30  * Contributor(s): none yet.
31  *
32  * ***** END GPL LICENSE BLOCK *****
33  */
34
35 #include <string.h>
36 #include <math.h>
37 #include "ctype.h"
38
39 #include "MEM_guardedalloc.h"
40
41 #include "DNA_meshdata_types.h"
42 #include "DNA_object_types.h"
43
44 #include "BKE_deform.h"
45
46 #include "BLI_blenlib.h"
47
48
49 void defgroup_copy_list (ListBase *outbase, ListBase *inbase)
50 {
51         bDeformGroup *defgroup, *defgroupn;
52
53         outbase->first= outbase->last= NULL;
54
55         for (defgroup = inbase->first; defgroup; defgroup=defgroup->next){
56                 defgroupn= defgroup_duplicate(defgroup);
57                 BLI_addtail(outbase, defgroupn);
58         }
59 }
60
61 bDeformGroup *defgroup_duplicate (bDeformGroup *ingroup)
62 {
63         bDeformGroup *outgroup;
64
65         if (!ingroup)
66                 return NULL;
67
68         outgroup=MEM_callocN(sizeof(bDeformGroup), "copy deformGroup");
69         
70         /* For now, just copy everything over. */
71         memcpy (outgroup, ingroup, sizeof(bDeformGroup));
72
73         outgroup->next=outgroup->prev=NULL;
74
75         return outgroup;
76 }
77
78 /* copy & overwrite weights */
79 void defvert_copy (MDeformVert *dvert_r, const MDeformVert *dvert)
80 {
81         if(dvert_r->totweight == dvert->totweight) {
82                 if(dvert->totweight)
83                         memcpy(dvert_r->dw, dvert->dw, dvert->totweight * sizeof(MDeformWeight));
84         }
85         else {
86                 if(dvert_r->dw)
87                         MEM_freeN(dvert_r->dw);
88
89                 if(dvert->totweight)
90                         dvert_r->dw= MEM_dupallocN(dvert->dw);
91                 else
92                         dvert_r->dw= NULL;
93
94                 dvert_r->totweight = dvert->totweight;
95         }
96 }
97
98 /* only sync over matching weights, don't add or remove groups
99  * warning, loop within loop.
100  */
101 void defvert_sync (MDeformVert *dvert_r, const MDeformVert *dvert, int use_verify)
102 {
103         if(dvert->totweight && dvert_r->totweight) {
104                 int i;
105                 MDeformWeight *dw;
106                 for(i=0, dw=dvert->dw; i < dvert->totweight; i++, dw++) {
107                         MDeformWeight *dw_r;
108                         if(use_verify)  dw_r= defvert_find_index(dvert_r, dw->def_nr);
109                         else                    dw_r= defvert_verify_index(dvert_r, dw->def_nr);
110
111                         if(dw_r) {
112                                 dw_r->weight= dw->weight;
113                         }
114                 }
115         }
116 }
117
118 /* be sure all flip_map values are valid */
119 void defvert_sync_mapped (MDeformVert *dvert_r, const MDeformVert *dvert, int *flip_map, int use_verify)
120 {
121         if(dvert->totweight && dvert_r->totweight) {
122                 int i;
123                 MDeformWeight *dw;
124                 for(i=0, dw=dvert->dw; i < dvert->totweight; i++, dw++) {
125                         MDeformWeight *dw_r;
126                         if(use_verify)  dw_r= defvert_find_index(dvert_r, flip_map[dw->def_nr]);
127                         else                    dw_r= defvert_verify_index(dvert_r, flip_map[dw->def_nr]);
128
129                         if(dw_r) {
130                                 dw_r->weight= dw->weight;
131                         }
132                 }
133         }
134 }
135
136 /* be sure all flip_map values are valid */
137 void defvert_remap (MDeformVert *dvert, int *map)
138 {
139         MDeformWeight *dw;
140         int i;
141         for(i=0, dw=dvert->dw; i<dvert->totweight; i++, dw++) {
142                 dw->def_nr= map[dw->def_nr];
143         }
144 }
145
146 void defvert_normalize (MDeformVert *dvert)
147 {
148         if(dvert->totweight<=0) {
149                 /* nothing */
150         }
151         else if (dvert->totweight==1) {
152                 dvert->dw[0].weight= 1.0f;
153         }
154         else {
155                 int i;
156                 float tot= 0.0f;
157                 MDeformWeight *dw;
158                 for(i=0, dw=dvert->dw; i < dvert->totweight; i++, dw++)
159                         tot += dw->weight;
160
161                 if(tot > 0.0f) {
162                         for(i=0, dw=dvert->dw; i < dvert->totweight; i++, dw++)
163                                 dw->weight /= tot;
164                 }
165         }
166 }
167
168 void defvert_flip (MDeformVert *dvert, int *flip_map)
169 {
170         MDeformWeight *dw;
171         int i;
172
173         for(dw= dvert->dw, i=0; i<dvert->totweight; dw++, i++)
174                 if(flip_map[dw->def_nr] >= 0)
175                         dw->def_nr= flip_map[dw->def_nr];
176 }
177
178
179 bDeformGroup *defgroup_find_name (Object *ob, const char *name)
180 {
181         /* return a pointer to the deform group with this name
182          * or return NULL otherwise.
183          */
184         bDeformGroup *curdef;
185
186         for (curdef = ob->defbase.first; curdef; curdef=curdef->next) {
187                 if (!strcmp(curdef->name, name)) {
188                         return curdef;
189                 }
190         }
191         return NULL;
192 }
193
194 int defgroup_name_index (Object *ob, const char *name)
195 {
196         /* Return the location of the named deform group within the list of
197          * deform groups. This function is a combination of defgroup_find_index and
198          * defgroup_find_name. The other two could be called instead, but that
199          * require looping over the vertexgroups twice.
200          */
201         bDeformGroup *curdef;
202         int def_nr;
203         
204         if(name && name[0] != '\0') {
205                 for (curdef=ob->defbase.first, def_nr=0; curdef; curdef=curdef->next, def_nr++) {
206                         if (!strcmp(curdef->name, name))
207                                 return def_nr;
208                 }
209         }
210
211         return -1;
212 }
213
214 int defgroup_find_index (Object *ob, bDeformGroup *dg)
215 {
216         /* Fetch the location of this deform group
217          * within the linked list of deform groups.
218          * (this number is stored in the deform
219          * weights of the deform verts to link them
220          * to this deform group).
221          *
222          * note: this is zero based, ob->actdef starts at 1.
223          */
224
225         bDeformGroup *eg;
226         int def_nr;
227
228         eg = ob->defbase.first;
229         def_nr = 0;
230
231         /* loop through all deform groups */
232         while (eg != NULL) {
233
234                 /* if the current deform group is
235                  * the one we are after, return
236                  * def_nr
237                  */
238                 if (eg == dg) {
239                         break;
240                 }
241                 ++def_nr;
242                 eg = eg->next;
243         }
244
245         /* if there was no deform group found then
246          * return -1 (should set up a nice symbolic
247          * constant for this)
248          */
249         if (eg == NULL) return -1;
250         
251         return def_nr;
252     
253 }
254
255 /* note, must be freed */
256 int *defgroup_flip_map(Object *ob, int use_default)
257 {
258         bDeformGroup *dg;
259         int totdg= BLI_countlist(&ob->defbase);
260
261         if(totdg==0) {
262                 return NULL;
263         }
264         else {
265                 char name[sizeof(dg->name)];
266                 int i, flip_num, *map= MEM_mallocN(totdg * sizeof(int), "get_defgroup_flip_map");
267
268                 memset(map, -1, totdg * sizeof(int));
269
270                 for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
271                         if(map[i] == -1) { /* may be calculated previously */
272
273                                 /* incase no valid value is found, use this */
274                                 if(use_default)
275                                         map[i]= i;
276
277                                 flip_side_name(name, dg->name, 0);
278                                 if(strcmp(name, dg->name)) {
279                                         flip_num= defgroup_name_index(ob, name);
280                                         if(flip_num >= 0) {
281                                                 map[i]= flip_num;
282                                                 map[flip_num]= i; /* save an extra lookup */
283                                         }
284                                 }
285                         }
286                 }
287                 return map;
288         }
289 }
290
291 int defgroup_flip_index(Object *ob, int index, int use_default)
292 {
293         bDeformGroup *dg= BLI_findlink(&ob->defbase, index);
294         int flip_index = -1;
295
296         if(dg) {
297                 char name[sizeof(dg->name)];
298                 flip_side_name(name, dg->name, 0);
299
300                 if(strcmp(name, dg->name))
301                         flip_index= defgroup_name_index(ob, name);
302         }
303
304         return (flip_index==-1 && use_default) ? index : flip_index;
305 }
306
307 static int defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
308 {
309         bDeformGroup *curdef;
310         
311         for (curdef = ob->defbase.first; curdef; curdef=curdef->next) {
312                 if (dg!=curdef) {
313                         if (!strcmp(curdef->name, name)) {
314                                 return 1;
315                         }
316                 }
317         }
318
319         return 0;
320 }
321
322 static int defgroup_unique_check(void *arg, const char *name)
323 {
324         struct {Object *ob; void *dg;} *data= arg;
325         return defgroup_find_name_dupe(name, data->dg, data->ob);
326 }
327
328 void defgroup_unique_name (bDeformGroup *dg, Object *ob)
329 {
330         struct {Object *ob; void *dg;} data;
331         data.ob= ob;
332         data.dg= dg;
333
334         BLI_uniquename_cb(defgroup_unique_check, &data, "Group", '.', dg->name, sizeof(dg->name));
335 }
336
337 /* finds the best possible flipped name. For renaming; check for unique names afterwards */
338 /* if strip_number: removes number extensions
339  * note: dont use sizeof() for 'name' or 'from_name' */
340 void flip_side_name (char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME], int strip_number)
341 {
342         int     len;
343         char    prefix[MAX_VGROUP_NAME]=  "";   /* The part before the facing */
344         char    suffix[MAX_VGROUP_NAME]=  "";   /* The part after the facing */
345         char    replace[MAX_VGROUP_NAME]= "";   /* The replacement string */
346         char    number[MAX_VGROUP_NAME]=  "";   /* The number extension string */
347         char    *index=NULL;
348
349         len= BLI_strnlen(from_name, MAX_VGROUP_NAME);
350         if(len<3) return; // we don't do names like .R or .L
351
352         BLI_strncpy(name, from_name, MAX_VGROUP_NAME);
353
354         /* We first check the case with a .### extension, let's find the last period */
355         if(isdigit(name[len-1])) {
356                 index= strrchr(name, '.'); // last occurrence
357                 if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
358                         if(strip_number==0)
359                                  BLI_strncpy(number, index, sizeof(number));
360                         *index= 0;
361                         len= BLI_strnlen(name, MAX_VGROUP_NAME);
362                 }
363         }
364
365         BLI_strncpy(prefix, name, sizeof(prefix));
366
367 #define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')
368
369         /* first case; separator . - _ with extensions r R l L  */
370         if( IS_SEPARATOR(name[len-2]) ) {
371                 switch(name[len-1]) {
372                         case 'l':
373                                 prefix[len-1]= 0;
374                                 strcpy(replace, "r");
375                                 break;
376                         case 'r':
377                                 prefix[len-1]= 0;
378                                 strcpy(replace, "l");
379                                 break;
380                         case 'L':
381                                 prefix[len-1]= 0;
382                                 strcpy(replace, "R");
383                                 break;
384                         case 'R':
385                                 prefix[len-1]= 0;
386                                 strcpy(replace, "L");
387                                 break;
388                 }
389         }
390         /* case; beginning with r R l L , with separator after it */
391         else if( IS_SEPARATOR(name[1]) ) {
392                 switch(name[0]) {
393                         case 'l':
394                                 strcpy(replace, "r");
395                                 strcpy(suffix, name+1);
396                                 prefix[0]= 0;
397                                 break;
398                         case 'r':
399                                 strcpy(replace, "l");
400                                 strcpy(suffix, name+1);
401                                 prefix[0]= 0;
402                                 break;
403                         case 'L':
404                                 strcpy(replace, "R");
405                                 strcpy(suffix, name+1);
406                                 prefix[0]= 0;
407                                 break;
408                         case 'R':
409                                 strcpy(replace, "L");
410                                 strcpy(suffix, name+1);
411                                 prefix[0]= 0;
412                                 break;
413                 }
414         }
415         else if(len > 5) {
416                 /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
417                 index = BLI_strcasestr(prefix, "right");
418                 if (index==prefix || index==prefix+len-5) {
419                         if(index[0]=='r')
420                                 strcpy (replace, "left");
421                         else {
422                                 if(index[1]=='I')
423                                         strcpy (replace, "LEFT");
424                                 else
425                                         strcpy (replace, "Left");
426                         }
427                         *index= 0;
428                         strcpy (suffix, index+5);
429                 }
430                 else {
431                         index = BLI_strcasestr(prefix, "left");
432                         if (index==prefix || index==prefix+len-4) {
433                                 if(index[0]=='l')
434                                         strcpy (replace, "right");
435                                 else {
436                                         if(index[1]=='E')
437                                                 strcpy (replace, "RIGHT");
438                                         else
439                                                 strcpy (replace, "Right");
440                                 }
441                                 *index= 0;
442                                 strcpy (suffix, index+4);
443                         }
444                 }
445         }
446
447 #undef IS_SEPARATOR
448
449         BLI_snprintf (name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
450 }
451
452 float defvert_find_weight(const struct MDeformVert *dvert, const int group_num)
453 {
454         MDeformWeight *dw= defvert_find_index(dvert, group_num);
455         return dw ? dw->weight : 0.0f;
456 }
457
458 float defvert_array_find_weight_safe(const struct MDeformVert *dvert, int index, int group_num)
459 {
460         if(group_num == -1 || dvert == NULL)
461                 return 1.0f;
462
463         return defvert_find_weight(dvert+index, group_num);
464 }
465
466
467 MDeformWeight *defvert_find_index(const MDeformVert *dvert, const int defgroup)
468 {
469         if(dvert && defgroup >= 0) {
470                 MDeformWeight *dw = dvert->dw;
471                 int i;
472
473                 for(i=dvert->totweight; i>0; i--, dw++)
474                         if(dw->def_nr == defgroup)
475                                 return dw;
476         }
477
478         return NULL;
479 }
480
481 /* Ensures that mv has a deform weight entry for the specified defweight group */
482 /* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
483 MDeformWeight *defvert_verify_index(MDeformVert *dv, const int defgroup)
484 {
485         MDeformWeight *newdw;
486
487         /* do this check always, this function is used to check for it */
488         if(!dv || defgroup<0)
489                 return NULL;
490
491         newdw = defvert_find_index(dv, defgroup);
492         if(newdw)
493                 return newdw;
494
495         newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
496         if(dv->dw) {
497                 memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
498                 MEM_freeN(dv->dw);
499         }
500         dv->dw=newdw;
501
502         dv->dw[dv->totweight].weight=0.0f;
503         dv->dw[dv->totweight].def_nr=defgroup;
504         /* Group index */
505
506         dv->totweight++;
507
508         return dv->dw+(dv->totweight-1);
509 }