Patch #34204: [Render Animation] Fails with "Error: Specified sample_fmt is not suppo...
[blender.git] / source / blender / blenkernel / intern / deform.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Reevan McKay
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/deform.c
29  *  \ingroup bke
30  */
31
32
33 #include <string.h>
34 #include <math.h>
35 #include <ctype.h>
36 #include <stdlib.h>
37 #include <stddef.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "DNA_meshdata_types.h"
42 #include "DNA_object_types.h"
43
44 #include "BLI_listbase.h"
45 #include "BLI_math.h"
46 #include "BLI_path_util.h"
47 #include "BLI_string.h"
48 #include "BLI_utildefines.h"
49
50 #include "BKE_deform.h"  /* own include */
51
52 void defgroup_copy_list(ListBase *outbase, ListBase *inbase)
53 {
54         bDeformGroup *defgroup, *defgroupn;
55
56         outbase->first = outbase->last = NULL;
57
58         for (defgroup = inbase->first; defgroup; defgroup = defgroup->next) {
59                 defgroupn = defgroup_duplicate(defgroup);
60                 BLI_addtail(outbase, defgroupn);
61         }
62 }
63
64 bDeformGroup *defgroup_duplicate(bDeformGroup *ingroup)
65 {
66         bDeformGroup *outgroup;
67
68         if (!ingroup)
69                 return NULL;
70
71         outgroup = MEM_callocN(sizeof(bDeformGroup), "copy deformGroup");
72
73         /* For now, just copy everything over. */
74         memcpy(outgroup, ingroup, sizeof(bDeformGroup));
75
76         outgroup->next = outgroup->prev = NULL;
77
78         return outgroup;
79 }
80
81 /* copy & overwrite weights */
82 void defvert_copy(MDeformVert *dvert_dst, const MDeformVert *dvert_src)
83 {
84         if (dvert_dst->totweight == dvert_src->totweight) {
85                 if (dvert_src->totweight)
86                         memcpy(dvert_dst->dw, dvert_src->dw, dvert_src->totweight * sizeof(MDeformWeight));
87         }
88         else {
89                 if (dvert_dst->dw)
90                         MEM_freeN(dvert_dst->dw);
91
92                 if (dvert_src->totweight)
93                         dvert_dst->dw = MEM_dupallocN(dvert_src->dw);
94                 else
95                         dvert_dst->dw = NULL;
96
97                 dvert_dst->totweight = dvert_src->totweight;
98         }
99 }
100
101 /* copy an index from one dvert to another
102  * - do nothing if neither are set.
103  * - add destination weight if needed.
104  */
105 void defvert_copy_index(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const int defgroup)
106 {
107         MDeformWeight *dw_src, *dw_dst;
108
109         dw_src = defvert_find_index(dvert_src, defgroup);
110
111         if (dw_src) {
112                 /* source is valid, verify destination */
113                 dw_dst = defvert_verify_index(dvert_dst, defgroup);
114                 dw_dst->weight = dw_src->weight;
115         }
116         else {
117                 /* source was NULL, assign zero, could also remove */
118                 dw_dst = defvert_find_index(dvert_dst, defgroup);
119
120                 if (dw_dst) {
121                         dw_dst->weight = 0.0f;
122                 }
123         }
124 }
125
126 /* only sync over matching weights, don't add or remove groups
127  * warning, loop within loop.
128  */
129 void defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, int use_verify)
130 {
131         if (dvert_src->totweight && dvert_dst->totweight) {
132                 int i;
133                 MDeformWeight *dw_src;
134                 for (i = 0, dw_src = dvert_src->dw; i < dvert_src->totweight; i++, dw_src++) {
135                         MDeformWeight *dw_dst;
136                         if (use_verify) dw_dst = defvert_verify_index(dvert_dst, dw_src->def_nr);
137                         else            dw_dst = defvert_find_index(dvert_dst, dw_src->def_nr);
138
139                         if (dw_dst) {
140                                 dw_dst->weight = dw_src->weight;
141                         }
142                 }
143         }
144 }
145
146 /* be sure all flip_map values are valid */
147 void defvert_sync_mapped(MDeformVert *dvert_dst, const MDeformVert *dvert_src,
148                          const int *flip_map, const int flip_map_len, const int use_verify)
149 {
150         if (dvert_src->totweight && dvert_dst->totweight) {
151                 int i;
152                 MDeformWeight *dw_src;
153                 for (i = 0, dw_src = dvert_src->dw; i < dvert_src->totweight; i++, dw_src++) {
154                         if (dw_src->def_nr < flip_map_len) {
155                                 MDeformWeight *dw_dst;
156                                 if (use_verify) dw_dst = defvert_verify_index(dvert_dst, flip_map[dw_src->def_nr]);
157                                 else            dw_dst = defvert_find_index(dvert_dst, flip_map[dw_src->def_nr]);
158
159                                 if (dw_dst) {
160                                         dw_dst->weight = dw_src->weight;
161                                 }
162                         }
163                 }
164         }
165 }
166
167 /* be sure all flip_map values are valid */
168 void defvert_remap(MDeformVert *dvert, int *map, const int map_len)
169 {
170         MDeformWeight *dw = dvert->dw;
171         unsigned int i;
172         for (i = dvert->totweight; i != 0; i--, dw++) {
173                 if (dw->def_nr < map_len) {
174                         dw->def_nr = map[dw->def_nr];
175
176                         /* just in case */
177                         BLI_assert(dw->def_nr >= 0);
178                 }
179         }
180 }
181
182 void defvert_normalize(MDeformVert *dvert)
183 {
184         if (dvert->totweight <= 0) {
185                 /* nothing */
186         }
187         else if (dvert->totweight == 1) {
188                 dvert->dw[0].weight = 1.0f;
189         }
190         else {
191                 MDeformWeight *dw;
192                 unsigned int i;
193                 float tot_weight = 0.0f;
194
195                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
196                         tot_weight += dw->weight;
197                 }
198
199                 if (tot_weight > 0.0f) {
200                         float scalar = 1.0f / tot_weight;
201                         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
202                                 dw->weight *= scalar;
203
204                                 /* in case of division errors with very low weights */
205                                 CLAMP(dw->weight, 0.0f, 1.0f);
206                         }
207                 }
208         }
209 }
210
211 void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock)
212 {
213         if (dvert->totweight <= 0) {
214                 /* nothing */
215         }
216         else if (dvert->totweight == 1) {
217                 if (def_nr_lock != 0) {
218                         dvert->dw[0].weight = 1.0f;
219                 }
220         }
221         else {
222                 MDeformWeight *dw_lock = NULL;
223                 MDeformWeight *dw;
224                 unsigned int i;
225                 float tot_weight = 0.0f;
226                 float lock_iweight = 1.0f;
227
228                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
229                         if (dw->def_nr != def_nr_lock) {
230                                 tot_weight += dw->weight;
231                         }
232                         else {
233                                 dw_lock = dw;
234                                 lock_iweight = (1.0f - dw_lock->weight);
235                                 CLAMP(lock_iweight, 0.0f, 1.0f);
236                         }
237                 }
238
239                 if (tot_weight > 0.0f) {
240                         /* paranoid, should be 1.0 but in case of float error clamp anyway */
241
242                         float scalar = (1.0f / tot_weight) * lock_iweight;
243                         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
244                                 if (dw != dw_lock) {
245                                         dw->weight *= scalar;
246
247                                         /* in case of division errors with very low weights */
248                                         CLAMP(dw->weight, 0.0f, 1.0f);
249                                 }
250                         }
251                 }
252         }
253 }
254
255 void defvert_normalize_lock_map(MDeformVert *dvert, const char *lock_flags, const int defbase_tot)
256 {
257         if (dvert->totweight <= 0) {
258                 /* nothing */
259         }
260         else if (dvert->totweight == 1) {
261                 if (LIKELY(defbase_tot >= 1) && lock_flags[0]) {
262                         dvert->dw[0].weight = 1.0f;
263                 }
264         }
265         else {
266                 MDeformWeight *dw;
267                 unsigned int i;
268                 float tot_weight = 0.0f;
269                 float lock_iweight = 0.0f;
270
271                 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
272                         if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) {
273                                 tot_weight += dw->weight;
274                         }
275                         else {
276                                 /* invert after */
277                                 lock_iweight += dw->weight;
278                         }
279                 }
280
281                 lock_iweight = max_ff(0.0f, 1.0f - lock_iweight);
282
283                 if (tot_weight > 0.0f) {
284                         /* paranoid, should be 1.0 but in case of float error clamp anyway */
285
286                         float scalar = (1.0f / tot_weight) * lock_iweight;
287                         for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
288                                 if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) {
289                                         dw->weight *= scalar;
290
291                                         /* in case of division errors with very low weights */
292                                         CLAMP(dw->weight, 0.0f, 1.0f);
293                                 }
294                         }
295                 }
296         }
297 }
298
299 void defvert_flip(MDeformVert *dvert, const int *flip_map, const int flip_map_len)
300 {
301         MDeformWeight *dw;
302         int i;
303
304         for (dw = dvert->dw, i = 0; i < dvert->totweight; dw++, i++) {
305                 if (dw->def_nr < flip_map_len) {
306                         if (flip_map[dw->def_nr] >= 0) {
307                                 dw->def_nr = flip_map[dw->def_nr];
308                         }
309                 }
310         }
311 }
312
313 void defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int flip_map_len)
314 {
315         MDeformWeight *dw, *dw_cpy;
316         float weight;
317         int i, totweight = dvert->totweight;
318
319         /* copy weights */
320         for (dw = dvert->dw, i = 0; i < totweight; dw++, i++) {
321                 if (dw->def_nr < flip_map_len) {
322                         if (flip_map[dw->def_nr] >= 0) {
323                                 /* error checkers complain of this but we'll never get NULL return */
324                                 dw_cpy = defvert_verify_index(dvert, flip_map[dw->def_nr]);
325                                 dw = &dvert->dw[i]; /* in case array got realloced */
326
327                                 /* distribute weights: if only one of the vertex groups was
328                                  * assigned this will halve the weights, otherwise it gets
329                                  * evened out. this keeps it proportional to other groups */
330                                 weight = 0.5f * (dw_cpy->weight + dw->weight);
331                                 dw_cpy->weight = weight;
332                                 dw->weight = weight;
333                         }
334                 }
335         }
336 }
337
338 bDeformGroup *defgroup_find_name(Object *ob, const char *name)
339 {
340         return BLI_findstring(&ob->defbase, name, offsetof(bDeformGroup, name));
341 }
342
343 int defgroup_name_index(Object *ob, const char *name)
344 {
345         return (name) ? BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name)) : -1;
346 }
347
348 /* note, must be freed */
349 int *defgroup_flip_map(Object *ob, int *flip_map_len, int use_default)
350 {
351         int defbase_tot = *flip_map_len = BLI_countlist(&ob->defbase);
352
353         if (defbase_tot == 0) {
354                 return NULL;
355         }
356         else {
357                 bDeformGroup *dg;
358                 char name[sizeof(dg->name)];
359                 int i, flip_num, *map = MEM_mallocN(defbase_tot * sizeof(int), __func__);
360
361                 for (i = 0; i < defbase_tot; i++) {
362                         map[i] = -1;
363                 }
364
365                 for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) {
366                         if (map[i] == -1) { /* may be calculated previously */
367
368                                 /* in case no valid value is found, use this */
369                                 if (use_default)
370                                         map[i] = i;
371
372                                 flip_side_name(name, dg->name, FALSE);
373                                 if (strcmp(name, dg->name)) {
374                                         flip_num = defgroup_name_index(ob, name);
375                                         if (flip_num >= 0) {
376                                                 map[i] = flip_num;
377                                                 map[flip_num] = i; /* save an extra lookup */
378                                         }
379                                 }
380                         }
381                 }
382                 return map;
383         }
384 }
385
386 /* note, must be freed */
387 int *defgroup_flip_map_single(Object *ob, int *flip_map_len, int use_default, int defgroup)
388 {
389         int defbase_tot = *flip_map_len = BLI_countlist(&ob->defbase);
390
391         if (defbase_tot == 0) {
392                 return NULL;
393         }
394         else {
395                 bDeformGroup *dg;
396                 char name[sizeof(dg->name)];
397                 int i, flip_num, *map = MEM_mallocN(defbase_tot * sizeof(int), __func__);
398
399                 for (i = 0; i < defbase_tot; i++) {
400                         map[i] = use_default ? i : -1;
401                 }
402
403                 dg = BLI_findlink(&ob->defbase, defgroup);
404
405                 flip_side_name(name, dg->name, FALSE);
406                 if (strcmp(name, dg->name)) {
407                         flip_num = defgroup_name_index(ob, name);
408
409                         if (flip_num != -1) {
410                                 map[defgroup] = flip_num;
411                                 map[flip_num] = defgroup;
412                         }
413                 }
414
415                 return map;
416         }
417 }
418
419 int defgroup_flip_index(Object *ob, int index, int use_default)
420 {
421         bDeformGroup *dg = BLI_findlink(&ob->defbase, index);
422         int flip_index = -1;
423
424         if (dg) {
425                 char name[sizeof(dg->name)];
426                 flip_side_name(name, dg->name, 0);
427
428                 if (strcmp(name, dg->name))
429                         flip_index = defgroup_name_index(ob, name);
430         }
431
432         return (flip_index == -1 && use_default) ? index : flip_index;
433 }
434
435 static bool defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob)
436 {
437         bDeformGroup *curdef;
438
439         for (curdef = ob->defbase.first; curdef; curdef = curdef->next) {
440                 if (dg != curdef) {
441                         if (!strcmp(curdef->name, name)) {
442                                 return true;
443                         }
444                 }
445         }
446
447         return false;
448 }
449
450 static bool defgroup_unique_check(void *arg, const char *name)
451 {
452         struct {Object *ob; void *dg; } *data = arg;
453         return defgroup_find_name_dupe(name, data->dg, data->ob);
454 }
455
456 void defgroup_unique_name(bDeformGroup *dg, Object *ob)
457 {
458         struct {Object *ob; void *dg; } data;
459         data.ob = ob;
460         data.dg = dg;
461
462         BLI_uniquename_cb(defgroup_unique_check, &data, "Group", '.', dg->name, sizeof(dg->name));
463 }
464
465 static int is_char_sep(const char c)
466 {
467         return ELEM4(c, '.', ' ', '-', '_');
468 }
469
470 /* based on BLI_split_dirfile() / os.path.splitext(), "a.b.c" -> ("a.b", ".c") */
471
472 void BKE_deform_split_suffix(const char string[MAX_VGROUP_NAME], char body[MAX_VGROUP_NAME], char suf[MAX_VGROUP_NAME])
473 {
474         size_t len = BLI_strnlen(string, MAX_VGROUP_NAME);
475         size_t i;
476
477         body[0] = suf[0] = '\0';
478
479         for (i = len - 1; i > 1; i--) {
480                 if (is_char_sep(string[i])) {
481                         BLI_strncpy(body, string, i + 1);
482                         BLI_strncpy(suf, string + i,  (len + 1) - i);
483                         return;
484                 }
485         }
486
487         BLI_strncpy(body, string, len);
488 }
489
490 /* "a.b.c" -> ("a.", "b.c") */
491 void BKE_deform_split_prefix(const char string[MAX_VGROUP_NAME], char pre[MAX_VGROUP_NAME], char body[MAX_VGROUP_NAME])
492 {
493         size_t len = BLI_strnlen(string, MAX_VGROUP_NAME);
494         size_t i;
495
496         body[0] = pre[0] = '\0';
497
498         for (i = 1; i < len; i++) {
499                 if (is_char_sep(string[i])) {
500                         i++;
501                         BLI_strncpy(pre, string, i + 1);
502                         BLI_strncpy(body, string + i, (len + 1) - i);
503                         return;
504                 }
505         }
506
507         BLI_strncpy(body, string, len);
508 }
509
510 /* finds the best possible flipped name. For renaming; check for unique names afterwards */
511 /* if strip_number: removes number extensions
512  * note: don't use sizeof() for 'name' or 'from_name' */
513 void flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME], int strip_number)
514 {
515         int     len;
516         char    prefix[MAX_VGROUP_NAME]  = "";   /* The part before the facing */
517         char    suffix[MAX_VGROUP_NAME]  = "";   /* The part after the facing */
518         char    replace[MAX_VGROUP_NAME] = "";   /* The replacement string */
519         char    number[MAX_VGROUP_NAME]  = "";   /* The number extension string */
520         char    *index = NULL;
521
522         /* always copy the name, since this can be called with an uninitialized string */
523         BLI_strncpy(name, from_name, MAX_VGROUP_NAME);
524
525         len = BLI_strnlen(from_name, MAX_VGROUP_NAME);
526         if (len < 3) {
527                 /* we don't do names like .R or .L */
528                 return;
529         }
530
531         /* We first check the case with a .### extension, let's find the last period */
532         if (isdigit(name[len - 1])) {
533                 index = strrchr(name, '.'); // last occurrence
534                 if (index && isdigit(index[1])) { // doesnt handle case bone.1abc2 correct..., whatever!
535                         if (strip_number == 0) {
536                                 BLI_strncpy(number, index, sizeof(number));
537                         }
538                         *index = 0;
539                         len = BLI_strnlen(name, MAX_VGROUP_NAME);
540                 }
541         }
542
543         BLI_strncpy(prefix, name, sizeof(prefix));
544
545         /* first case; separator . - _ with extensions r R l L  */
546         if (is_char_sep(name[len - 2])) {
547                 switch (name[len - 1]) {
548                         case 'l':
549                                 prefix[len - 1] = 0;
550                                 strcpy(replace, "r");
551                                 break;
552                         case 'r':
553                                 prefix[len - 1] = 0;
554                                 strcpy(replace, "l");
555                                 break;
556                         case 'L':
557                                 prefix[len - 1] = 0;
558                                 strcpy(replace, "R");
559                                 break;
560                         case 'R':
561                                 prefix[len - 1] = 0;
562                                 strcpy(replace, "L");
563                                 break;
564                 }
565         }
566         /* case; beginning with r R l L, with separator after it */
567         else if (is_char_sep(name[1])) {
568                 switch (name[0]) {
569                         case 'l':
570                                 strcpy(replace, "r");
571                                 BLI_strncpy(suffix, name + 1, sizeof(suffix));
572                                 prefix[0] = 0;
573                                 break;
574                         case 'r':
575                                 strcpy(replace, "l");
576                                 BLI_strncpy(suffix, name + 1, sizeof(suffix));
577                                 prefix[0] = 0;
578                                 break;
579                         case 'L':
580                                 strcpy(replace, "R");
581                                 BLI_strncpy(suffix, name + 1, sizeof(suffix));
582                                 prefix[0] = 0;
583                                 break;
584                         case 'R':
585                                 strcpy(replace, "L");
586                                 BLI_strncpy(suffix, name + 1, sizeof(suffix));
587                                 prefix[0] = 0;
588                                 break;
589                 }
590         }
591         else if (len > 5) {
592                 /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
593                 index = BLI_strcasestr(prefix, "right");
594                 if (index == prefix || index == prefix + len - 5) {
595                         if (index[0] == 'r')
596                                 strcpy(replace, "left");
597                         else {
598                                 if (index[1] == 'I')
599                                         strcpy(replace, "LEFT");
600                                 else
601                                         strcpy(replace, "Left");
602                         }
603                         *index = 0;
604                         BLI_strncpy(suffix, index + 5, sizeof(suffix));
605                 }
606                 else {
607                         index = BLI_strcasestr(prefix, "left");
608                         if (index == prefix || index == prefix + len - 4) {
609                                 if (index[0] == 'l')
610                                         strcpy(replace, "right");
611                                 else {
612                                         if (index[1] == 'E')
613                                                 strcpy(replace, "RIGHT");
614                                         else
615                                                 strcpy(replace, "Right");
616                                 }
617                                 *index = 0;
618                                 BLI_strncpy(suffix, index + 4, sizeof(suffix));
619                         }
620                 }
621         }
622
623         BLI_snprintf(name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
624 }
625
626 float defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
627 {
628         MDeformWeight *dw = defvert_find_index(dvert, defgroup);
629         return dw ? dw->weight : 0.0f;
630 }
631
632 /* take care with this the rationale is:
633  * - if the object has no vertex group. act like vertex group isn't set and return 1.0,
634  * - if the vertex group exists but the 'defgroup' isn't found on this vertex, _still_ return 0.0
635  *
636  * This is a bit confusing, just saves some checks from the caller.
637  */
638 float defvert_array_find_weight_safe(const struct MDeformVert *dvert, const int index, const int defgroup)
639 {
640         if (defgroup == -1 || dvert == NULL)
641                 return 1.0f;
642
643         return defvert_find_weight(dvert + index, defgroup);
644 }
645
646
647 MDeformWeight *defvert_find_index(const MDeformVert *dvert, const int defgroup)
648 {
649         if (dvert && defgroup >= 0) {
650                 MDeformWeight *dw = dvert->dw;
651                 unsigned int i;
652
653                 for (i = dvert->totweight; i != 0; i--, dw++) {
654                         if (dw->def_nr == defgroup) {
655                                 return dw;
656                         }
657                 }
658         }
659
660         return NULL;
661 }
662
663 /* Ensures that mv has a deform weight entry for the specified defweight group */
664 /* Note this function is mirrored in editmesh_tools.c, for use for editvertices */
665 MDeformWeight *defvert_verify_index(MDeformVert *dvert, const int defgroup)
666 {
667         MDeformWeight *dw_new;
668
669         /* do this check always, this function is used to check for it */
670         if (!dvert || defgroup < 0)
671                 return NULL;
672
673         dw_new = defvert_find_index(dvert, defgroup);
674         if (dw_new)
675                 return dw_new;
676
677         dw_new = MEM_callocN(sizeof(MDeformWeight) * (dvert->totweight + 1), "deformWeight");
678         if (dvert->dw) {
679                 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
680                 MEM_freeN(dvert->dw);
681         }
682         dvert->dw = dw_new;
683         dw_new += dvert->totweight;
684         dw_new->weight = 0.0f;
685         dw_new->def_nr = defgroup;
686         /* Group index */
687
688         dvert->totweight++;
689
690         return dw_new;
691 }
692
693 /* TODO. merge with code above! */
694
695 /* Adds the given vertex to the specified vertex group, with given weight.
696  * warning, this does NOT check for existing, assume caller already knows its not there */
697 void defvert_add_index_notest(MDeformVert *dvert, int defgroup, const float weight)
698 {
699         MDeformWeight *dw_new;
700
701         /* do this check always, this function is used to check for it */
702         if (!dvert || defgroup < 0)
703                 return;
704
705         dw_new = MEM_callocN(sizeof(MDeformWeight) * (dvert->totweight + 1), "defvert_add_to group, new deformWeight");
706         if (dvert->dw) {
707                 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
708                 MEM_freeN(dvert->dw);
709         }
710         dvert->dw = dw_new;
711         dw_new += dvert->totweight;
712         dw_new->weight = weight;
713         dw_new->def_nr = defgroup;
714         dvert->totweight++;
715 }
716
717
718 /* Removes the given vertex from the vertex group.
719  * WARNING: This function frees the given MDeformWeight, do not use it afterward! */
720 void defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
721 {
722         if (dvert && dw) {
723                 MDeformWeight *dw_new;
724                 int i = dw - dvert->dw;
725
726                 /* Security check! */
727                 if (i < 0 || i >= dvert->totweight) {
728                         return;
729                 }
730
731                 dvert->totweight--;
732                 /* If there are still other deform weights attached to this vert then remove
733                  * this deform weight, and reshuffle the others.
734                  */
735                 if (dvert->totweight) {
736                         dw_new = MEM_mallocN(sizeof(MDeformWeight) * (dvert->totweight), __func__);
737                         if (dvert->dw) {
738 #if 1           /* since we don't care about order, swap this with the last, save a memcpy */
739                                 if (i != dvert->totweight) {
740                                         dvert->dw[i] = dvert->dw[dvert->totweight];
741                                 }
742                                 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
743 #else
744                                 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * i);
745                                 memcpy(dw_new + i, dvert->dw + i + 1, sizeof(MDeformWeight) * (dvert->totweight - i));
746 #endif
747                                 MEM_freeN(dvert->dw);
748                         }
749                         dvert->dw = dw_new;
750                 }
751                 else {
752                         /* If there are no other deform weights left then just remove this one. */
753                         MEM_freeN(dvert->dw);
754                         dvert->dw = NULL;
755                 }
756         }
757 }
758
759 void defvert_clear(MDeformVert *dvert)
760 {
761         if (dvert->dw) {
762                 MEM_freeN(dvert->dw);
763                 dvert->dw = NULL;
764         }
765
766         dvert->totweight = 0;
767 }
768
769 /**
770  * \return The first group index shared by both deform verts
771  * or -1 if none are found.
772  */
773 int defvert_find_shared(const MDeformVert *dvert_a, const MDeformVert *dvert_b)
774 {
775         if (dvert_a->totweight && dvert_b->totweight) {
776                 MDeformWeight *dw = dvert_a->dw;
777                 unsigned int i;
778
779                 for (i = dvert_a->totweight; i != 0; i--, dw++) {
780                         if (dw->weight > 0.0f && defvert_find_weight(dvert_b, dw->def_nr) > 0.0f) {
781                                 return dw->def_nr;
782                         }
783                 }
784         }
785
786         return -1;
787 }
788
789 /**
790  * return true if has no weights
791  */
792 bool defvert_is_weight_zero(const struct MDeformVert *dvert, const int defgroup_tot)
793 {
794         MDeformWeight *dw = dvert->dw;
795         unsigned int i;
796         for (i = dvert->totweight; i != 0; i--, dw++) {
797                 if (dw->weight != 0.0f) {
798                         /* check the group is in-range, happens on rare situations */
799                         if (LIKELY(dw->def_nr < defgroup_tot)) {
800                                 return false;
801                         }
802                 }
803         }
804         return true;
805 }
806
807 /* -------------------------------------------------------------------- */
808 /* Defvert Array functions */
809
810 void BKE_defvert_array_copy(MDeformVert *dst, const MDeformVert *src, int copycount)
811 {
812         /* Assumes dst is already set up */
813         int i;
814
815         if (!src || !dst)
816                 return;
817
818         memcpy(dst, src, copycount * sizeof(MDeformVert));
819
820         for (i = 0; i < copycount; i++) {
821                 if (src[i].dw) {
822                         dst[i].dw = MEM_mallocN(sizeof(MDeformWeight) * src[i].totweight, "copy_deformWeight");
823                         memcpy(dst[i].dw, src[i].dw, sizeof(MDeformWeight) * src[i].totweight);
824                 }
825         }
826
827 }
828
829 void BKE_defvert_array_free_elems(MDeformVert *dvert, int totvert)
830 {
831         /* Instead of freeing the verts directly,
832          * call this function to delete any special
833          * vert data */
834         int i;
835
836         if (!dvert)
837                 return;
838
839         /* Free any special data from the verts */
840         for (i = 0; i < totvert; i++) {
841                 if (dvert[i].dw) MEM_freeN(dvert[i].dw);
842         }
843 }
844
845 void BKE_defvert_array_free(MDeformVert *dvert, int totvert)
846 {
847         /* Instead of freeing the verts directly,
848          * call this function to delete any special
849          * vert data */
850         if (!dvert)
851                 return;
852
853         /* Free any special data from the verts */
854         BKE_defvert_array_free_elems(dvert, totvert);
855
856         MEM_freeN(dvert);
857 }