header cleanup (no functional changes)
[blender.git] / source / blender / blenkernel / intern / deform.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Reevan McKay
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/blenkernel/intern/deform.c
31  *  \ingroup bke
32  */
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, const 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, const 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 /* note, must be freed */
255 int *defgroup_flip_map(Object *ob, int use_default)
256 {
257         bDeformGroup *dg;
258         int totdg= BLI_countlist(&ob->defbase);
259
260         if(totdg==0) {
261                 return NULL;
262         }
263         else {
264                 char name[sizeof(dg->name)];
265                 int i, flip_num, *map= MEM_mallocN(totdg * sizeof(int), "get_defgroup_flip_map");
266
267                 memset(map, -1, totdg * sizeof(int));
268
269                 for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
270                         if(map[i] == -1) { /* may be calculated previously */
271
272                                 /* incase no valid value is found, use this */
273                                 if(use_default)
274                                         map[i]= i;
275
276                                 flip_side_name(name, dg->name, 0);
277                                 if(strcmp(name, dg->name)) {
278                                         flip_num= defgroup_name_index(ob, name);
279                                         if(flip_num >= 0) {
280                                                 map[i]= flip_num;
281                                                 map[flip_num]= i; /* save an extra lookup */
282                                         }
283                                 }
284                         }
285                 }
286                 return map;
287         }
288 }
289
290 int defgroup_flip_index(Object *ob, int index, int use_default)
291 {
292         bDeformGroup *dg= BLI_findlink(&ob->defbase, index);
293         int flip_index = -1;
294
295         if(dg) {
296                 char name[sizeof(dg->name)];
297                 flip_side_name(name, dg->name, 0);
298
299                 if(strcmp(name, dg->name))
300                         flip_index= defgroup_name_index(ob, name);
301         }
302
303         return (flip_index==-1 && use_default) ? index : flip_index;
304 }
305
306 static int defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
307 {
308         bDeformGroup *curdef;
309         
310         for (curdef = ob->defbase.first; curdef; curdef=curdef->next) {
311                 if (dg!=curdef) {
312                         if (!strcmp(curdef->name, name)) {
313                                 return 1;
314                         }
315                 }
316         }
317
318         return 0;
319 }
320
321 static int defgroup_unique_check(void *arg, const char *name)
322 {
323         struct {Object *ob; void *dg;} *data= arg;
324         return defgroup_find_name_dupe(name, data->dg, data->ob);
325 }
326
327 void defgroup_unique_name (bDeformGroup *dg, Object *ob)
328 {
329         struct {Object *ob; void *dg;} data;
330         data.ob= ob;
331         data.dg= dg;
332
333         BLI_uniquename_cb(defgroup_unique_check, &data, "Group", '.', dg->name, sizeof(dg->name));
334 }
335
336 /* finds the best possible flipped name. For renaming; check for unique names afterwards */
337 /* if strip_number: removes number extensions
338  * note: dont use sizeof() for 'name' or 'from_name' */
339 void flip_side_name (char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME], int strip_number)
340 {
341         int     len;
342         char    prefix[MAX_VGROUP_NAME]=  "";   /* The part before the facing */
343         char    suffix[MAX_VGROUP_NAME]=  "";   /* The part after the facing */
344         char    replace[MAX_VGROUP_NAME]= "";   /* The replacement string */
345         char    number[MAX_VGROUP_NAME]=  "";   /* The number extension string */
346         char    *index=NULL;
347
348         len= BLI_strnlen(from_name, MAX_VGROUP_NAME);
349         if(len<3) return; // we don't do names like .R or .L
350
351         BLI_strncpy(name, from_name, MAX_VGROUP_NAME);
352
353         /* We first check the case with a .### extension, let's find the last period */
354         if(isdigit(name[len-1])) {
355                 index= strrchr(name, '.'); // last occurrence
356                 if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever!
357                         if(strip_number==0)
358                                 BLI_strncpy(number, index, sizeof(number));
359                         *index= 0;
360                         len= BLI_strnlen(name, MAX_VGROUP_NAME);
361                 }
362         }
363
364         BLI_strncpy(prefix, name, sizeof(prefix));
365
366 #define IS_SEPARATOR(a) ((a)=='.' || (a)==' ' || (a)=='-' || (a)=='_')
367
368         /* first case; separator . - _ with extensions r R l L  */
369         if( IS_SEPARATOR(name[len-2]) ) {
370                 switch(name[len-1]) {
371                         case 'l':
372                                 prefix[len-1]= 0;
373                                 strcpy(replace, "r");
374                                 break;
375                         case 'r':
376                                 prefix[len-1]= 0;
377                                 strcpy(replace, "l");
378                                 break;
379                         case 'L':
380                                 prefix[len-1]= 0;
381                                 strcpy(replace, "R");
382                                 break;
383                         case 'R':
384                                 prefix[len-1]= 0;
385                                 strcpy(replace, "L");
386                                 break;
387                 }
388         }
389         /* case; beginning with r R l L , with separator after it */
390         else if( IS_SEPARATOR(name[1]) ) {
391                 switch(name[0]) {
392                         case 'l':
393                                 strcpy(replace, "r");
394                                 strcpy(suffix, name+1);
395                                 prefix[0]= 0;
396                                 break;
397                         case 'r':
398                                 strcpy(replace, "l");
399                                 strcpy(suffix, name+1);
400                                 prefix[0]= 0;
401                                 break;
402                         case 'L':
403                                 strcpy(replace, "R");
404                                 strcpy(suffix, name+1);
405                                 prefix[0]= 0;
406                                 break;
407                         case 'R':
408                                 strcpy(replace, "L");
409                                 strcpy(suffix, name+1);
410                                 prefix[0]= 0;
411                                 break;
412                 }
413         }
414         else if(len > 5) {
415                 /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
416                 index = BLI_strcasestr(prefix, "right");
417                 if (index==prefix || index==prefix+len-5) {
418                         if(index[0]=='r')
419                                 strcpy (replace, "left");
420                         else {
421                                 if(index[1]=='I')
422                                         strcpy (replace, "LEFT");
423                                 else
424                                         strcpy (replace, "Left");
425                         }
426                         *index= 0;
427                         strcpy (suffix, index+5);
428                 }
429                 else {
430                         index = BLI_strcasestr(prefix, "left");
431                         if (index==prefix || index==prefix+len-4) {
432                                 if(index[0]=='l')
433                                         strcpy (replace, "right");
434                                 else {
435                                         if(index[1]=='E')
436                                                 strcpy (replace, "RIGHT");
437                                         else
438                                                 strcpy (replace, "Right");
439                                 }
440                                 *index= 0;
441                                 strcpy (suffix, index+4);
442                         }
443                 }
444         }
445
446 #undef IS_SEPARATOR
447
448         BLI_snprintf (name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
449 }
450
451 float defvert_find_weight(const struct MDeformVert *dvert, const int group_num)
452 {
453         MDeformWeight *dw= defvert_find_index(dvert, group_num);
454         return dw ? dw->weight : 0.0f;
455 }
456
457 float defvert_array_find_weight_safe(const struct MDeformVert *dvert, int index, int group_num)
458 {
459         if(group_num == -1 || dvert == NULL)
460                 return 1.0f;
461
462         return defvert_find_weight(dvert+index, group_num);
463 }
464
465
466 MDeformWeight *defvert_find_index(const MDeformVert *dvert, const int defgroup)
467 {
468         if(dvert && defgroup >= 0) {
469                 MDeformWeight *dw = dvert->dw;
470                 int i;
471
472                 for(i=dvert->totweight; i>0; i--, dw++)
473                         if(dw->def_nr == defgroup)
474                                 return dw;
475         }
476
477         return NULL;
478 }
479
480 /* Ensures that mv has a deform weight entry for the specified defweight group */
481 /* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
482 MDeformWeight *defvert_verify_index(MDeformVert *dv, const int defgroup)
483 {
484         MDeformWeight *newdw;
485
486         /* do this check always, this function is used to check for it */
487         if(!dv || defgroup<0)
488                 return NULL;
489
490         newdw = defvert_find_index(dv, defgroup);
491         if(newdw)
492                 return newdw;
493
494         newdw = MEM_callocN(sizeof(MDeformWeight)*(dv->totweight+1), "deformWeight");
495         if(dv->dw) {
496                 memcpy(newdw, dv->dw, sizeof(MDeformWeight)*dv->totweight);
497                 MEM_freeN(dv->dw);
498         }
499         dv->dw=newdw;
500
501         dv->dw[dv->totweight].weight=0.0f;
502         dv->dw[dv->totweight].def_nr=defgroup;
503         /* Group index */
504
505         dv->totweight++;
506
507         return dv->dw+(dv->totweight-1);
508 }