Blender V4.3
deform.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cctype>
10#include <cmath>
11#include <cstddef>
12#include <cstdlib>
13#include <cstring>
14
15#include "MEM_guardedalloc.h"
16
19#include "DNA_lattice_types.h"
20#include "DNA_mesh_types.h"
21#include "DNA_meshdata_types.h"
22#include "DNA_object_types.h"
23#include "DNA_scene_types.h"
24
25#include "BLI_listbase.h"
26#include "BLI_math_vector.h"
27#include "BLI_string.h"
28#include "BLI_string_utf8.h"
29#include "BLI_string_utils.hh"
30#include "BLI_utildefines.h"
31
32#include "BLT_translation.hh"
33
34#include "BKE_attribute.hh"
35#include "BKE_customdata.hh"
36#include "BKE_data_transfer.h"
37#include "BKE_deform.hh" /* own include */
38#include "BKE_grease_pencil.hh"
40#include "BKE_mesh.hh"
41#include "BKE_mesh_mapping.hh"
42#include "BKE_object.hh"
43#include "BKE_object_deform.h"
44
45#include "BLO_read_write.hh"
46
48
50
52{
53 bDeformGroup *defgroup;
54
56
57 defgroup = MEM_cnew<bDeformGroup>(__func__);
58
59 name.copy(defgroup->name);
60
62
63 BLI_addtail(defbase, defgroup);
65
66 if (ob->type == OB_GREASE_PENCIL) {
68 *static_cast<GreasePencil *>(ob->data));
69 }
70
72
73 return defgroup;
74}
75
76void BKE_defgroup_copy_list(ListBase *outbase, const ListBase *inbase)
77{
78 BLI_listbase_clear(outbase);
79 LISTBASE_FOREACH (const bDeformGroup *, defgroup, inbase) {
80 bDeformGroup *defgroupn = BKE_defgroup_duplicate(defgroup);
81 BLI_addtail(outbase, defgroupn);
82 }
83}
84
86{
87 if (!ingroup) {
88 BLI_assert(0);
89 return nullptr;
90 }
91
92 bDeformGroup *outgroup = MEM_cnew<bDeformGroup>(__func__);
93
94 /* For now, just copy everything over. */
95 memcpy(outgroup, ingroup, sizeof(bDeformGroup));
96
97 outgroup->next = outgroup->prev = nullptr;
98
99 return outgroup;
100}
101
103 const MDeformVert *dvert_src,
104 const bool *vgroup_subset,
105 const int vgroup_num)
106{
107 int defgroup;
108 for (defgroup = 0; defgroup < vgroup_num; defgroup++) {
109 if (vgroup_subset[defgroup]) {
110 BKE_defvert_copy_index(dvert_dst, defgroup, dvert_src, defgroup);
111 }
112 }
113}
114
116 const MDeformVert *dvert_src,
117 const bool *vgroup_subset,
118 const int vgroup_num,
119 const int *flip_map,
120 const int flip_map_num)
121{
122 int defgroup;
123 for (defgroup = 0; defgroup < vgroup_num && defgroup < flip_map_num; defgroup++) {
124 if (vgroup_subset[defgroup] && (dvert_dst != dvert_src || flip_map[defgroup] != defgroup)) {
125 BKE_defvert_copy_index(dvert_dst, flip_map[defgroup], dvert_src, defgroup);
126 }
127 }
128}
129
130void BKE_defvert_copy(MDeformVert *dvert_dst, const MDeformVert *dvert_src)
131{
132 if (dvert_dst->totweight == dvert_src->totweight) {
133 if (dvert_src->totweight) {
134 memcpy(dvert_dst->dw, dvert_src->dw, dvert_src->totweight * sizeof(MDeformWeight));
135 }
136 }
137 else {
138 if (dvert_dst->dw) {
139 MEM_freeN(dvert_dst->dw);
140 }
141
142 if (dvert_src->totweight) {
143 dvert_dst->dw = static_cast<MDeformWeight *>(MEM_dupallocN(dvert_src->dw));
144 }
145 else {
146 dvert_dst->dw = nullptr;
147 }
148
149 dvert_dst->totweight = dvert_src->totweight;
150 }
151}
152
154 const int defgroup_dst,
155 const MDeformVert *dvert_src,
156 const int defgroup_src)
157{
158 MDeformWeight *dw_dst;
159
160 const MDeformWeight *dw_src = BKE_defvert_find_index(dvert_src, defgroup_src);
161
162 if (dw_src) {
163 /* Source is valid, ensure destination is created. */
164 dw_dst = BKE_defvert_ensure_index(dvert_dst, defgroup_dst);
165 dw_dst->weight = dw_src->weight;
166 }
167 else {
168 /* Source was nullptr, assign zero (could also remove). */
169 dw_dst = BKE_defvert_find_index(dvert_dst, defgroup_dst);
170
171 if (dw_dst) {
172 dw_dst->weight = 0.0f;
173 }
174 }
175}
176
177void BKE_defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const bool use_ensure)
178{
179 if (dvert_src->totweight && dvert_dst->totweight) {
180 MDeformWeight *dw_src = dvert_src->dw;
181 for (int i = 0; i < dvert_src->totweight; i++, dw_src++) {
182 MDeformWeight *dw_dst;
183 if (use_ensure) {
184 dw_dst = BKE_defvert_ensure_index(dvert_dst, dw_src->def_nr);
185 }
186 else {
187 dw_dst = BKE_defvert_find_index(dvert_dst, dw_src->def_nr);
188 }
189
190 if (dw_dst) {
191 dw_dst->weight = dw_src->weight;
192 }
193 }
194 }
195}
196
198 const MDeformVert *dvert_src,
199 const int *flip_map,
200 const int flip_map_num,
201 const bool use_ensure)
202{
203 if (dvert_src->totweight && dvert_dst->totweight) {
204 MDeformWeight *dw_src = dvert_src->dw;
205 for (int i = 0; i < dvert_src->totweight; i++, dw_src++) {
206 if (dw_src->def_nr < flip_map_num) {
207 MDeformWeight *dw_dst;
208 if (use_ensure) {
209 dw_dst = BKE_defvert_ensure_index(dvert_dst, flip_map[dw_src->def_nr]);
210 }
211 else {
212 dw_dst = BKE_defvert_find_index(dvert_dst, flip_map[dw_src->def_nr]);
213 }
214
215 if (dw_dst) {
216 dw_dst->weight = dw_src->weight;
217 }
218 }
219 }
220 }
221}
222
223void BKE_defvert_remap(MDeformVert *dvert, const int *map, const int map_len)
224{
225 MDeformWeight *dw = dvert->dw;
226 for (int i = dvert->totweight; i != 0; i--, dw++) {
227 if (dw->def_nr < map_len) {
228 BLI_assert(map[dw->def_nr] >= 0);
229
230 dw->def_nr = map[dw->def_nr];
231 }
232 }
233}
234
236 const bool *vgroup_subset,
237 const int vgroup_num)
238{
239 if (dvert->totweight == 0) {
240 /* nothing */
241 }
242 else if (dvert->totweight == 1) {
243 MDeformWeight *dw = dvert->dw;
244 if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) {
245 dw->weight = 1.0f;
246 }
247 }
248 else {
249 MDeformWeight *dw = dvert->dw;
250 float tot_weight = 0.0f;
251 for (int i = dvert->totweight; i != 0; i--, dw++) {
252 if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) {
253 tot_weight += dw->weight;
254 }
255 }
256
257 if (tot_weight > 0.0f) {
258 float scalar = 1.0f / tot_weight;
259 dw = dvert->dw;
260 for (int i = dvert->totweight; i != 0; i--, dw++) {
261 if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) {
262 dw->weight *= scalar;
263
264 /* in case of division errors with very low weights */
265 CLAMP(dw->weight, 0.0f, 1.0f);
266 }
267 }
268 }
269 }
270}
271
273{
274 if (dvert->totweight == 0) {
275 /* nothing */
276 }
277 else if (dvert->totweight == 1) {
278 dvert->dw[0].weight = 1.0f;
279 }
280 else {
281 MDeformWeight *dw;
282 uint i;
283 float tot_weight = 0.0f;
284
285 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
286 tot_weight += dw->weight;
287 }
288
289 if (tot_weight > 0.0f) {
290 float scalar = 1.0f / tot_weight;
291 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
292 dw->weight *= scalar;
293
294 /* in case of division errors with very low weights */
295 CLAMP(dw->weight, 0.0f, 1.0f);
296 }
297 }
298 }
299}
300
302 const bool *vgroup_subset,
303 const int vgroup_num,
304 const uint def_nr_lock)
305{
306 if (dvert->totweight == 0) {
307 /* nothing */
308 }
309 else if (dvert->totweight == 1) {
310 MDeformWeight *dw = dvert->dw;
311 if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) {
312 if (def_nr_lock != dw->def_nr) {
313 dw->weight = 1.0f;
314 }
315 }
316 }
317 else {
318 MDeformWeight *dw_lock = nullptr;
319 MDeformWeight *dw;
320 uint i;
321 float tot_weight = 0.0f;
322 float lock_iweight = 1.0f;
323
324 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
325 if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) {
326 if (dw->def_nr != def_nr_lock) {
327 tot_weight += dw->weight;
328 }
329 else {
330 dw_lock = dw;
331 lock_iweight = (1.0f - dw_lock->weight);
332 CLAMP(lock_iweight, 0.0f, 1.0f);
333 }
334 }
335 }
336
337 if (tot_weight > 0.0f) {
338 /* paranoid, should be 1.0 but in case of float error clamp anyway */
339
340 float scalar = (1.0f / tot_weight) * lock_iweight;
341 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
342 if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) {
343 if (dw != dw_lock) {
344 dw->weight *= scalar;
345
346 /* in case of division errors with very low weights */
347 CLAMP(dw->weight, 0.0f, 1.0f);
348 }
349 }
350 }
351 }
352 }
353}
354
356 const bool *vgroup_subset,
357 const int vgroup_num,
358 const bool *lock_flags,
359 const int defbase_num)
360{
361 if (dvert->totweight == 0) {
362 /* nothing */
363 }
364 else if (dvert->totweight == 1) {
365 MDeformWeight *dw = dvert->dw;
366 if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) {
367 if ((dw->def_nr < defbase_num) && (lock_flags[dw->def_nr] == false)) {
368 dw->weight = 1.0f;
369 }
370 }
371 }
372 else {
373 MDeformWeight *dw;
374 uint i;
375 float tot_weight = 0.0f;
376 float lock_iweight = 0.0f;
377
378 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
379 if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) {
380 if ((dw->def_nr < defbase_num) && (lock_flags[dw->def_nr] == false)) {
381 tot_weight += dw->weight;
382 }
383 else {
384 /* invert after */
385 lock_iweight += dw->weight;
386 }
387 }
388 }
389
390 lock_iweight = max_ff(0.0f, 1.0f - lock_iweight);
391
392 if (tot_weight > 0.0f) {
393 /* paranoid, should be 1.0 but in case of float error clamp anyway */
394
395 float scalar = (1.0f / tot_weight) * lock_iweight;
396 for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
397 if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) {
398 if ((dw->def_nr < defbase_num) && (lock_flags[dw->def_nr] == false)) {
399 dw->weight *= scalar;
400
401 /* in case of division errors with very low weights */
402 CLAMP(dw->weight, 0.0f, 1.0f);
403 }
404 }
405 }
406 }
407 }
408}
409
410void BKE_defvert_flip(MDeformVert *dvert, const int *flip_map, const int flip_map_num)
411{
412 MDeformWeight *dw;
413 int i;
414
415 for (dw = dvert->dw, i = 0; i < dvert->totweight; dw++, i++) {
416 if (dw->def_nr < flip_map_num) {
417 if (flip_map[dw->def_nr] >= 0) {
418 dw->def_nr = flip_map[dw->def_nr];
419 }
420 }
421 }
422}
423
424void BKE_defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int flip_map_num)
425{
426 MDeformWeight *dw, *dw_cpy;
427 float weight;
428 int i, totweight = dvert->totweight;
429
430 /* copy weights */
431 for (dw = dvert->dw, i = 0; i < totweight; dw++, i++) {
432 if (dw->def_nr < flip_map_num) {
433 if (flip_map[dw->def_nr] >= 0) {
434 /* error checkers complain of this but we'll never get nullptr return */
435 dw_cpy = BKE_defvert_ensure_index(dvert, flip_map[dw->def_nr]);
436 dw = &dvert->dw[i]; /* in case array got realloced */
437
438 /* distribute weights: if only one of the vertex groups was
439 * assigned this will halve the weights, otherwise it gets
440 * evened out. this keeps it proportional to other groups */
441 weight = 0.5f * (dw_cpy->weight + dw->weight);
442 dw_cpy->weight = weight;
443 dw->weight = weight;
444 }
445 }
446 }
447}
448
450{
451 if (id == nullptr) {
452 return false;
453 }
454 return ELEM(GS(id->name), ID_ME, ID_LT, ID_GD_LEGACY, ID_GP);
455}
456
458{
459 const ID *id = static_cast<const ID *>(ob->data);
460
462}
463
465{
466 switch (GS(id->name)) {
467 case ID_ME: {
468 const Mesh *mesh = (const Mesh *)id;
469 return &mesh->vertex_group_names;
470 }
471 case ID_LT: {
472 const Lattice *lt = (const Lattice *)id;
473 return &lt->vertex_group_names;
474 }
475 case ID_GD_LEGACY: {
476 const bGPdata *gpd = (const bGPdata *)id;
477 return &gpd->vertex_group_names;
478 }
479 case ID_GP: {
480 const GreasePencil *grease_pencil = (const GreasePencil *)id;
481 return &grease_pencil->vertex_group_names;
482 }
483 default: {
485 }
486 }
487 return nullptr;
488}
489
490static const int *object_defgroup_active_index_get_p(const Object *ob)
491{
493 switch (ob->type) {
494 case OB_MESH: {
495 const Mesh *mesh = (const Mesh *)ob->data;
496 return &mesh->vertex_group_active_index;
497 }
498 case OB_LATTICE: {
499 const Lattice *lattice = (const Lattice *)ob->data;
501 }
502 case OB_GPENCIL_LEGACY: {
503 const bGPdata *gpd = (const bGPdata *)ob->data;
504 return &gpd->vertex_group_active_index;
505 }
506 case OB_GREASE_PENCIL: {
507 const GreasePencil *grease_pencil = (const GreasePencil *)ob->data;
508 return &grease_pencil->vertex_group_active_index;
509 }
510 }
511 return nullptr;
512}
513
515{
516 /* Cast away const just for the accessor. */
518}
519
521{
522 if (name.is_empty()) {
523 return nullptr;
524 }
525 const ListBase *defbase = BKE_object_defgroup_list(ob);
526 LISTBASE_FOREACH (bDeformGroup *, group, defbase) {
527 if (name == group->name) {
528 return group;
529 }
530 }
531 return nullptr;
532}
533
534int BKE_defgroup_name_index(const ListBase *defbase, const StringRef name)
535{
536 int index;
537 if (!BKE_defgroup_listbase_name_find(defbase, name, &index, nullptr)) {
538 return -1;
539 }
540 return index;
541}
542
543int BKE_id_defgroup_name_index(const ID *id, const StringRef name)
544{
546}
547
549 const StringRef name,
550 int *r_index,
551 bDeformGroup **r_group)
552{
553 if (name.is_empty()) {
554 return false;
555 }
556 int index;
557 LISTBASE_FOREACH_INDEX (bDeformGroup *, group, defbase, index) {
558 if (name == group->name) {
559 if (r_index != nullptr) {
560 *r_index = index;
561 }
562 if (r_group != nullptr) {
563 *r_group = group;
564 }
565 return true;
566 }
567 }
568 return false;
569}
570
572 const StringRef name,
573 int *r_index,
574 bDeformGroup **r_group)
575{
576 return BKE_defgroup_listbase_name_find(BKE_id_defgroup_list_get(id), name, r_index, r_group);
577}
578
584
586{
587 return BKE_id_defgroup_name_index((ID *)ob->data, name);
588}
589
595
600
605
606void BKE_object_defgroup_active_index_set(Object *ob, const int new_index)
607{
608 /* Cast away const just for the accessor. */
609 int *index = (int *)object_defgroup_active_index_get_p(ob);
610 *index = new_index;
611}
612
614 const bool use_default,
615 const bool use_only_unlocked,
616 int *r_flip_map_num)
617{
618 const ListBase *defbase = BKE_object_defgroup_list(ob);
619 const int defbase_num = BLI_listbase_count(defbase);
620 *r_flip_map_num = defbase_num;
621
622 if (defbase_num == 0) {
623 return nullptr;
624 }
625
626 bDeformGroup *dg;
627 char name_flip[sizeof(dg->name)];
628 int i, flip_num;
629 int *map = static_cast<int *>(MEM_mallocN(defbase_num * sizeof(int), __func__));
630
631 for (i = 0; i < defbase_num; i++) {
632 map[i] = -1;
633 }
634
635 for (dg = static_cast<bDeformGroup *>(defbase->first), i = 0; dg; dg = dg->next, i++) {
636 if (map[i] == -1) { /* may be calculated previously */
637
638 /* in case no valid value is found, use this */
639 if (use_default) {
640 map[i] = i;
641 }
642
643 if (use_only_unlocked && (dg->flag & DG_LOCK_WEIGHT)) {
644 continue;
645 }
646
647 BLI_string_flip_side_name(name_flip, dg->name, false, sizeof(name_flip));
648
649 if (!STREQ(name_flip, dg->name)) {
650 flip_num = BKE_object_defgroup_name_index(ob, name_flip);
651 if (flip_num != -1) {
652 map[i] = flip_num;
653 map[flip_num] = i; /* save an extra lookup */
654 }
655 }
656 }
657 }
658 return map;
659}
660
661int *BKE_object_defgroup_flip_map(const Object *ob, const bool use_default, int *r_flip_map_num)
662{
663 return object_defgroup_unlocked_flip_map_ex(ob, use_default, false, r_flip_map_num);
664}
665
667 const bool use_default,
668 int *r_flip_map_num)
669{
670 return object_defgroup_unlocked_flip_map_ex(ob, use_default, true, r_flip_map_num);
671}
672
674 const bool use_default,
675 const int defgroup,
676 int *r_flip_map_num)
677{
678 const ListBase *defbase = BKE_object_defgroup_list(ob);
679 const int defbase_num = BLI_listbase_count(defbase);
680 *r_flip_map_num = defbase_num;
681
682 if (defbase_num == 0) {
683 return nullptr;
684 }
685
686 char name_flip[sizeof(bDeformGroup::name)];
687 int i, flip_num, *map = static_cast<int *>(MEM_mallocN(defbase_num * sizeof(int), __func__));
688
689 for (i = 0; i < defbase_num; i++) {
690 map[i] = use_default ? i : -1;
691 }
692
693 bDeformGroup *dg = static_cast<bDeformGroup *>(BLI_findlink(defbase, defgroup));
694
695 BLI_string_flip_side_name(name_flip, dg->name, false, sizeof(name_flip));
696 if (!STREQ(name_flip, dg->name)) {
697 flip_num = BKE_object_defgroup_name_index(ob, name_flip);
698
699 if (flip_num != -1) {
700 map[defgroup] = flip_num;
701 map[flip_num] = defgroup;
702 }
703 }
704
705 return map;
706}
707
708int BKE_object_defgroup_flip_index(const Object *ob, int index, const bool use_default)
709{
710 const ListBase *defbase = BKE_object_defgroup_list(ob);
711 bDeformGroup *dg = static_cast<bDeformGroup *>(BLI_findlink(defbase, index));
712 int flip_index = -1;
713
714 if (dg) {
715 char name_flip[sizeof(dg->name)];
716 BLI_string_flip_side_name(name_flip, dg->name, false, sizeof(name_flip));
717
718 if (!STREQ(name_flip, dg->name)) {
719 flip_index = BKE_object_defgroup_name_index(ob, name_flip);
720 }
721 }
722
723 return (flip_index == -1 && use_default) ? index : flip_index;
724}
725
730
731static bool defgroup_find_name_dupe(const StringRef name, bDeformGroup *dg, Object *ob)
732{
733 const ListBase *defbase = BKE_object_defgroup_list(ob);
734
735 LISTBASE_FOREACH (bDeformGroup *, curdef, defbase) {
736 if (dg != curdef) {
737 if (curdef->name == name) {
738 return true;
739 }
740 }
741 }
742
743 return false;
744}
745
746static bool defgroup_unique_check(void *arg, const char *name)
747{
748 DeformGroupUniqueNameData *data = static_cast<DeformGroupUniqueNameData *>(arg);
749 return defgroup_find_name_dupe(name, data->dg, data->ob);
750}
751
753{
754 DeformGroupUniqueNameData data{ob, dg};
755 BLI_uniquename_cb(defgroup_unique_check, &data, DATA_("Group"), '.', dg->name, sizeof(dg->name));
756}
757
758void BKE_object_defgroup_set_name(bDeformGroup *dg, Object *ob, const char *new_name)
759{
760 std::string old_name = dg->name;
761 STRNCPY_UTF8(dg->name, new_name);
763
764 if (ob->type == OB_GREASE_PENCIL) {
765 /* Update vgroup names stored in CurvesGeometry */
766 BKE_grease_pencil_vgroup_name_update(ob, old_name.c_str(), dg->name);
767 }
768}
769
770float BKE_defvert_find_weight(const MDeformVert *dvert, const int defgroup)
771{
772 MDeformWeight *dw = BKE_defvert_find_index(dvert, defgroup);
773 return dw ? dw->weight : 0.0f;
774}
775
777 const int index,
778 const int defgroup)
779{
780 /* Invalid defgroup index means the vgroup selected is invalid,
781 * does not exist, in that case it is OK to return 1.0
782 * (i.e. maximum weight, as if no vgroup was selected).
783 * But in case of valid defgroup and nullptr dvert data pointer, it means that vgroup **is**
784 * valid, and just totally empty, so we shall return '0.0' value then! */
785 if (defgroup == -1) {
786 return 1.0f;
787 }
788 if (dvert == nullptr) {
789 return 0.0f;
790 }
791
792 return BKE_defvert_find_weight(dvert + index, defgroup);
793}
794
795MDeformWeight *BKE_defvert_find_index(const MDeformVert *dvert, const int defgroup)
796{
797 if (dvert && defgroup >= 0) {
798 MDeformWeight *dw = dvert->dw;
799 uint i;
800
801 for (i = dvert->totweight; i != 0; i--, dw++) {
802 if (dw->def_nr == defgroup) {
803 return dw;
804 }
805 }
806 }
807 else {
808 BLI_assert(0);
809 }
810
811 return nullptr;
812}
813
815{
816 MDeformWeight *dw_new;
817
818 /* do this check always, this function is used to check for it */
819 if (!dvert || defgroup < 0) {
820 BLI_assert(0);
821 return nullptr;
822 }
823
824 dw_new = BKE_defvert_find_index(dvert, defgroup);
825 if (dw_new) {
826 return dw_new;
827 }
828
829 dw_new = static_cast<MDeformWeight *>(
830 MEM_mallocN(sizeof(MDeformWeight) * (dvert->totweight + 1), __func__));
831 if (dvert->dw) {
832 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
833 MEM_freeN(dvert->dw);
834 }
835 dvert->dw = dw_new;
836 dw_new += dvert->totweight;
837 dw_new->weight = 0.0f;
838 dw_new->def_nr = defgroup;
839 /* Group index */
840
841 dvert->totweight++;
842
843 return dw_new;
844}
845
846void BKE_defvert_add_index_notest(MDeformVert *dvert, const int defgroup, const float weight)
847{
848 /* TODO: merge with #BKE_defvert_ensure_index! */
849
850 MDeformWeight *dw_new;
851
852 /* do this check always, this function is used to check for it */
853 if (!dvert || defgroup < 0) {
854 BLI_assert(0);
855 return;
856 }
857
858 dw_new = static_cast<MDeformWeight *>(
859 MEM_callocN(sizeof(MDeformWeight) * (dvert->totweight + 1), __func__));
860 if (dvert->dw) {
861 memcpy(dw_new, dvert->dw, sizeof(MDeformWeight) * dvert->totweight);
862 MEM_freeN(dvert->dw);
863 }
864 dvert->dw = dw_new;
865 dw_new += dvert->totweight;
866 dw_new->weight = weight;
867 dw_new->def_nr = defgroup;
868 dvert->totweight++;
869}
870
872{
873 if (UNLIKELY(!dvert || !dw)) {
874 return;
875 }
876 /* Ensure `dw` is part of `dvert` (security check). */
877 if (UNLIKELY(uintptr_t(dw - dvert->dw) >= uintptr_t(dvert->totweight))) {
878 /* Assert as an invalid `dw` (while supported) isn't likely to do what the caller expected. */
880 return;
881 }
882
883 const int i = dw - dvert->dw;
884 dvert->totweight--;
885 /* If there are still other deform weights attached to this vert then remove
886 * this deform weight, and reshuffle the others. */
887 if (dvert->totweight) {
888 BLI_assert(dvert->dw != nullptr);
889
890 if (i != dvert->totweight) {
891 dvert->dw[i] = dvert->dw[dvert->totweight];
892 }
893
894 dvert->dw = static_cast<MDeformWeight *>(
895 MEM_reallocN(dvert->dw, sizeof(MDeformWeight) * dvert->totweight));
896 }
897 else {
898 /* If there are no other deform weights left then just remove this one. */
899 MEM_freeN(dvert->dw);
900 dvert->dw = nullptr;
901 }
902}
903
905{
906 MEM_SAFE_FREE(dvert->dw);
907
908 dvert->totweight = 0;
909}
910
911int BKE_defvert_find_shared(const MDeformVert *dvert_a, const MDeformVert *dvert_b)
912{
913 if (dvert_a->totweight && dvert_b->totweight) {
914 MDeformWeight *dw = dvert_a->dw;
915 uint i;
916
917 for (i = dvert_a->totweight; i != 0; i--, dw++) {
918 if (dw->weight > 0.0f && BKE_defvert_find_weight(dvert_b, dw->def_nr) > 0.0f) {
919 return dw->def_nr;
920 }
921 }
922 }
923
924 return -1;
925}
926
927bool BKE_defvert_is_weight_zero(const MDeformVert *dvert, const int defgroup_tot)
928{
929 MDeformWeight *dw = dvert->dw;
930 for (int i = dvert->totweight; i != 0; i--, dw++) {
931 if (dw->weight != 0.0f) {
932 /* check the group is in-range, happens on rare situations */
933 if (LIKELY(dw->def_nr < defgroup_tot)) {
934 return false;
935 }
936 }
937 }
938 return true;
939}
940
942 int defbase_num,
943 const bool *defbase_sel)
944{
945 float total = 0.0f;
946 const MDeformWeight *dw = dv->dw;
947
948 if (defbase_sel == nullptr) {
949 return total;
950 }
951
952 for (int i = dv->totweight; i != 0; i--, dw++) {
953 if (dw->def_nr < defbase_num) {
954 if (defbase_sel[dw->def_nr]) {
955 total += dw->weight;
956 }
957 }
958 }
959
960 return total;
961}
962
964 const int defbase_num,
965 const bool *defbase_sel,
966 const int defbase_sel_num,
967 const bool is_normalized)
968{
969 float total = BKE_defvert_total_selected_weight(dv, defbase_num, defbase_sel);
970
971 /* in multipaint, get the average if auto normalize is inactive
972 * get the sum if it is active */
973 if (!is_normalized) {
974 total /= defbase_sel_num;
975 }
976
977 return total;
978}
979
981 float locked_weight,
982 float unlocked_weight)
983{
984 /* First try normalizing unlocked weights. */
985 if (unlocked_weight > 0.0f) {
986 return weight / unlocked_weight;
987 }
988
989 /* If no unlocked weight exists, take locked into account. */
990 if (locked_weight <= 0.0f) {
991 return weight;
992 }
993
994 /* handle division by zero */
995 if (locked_weight >= 1.0f - VERTEX_WEIGHT_LOCK_EPSILON) {
996 if (weight != 0.0f) {
997 return 1.0f;
998 }
999
1000 /* resolve 0/0 to 0 */
1001 return 0.0f;
1002 }
1003
1004 /* non-degenerate division */
1005 return weight / (1.0f - locked_weight);
1006}
1007
1008float BKE_defvert_lock_relative_weight(const float weight,
1009 const MDeformVert *dv,
1010 const int defbase_num,
1011 const bool *defbase_locked,
1012 const bool *defbase_unlocked)
1013{
1014 float unlocked = BKE_defvert_total_selected_weight(dv, defbase_num, defbase_unlocked);
1015
1016 if (unlocked > 0.0f) {
1017 return weight / unlocked;
1018 }
1019
1020 float locked = BKE_defvert_total_selected_weight(dv, defbase_num, defbase_locked);
1021
1022 return BKE_defvert_calc_lock_relative_weight(weight, locked, unlocked);
1023}
1024
1025/* -------------------------------------------------------------------- */
1029void BKE_defvert_array_copy(MDeformVert *dst, const MDeformVert *src, int totvert)
1030{
1031 /* Assumes dst is already set up */
1032
1033 if (!src || !dst) {
1034 return;
1035 }
1036
1037 memcpy(dst, src, totvert * sizeof(MDeformVert));
1038
1039 for (int i = 0; i < totvert; i++) {
1040 if (src[i].dw) {
1041 dst[i].dw = static_cast<MDeformWeight *>(
1042 MEM_mallocN(sizeof(MDeformWeight) * src[i].totweight, __func__));
1043 memcpy(dst[i].dw, src[i].dw, sizeof(MDeformWeight) * src[i].totweight);
1044 }
1045 }
1046}
1047
1049{
1050 /* Instead of freeing the verts directly,
1051 * call this function to delete any special
1052 * vert data */
1053
1054 if (!dvert) {
1055 return;
1056 }
1057
1058 /* Free any special data from the verts */
1059 for (int i = 0; i < totvert; i++) {
1060 if (dvert[i].dw) {
1061 MEM_freeN(dvert[i].dw);
1062 }
1063 }
1064}
1065
1066void BKE_defvert_array_free(MDeformVert *dvert, int totvert)
1067{
1068 /* Instead of freeing the verts directly,
1069 * call this function to delete any special
1070 * vert data */
1071 if (!dvert) {
1072 return;
1073 }
1074
1075 /* Free any special data from the verts */
1076 BKE_defvert_array_free_elems(dvert, totvert);
1077
1078 MEM_freeN(dvert);
1079}
1080
1082 const int defgroup,
1083 const int verts_num,
1084 const bool invert_vgroup,
1085 float *r_weights)
1086{
1087 if (dvert && defgroup != -1) {
1088 int i = verts_num;
1089
1090 while (i--) {
1091 const float w = BKE_defvert_find_weight(&dvert[i], defgroup);
1092 r_weights[i] = invert_vgroup ? (1.0f - w) : w;
1093 }
1094 }
1095 else {
1096 copy_vn_fl(r_weights, verts_num, invert_vgroup ? 1.0f : 0.0f);
1097 }
1098}
1099
1101 const int defgroup,
1102 const int verts_num,
1103 const blender::int2 *edges,
1104 const int edges_num,
1105 const bool invert_vgroup,
1106 float *r_weights)
1107{
1108 if (UNLIKELY(!dvert || defgroup == -1)) {
1109 copy_vn_fl(r_weights, edges_num, 0.0f);
1110 return;
1111 }
1112
1113 int i = edges_num;
1114 float *tmp_weights = static_cast<float *>(
1115 MEM_mallocN(sizeof(*tmp_weights) * size_t(verts_num), __func__));
1116
1118 dvert, defgroup, verts_num, invert_vgroup, tmp_weights);
1119
1120 while (i--) {
1121 const blender::int2 &edge = edges[i];
1122
1123 r_weights[i] = (tmp_weights[edge[0]] + tmp_weights[edge[1]]) * 0.5f;
1124 }
1125
1126 MEM_freeN(tmp_weights);
1127}
1128
1130 const int defgroup,
1131 const int verts_num,
1132 const int *corner_verts,
1133 const int loops_num,
1134 const bool invert_vgroup,
1135 float *r_weights)
1136{
1137 if (UNLIKELY(!dvert || defgroup == -1)) {
1138 copy_vn_fl(r_weights, loops_num, 0.0f);
1139 return;
1140 }
1141
1142 int i = loops_num;
1143 float *tmp_weights = static_cast<float *>(
1144 MEM_mallocN(sizeof(*tmp_weights) * size_t(verts_num), __func__));
1145
1147 dvert, defgroup, verts_num, invert_vgroup, tmp_weights);
1148
1149 while (i--) {
1150 r_weights[i] = tmp_weights[corner_verts[i]];
1151 }
1152
1153 MEM_freeN(tmp_weights);
1154}
1155
1157 const int defgroup,
1158 const int verts_num,
1159 const int *corner_verts,
1160 const int /*loops_num*/,
1161 const blender::OffsetIndices<int> faces,
1162 const bool invert_vgroup,
1163 float *r_weights)
1164{
1165 if (UNLIKELY(!dvert || defgroup == -1)) {
1166 copy_vn_fl(r_weights, faces.size(), 0.0f);
1167 return;
1168 }
1169
1170 int i = faces.size();
1171 float *tmp_weights = static_cast<float *>(
1172 MEM_mallocN(sizeof(*tmp_weights) * size_t(verts_num), __func__));
1173
1175 dvert, defgroup, verts_num, invert_vgroup, tmp_weights);
1176
1177 while (i--) {
1178 const blender::IndexRange face = faces[i];
1179 const int *corner_vert = &corner_verts[face.start()];
1180 int j = face.size();
1181 float w = 0.0f;
1182
1183 for (; j--; corner_vert++) {
1184 w += tmp_weights[*corner_vert];
1185 }
1186 r_weights[i] = w / float(face.size());
1187 }
1188
1189 MEM_freeN(tmp_weights);
1190}
1191
1194/* -------------------------------------------------------------------- */
1199 void *dest,
1200 const void **sources,
1201 const float *weights,
1202 const int count,
1203 const float mix_factor)
1204{
1205 MDeformVert **data_src = (MDeformVert **)sources;
1206 MDeformVert *data_dst = (MDeformVert *)dest;
1207 const int idx_src = laymap->data_src_n;
1208 const int idx_dst = laymap->data_dst_n;
1209
1210 const int mix_mode = laymap->mix_mode;
1211
1212 int i, j;
1213
1214 MDeformWeight *dw_src;
1215 MDeformWeight *dw_dst = BKE_defvert_find_index(data_dst, idx_dst);
1216 float weight_src = 0.0f, weight_dst = 0.0f;
1217
1218 bool has_dw_sources = false;
1219 if (sources) {
1220 for (i = count; i--;) {
1221 for (j = data_src[i]->totweight; j--;) {
1222 if ((dw_src = &data_src[i]->dw[j])->def_nr == idx_src) {
1223 weight_src += dw_src->weight * weights[i];
1224 has_dw_sources = true;
1225 break;
1226 }
1227 }
1228 }
1229 }
1230
1231 if (dw_dst) {
1232 weight_dst = dw_dst->weight;
1233 }
1234 else if (mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD) {
1235 return; /* Do not affect destination. */
1236 }
1237
1238 weight_src = data_transfer_interp_float_do(mix_mode, weight_dst, weight_src, mix_factor);
1239
1240 CLAMP(weight_src, 0.0f, 1.0f);
1241
1242 /* Do not create a destination MDeformWeight data if we had no sources at all. */
1243 if (!has_dw_sources) {
1244 BLI_assert(weight_src == 0.0f);
1245 if (dw_dst) {
1246 dw_dst->weight = weight_src;
1247 }
1248 }
1249 else if (!dw_dst) {
1250 BKE_defvert_add_index_notest(data_dst, idx_dst, weight_src);
1251 }
1252 else {
1253 dw_dst->weight = weight_src;
1254 }
1255}
1256
1258 const int mix_mode,
1259 const float mix_factor,
1260 const float *mix_weights,
1261 const int num_elem_dst,
1262 const bool use_create,
1263 const bool use_delete,
1264 Object *ob_src,
1265 Object *ob_dst,
1266 const MDeformVert *data_src,
1267 MDeformVert *data_dst,
1268 const CustomData * /*cd_src*/,
1269 CustomData *cd_dst,
1270 const bool /*use_dupref_dst*/,
1271 const int tolayers,
1272 const bool *use_layers_src,
1273 const int num_layers_src)
1274{
1275 int idx_src;
1276 int idx_dst;
1277 const ListBase *src_list = BKE_object_defgroup_list(ob_src);
1278 ListBase *dst_defbase = BKE_object_defgroup_list_mutable(ob_dst);
1279
1280 const int tot_dst = BLI_listbase_count(dst_defbase);
1281
1282 const size_t elem_size = sizeof(MDeformVert);
1283
1284 switch (tolayers) {
1286 idx_dst = tot_dst;
1287
1288 /* Find last source actually used! */
1289 idx_src = num_layers_src;
1290 while (idx_src-- && !use_layers_src[idx_src]) {
1291 /* pass */
1292 }
1293 idx_src++;
1294
1295 if (idx_dst < idx_src) {
1296 if (use_create) {
1297 /* Create as much vgroups as necessary! */
1298 for (; idx_dst < idx_src; idx_dst++) {
1300 }
1301 }
1302 else {
1303 /* Otherwise, just try to map what we can with existing dst vgroups. */
1304 idx_src = idx_dst;
1305 }
1306 }
1307 else if (use_delete && idx_dst > idx_src) {
1308 while (idx_dst-- > idx_src) {
1309 BKE_object_defgroup_remove(ob_dst, static_cast<bDeformGroup *>(dst_defbase->last));
1310 }
1311 }
1312 if (r_map) {
1313 /* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest!
1314 * Again, use_create is not relevant in this case */
1315 if (!data_dst) {
1316 data_dst = static_cast<MDeformVert *>(
1317 CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, num_elem_dst));
1318 }
1319
1320 while (idx_src--) {
1321 if (!use_layers_src[idx_src]) {
1322 continue;
1323 }
1326 mix_mode,
1327 mix_factor,
1328 mix_weights,
1329 data_src,
1330 data_dst,
1331 idx_src,
1332 idx_src,
1333 elem_size,
1334 0,
1335 0,
1336 0,
1338 nullptr);
1339 }
1340 }
1341 break;
1342 case DT_LAYERS_NAME_DST: {
1343 bDeformGroup *dg_src, *dg_dst;
1344
1345 if (use_delete) {
1346 /* Remove all unused dst vgroups first, simpler in this case. */
1347 for (dg_dst = static_cast<bDeformGroup *>(dst_defbase->first); dg_dst;) {
1348 bDeformGroup *dg_dst_next = dg_dst->next;
1349
1350 if (BKE_object_defgroup_name_index(ob_src, dg_dst->name) == -1) {
1351 BKE_object_defgroup_remove(ob_dst, dg_dst);
1352 }
1353 dg_dst = dg_dst_next;
1354 }
1355 }
1356
1357 for (idx_src = 0, dg_src = static_cast<bDeformGroup *>(src_list->first);
1358 idx_src < num_layers_src;
1359 idx_src++, dg_src = dg_src->next)
1360 {
1361 if (!use_layers_src[idx_src]) {
1362 continue;
1363 }
1364
1365 if ((idx_dst = BKE_object_defgroup_name_index(ob_dst, dg_src->name)) == -1) {
1366 if (use_create) {
1367 BKE_object_defgroup_add_name(ob_dst, dg_src->name);
1368 idx_dst = BKE_object_defgroup_active_index_get(ob_dst) - 1;
1369 }
1370 else {
1371 /* If we are not allowed to create missing dst vgroups, just skip matching src one. */
1372 continue;
1373 }
1374 }
1375 if (r_map) {
1376 /* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest!
1377 * use_create is not relevant in this case */
1378 if (!data_dst) {
1379 data_dst = static_cast<MDeformVert *>(
1380 CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, num_elem_dst));
1381 }
1382
1385 mix_mode,
1386 mix_factor,
1387 mix_weights,
1388 data_src,
1389 data_dst,
1390 idx_src,
1391 idx_dst,
1392 elem_size,
1393 0,
1394 0,
1395 0,
1397 nullptr);
1398 }
1399 }
1400 break;
1401 }
1402 default:
1403 return false;
1404 }
1405
1406 return true;
1407}
1408
1410 const int mix_mode,
1411 const float mix_factor,
1412 const float *mix_weights,
1413 const int num_elem_dst,
1414 const bool use_create,
1415 const bool use_delete,
1416 Object *ob_src,
1417 Object *ob_dst,
1418 const CustomData *cd_src,
1419 CustomData *cd_dst,
1420 const bool use_dupref_dst,
1421 const int fromlayers,
1422 const int tolayers)
1423{
1424 int idx_src, idx_dst;
1425
1426 const size_t elem_size = sizeof(MDeformVert);
1427
1428 /* NOTE:
1429 * VGroups are a bit hairy, since their layout is defined on object level (ob->defbase),
1430 * while their actual data is a (mesh) CD layer.
1431 * This implies we may have to handle data layout itself while having nullptr data itself,
1432 * and even have to support nullptr data_src in transfer data code
1433 * (we always create a data_dst, though).
1434 *
1435 * NOTE: Above comment is outdated, but this function was written when that was true.
1436 */
1437
1438 const ListBase *src_defbase = BKE_object_defgroup_list(ob_src);
1439 if (BLI_listbase_is_empty(src_defbase)) {
1440 if (use_delete) {
1442 }
1443 return true;
1444 }
1445
1446 const MDeformVert *data_src = static_cast<const MDeformVert *>(
1448
1449 MDeformVert *data_dst = static_cast<MDeformVert *>(
1450 CustomData_get_layer_for_write(cd_dst, CD_MDEFORMVERT, num_elem_dst));
1451 if (data_dst && use_dupref_dst && r_map) {
1452 /* If dest is an evaluated mesh, we do not want to overwrite cdlayers of org mesh! */
1453 data_dst = static_cast<MDeformVert *>(
1454 CustomData_get_layer_for_write(cd_dst, CD_MDEFORMVERT, num_elem_dst));
1455 }
1456
1457 if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) {
1458 /* NOTE: use_delete has not much meaning in this case, ignored. */
1459
1460 if (fromlayers >= 0) {
1461 idx_src = fromlayers;
1462 if (idx_src >= BLI_listbase_count(src_defbase)) {
1463 /* This can happen when vgroups are removed from source object...
1464 * Remapping would be really tricky here, we'd need to go over all objects in
1465 * Main every time we delete a vgroup... for now, simpler and safer to abort. */
1466 return false;
1467 }
1468 }
1469 else if ((idx_src = BKE_object_defgroup_active_index_get(ob_src) - 1) == -1) {
1470 return false;
1471 }
1472
1473 if (tolayers >= 0) {
1474 /* NOTE: in this case we assume layer exists! */
1475 idx_dst = tolayers;
1476 const ListBase *dst_defbase = BKE_object_defgroup_list(ob_dst);
1477 BLI_assert(idx_dst < BLI_listbase_count(dst_defbase));
1478 UNUSED_VARS_NDEBUG(dst_defbase);
1479 }
1480 else if (tolayers == DT_LAYERS_ACTIVE_DST) {
1481 if ((idx_dst = BKE_object_defgroup_active_index_get(ob_dst) - 1) == -1) {
1482 bDeformGroup *dg_src;
1483 if (!use_create) {
1484 return true;
1485 }
1486 dg_src = static_cast<bDeformGroup *>(BLI_findlink(src_defbase, idx_src));
1487 BKE_object_defgroup_add_name(ob_dst, dg_src->name);
1488 idx_dst = BKE_object_defgroup_active_index_get(ob_dst) - 1;
1489 }
1490 }
1491 else if (tolayers == DT_LAYERS_INDEX_DST) {
1492 int num = BLI_listbase_count(src_defbase);
1493 idx_dst = idx_src;
1494 if (num <= idx_dst) {
1495 if (!use_create) {
1496 return true;
1497 }
1498 /* Create as much vgroups as necessary! */
1499 for (; num <= idx_dst; num++) {
1501 }
1502 }
1503 }
1504 else if (tolayers == DT_LAYERS_NAME_DST) {
1505 bDeformGroup *dg_src = static_cast<bDeformGroup *>(BLI_findlink(src_defbase, idx_src));
1506 if ((idx_dst = BKE_object_defgroup_name_index(ob_dst, dg_src->name)) == -1) {
1507 if (!use_create) {
1508 return true;
1509 }
1510 BKE_object_defgroup_add_name(ob_dst, dg_src->name);
1511 idx_dst = BKE_object_defgroup_active_index_get(ob_dst) - 1;
1512 }
1513 }
1514 else {
1515 return false;
1516 }
1517
1518 if (r_map) {
1519 /* At this stage, we **need** a valid CD_MDEFORMVERT layer on dest!
1520 * use_create is not relevant in this case */
1521 if (!data_dst) {
1522 data_dst = static_cast<MDeformVert *>(
1523 CustomData_add_layer(cd_dst, CD_MDEFORMVERT, CD_SET_DEFAULT, num_elem_dst));
1524 }
1525
1528 mix_mode,
1529 mix_factor,
1530 mix_weights,
1531 data_src,
1532 data_dst,
1533 idx_src,
1534 idx_dst,
1535 elem_size,
1536 0,
1537 0,
1538 0,
1540 nullptr);
1541 }
1542 }
1543 else {
1544 int num_src, num_sel_unused;
1545 bool *use_layers_src = nullptr;
1546 bool ret = false;
1547
1548 switch (fromlayers) {
1549 case DT_LAYERS_ALL_SRC:
1551 ob_src, WT_VGROUP_ALL, &num_src, &num_sel_unused);
1552 break;
1555 ob_src, WT_VGROUP_BONE_SELECT, &num_src, &num_sel_unused);
1556 break;
1559 ob_src, WT_VGROUP_BONE_DEFORM, &num_src, &num_sel_unused);
1560 break;
1561 }
1562
1563 if (use_layers_src) {
1565 mix_mode,
1566 mix_factor,
1567 mix_weights,
1568 num_elem_dst,
1569 use_create,
1570 use_delete,
1571 ob_src,
1572 ob_dst,
1573 data_src,
1574 data_dst,
1575 cd_src,
1576 cd_dst,
1577 use_dupref_dst,
1578 tolayers,
1579 use_layers_src,
1580 num_src);
1581 }
1582
1583 MEM_SAFE_FREE(use_layers_src);
1584 return ret;
1585 }
1586
1587 return true;
1588}
1589
1592/* -------------------------------------------------------------------- */
1596void BKE_defvert_weight_to_rgb(float r_rgb[3], const float weight)
1597{
1598 const float blend = ((weight / 2.0f) + 0.5f);
1599
1600 if (weight <= 0.25f) { /* blue->cyan */
1601 r_rgb[0] = 0.0f;
1602 r_rgb[1] = blend * weight * 4.0f;
1603 r_rgb[2] = blend;
1604 }
1605 else if (weight <= 0.50f) { /* cyan->green */
1606 r_rgb[0] = 0.0f;
1607 r_rgb[1] = blend;
1608 r_rgb[2] = blend * (1.0f - ((weight - 0.25f) * 4.0f));
1609 }
1610 else if (weight <= 0.75f) { /* green->yellow */
1611 r_rgb[0] = blend * ((weight - 0.50f) * 4.0f);
1612 r_rgb[1] = blend;
1613 r_rgb[2] = 0.0f;
1614 }
1615 else if (weight <= 1.0f) { /* yellow->red */
1616 r_rgb[0] = blend;
1617 r_rgb[1] = blend * (1.0f - ((weight - 0.75f) * 4.0f));
1618 r_rgb[2] = 0.0f;
1619 }
1620 else {
1621 /* exceptional value, unclamped or nan,
1622 * avoid uninitialized memory use */
1623 r_rgb[0] = 1.0f;
1624 r_rgb[1] = 0.0f;
1625 r_rgb[2] = 1.0f;
1626 }
1627}
1628
1631/* -------------------------------------------------------------------- */
1635void BKE_defbase_blend_write(BlendWriter *writer, const ListBase *defbase)
1636{
1637 LISTBASE_FOREACH (bDeformGroup *, defgroup, defbase) {
1638 BLO_write_struct(writer, bDeformGroup, defgroup);
1639 }
1640}
1641
1642void BKE_defvert_blend_write(BlendWriter *writer, int count, const MDeformVert *dvlist)
1643{
1644 if (dvlist == nullptr) {
1645 return;
1646 }
1647
1648 /* Write the dvert list */
1649 BLO_write_struct_array(writer, MDeformVert, count, dvlist);
1650
1651 /* Write deformation data for each dvert */
1652 for (int i = 0; i < count; i++) {
1653 if (dvlist[i].dw) {
1654 BLO_write_struct_array(writer, MDeformWeight, dvlist[i].totweight, dvlist[i].dw);
1655 }
1656 }
1657}
1658
1660{
1661 if (mdverts == nullptr) {
1662 return;
1663 }
1664
1665 for (int i = count; i > 0; i--, mdverts++) {
1666 /* Convert to vertex group allocation system. */
1667 MDeformWeight *dw = mdverts->dw;
1668 BLO_read_struct_array(reader, MDeformWeight, mdverts->totweight, &dw);
1669 if (dw) {
1670 const size_t dw_len = sizeof(MDeformWeight) * mdverts->totweight;
1671 void *dw_tmp = MEM_mallocN(dw_len, __func__);
1672 memcpy(dw_tmp, dw, dw_len);
1673 mdverts->dw = static_cast<MDeformWeight *>(dw_tmp);
1674 MEM_freeN(dw);
1675 }
1676 else {
1677 mdverts->dw = nullptr;
1678 mdverts->totweight = 0;
1679 }
1680 }
1681}
1682
1685/* -------------------------------------------------------------------- */
1689namespace blender::bke {
1690
1692 private:
1693 MDeformVert *dverts_;
1694 const int dvert_index_;
1695
1696 public:
1698 : VMutableArrayImpl<float>(dverts.size()), dverts_(dverts.data()), dvert_index_(dvert_index)
1699 {
1700 }
1701
1703 : VMutableArrayImpl<float>(dverts.size()),
1704 dverts_(const_cast<MDeformVert *>(dverts.data())),
1705 dvert_index_(dvert_index)
1706 {
1707 }
1708
1709 float get(const int64_t index) const override
1710 {
1711 if (dverts_ == nullptr) {
1712 return 0.0f;
1713 }
1714 if (const MDeformWeight *weight = this->find_weight_at_index(index)) {
1715 return weight->weight;
1716 }
1717 return 0.0f;
1718 }
1719
1720 void set(const int64_t index, const float value) override
1721 {
1722 MDeformVert &dvert = dverts_[index];
1723 if (value == 0.0f) {
1724 if (MDeformWeight *weight = this->find_weight_at_index(index)) {
1725 weight->weight = 0.0f;
1726 }
1727 }
1728 else {
1729 MDeformWeight *weight = BKE_defvert_ensure_index(&dvert, dvert_index_);
1730 weight->weight = value;
1731 }
1732 }
1733
1734 void set_all(Span<float> src) override
1735 {
1736 threading::parallel_for(src.index_range(), 4096, [&](const IndexRange range) {
1737 for (const int64_t i : range) {
1738 this->set(i, src[i]);
1739 }
1740 });
1741 }
1742
1743 void materialize(const IndexMask &mask, float *dst) const override
1744 {
1745 if (dverts_ == nullptr) {
1746 mask.foreach_index([&](const int i) { dst[i] = 0.0f; });
1747 }
1748 threading::parallel_for(mask.index_range(), 4096, [&](const IndexRange range) {
1749 mask.slice(range).foreach_index_optimized<int64_t>([&](const int64_t index) {
1750 if (const MDeformWeight *weight = this->find_weight_at_index(index)) {
1751 dst[index] = weight->weight;
1752 }
1753 else {
1754 dst[index] = 0.0f;
1755 }
1756 });
1757 });
1758 }
1759
1760 void materialize_to_uninitialized(const IndexMask &mask, float *dst) const override
1761 {
1762 this->materialize(mask, dst);
1763 }
1764
1765 private:
1766 MDeformWeight *find_weight_at_index(const int64_t index)
1767 {
1768 for (MDeformWeight &weight : MutableSpan(dverts_[index].dw, dverts_[index].totweight)) {
1769 if (weight.def_nr == dvert_index_) {
1770 return &weight;
1771 }
1772 }
1773 return nullptr;
1774 }
1775 const MDeformWeight *find_weight_at_index(const int64_t index) const
1776 {
1777 for (const MDeformWeight &weight : Span(dverts_[index].dw, dverts_[index].totweight)) {
1778 if (weight.def_nr == dvert_index_) {
1779 return &weight;
1780 }
1781 }
1782 return nullptr;
1783 }
1784};
1785
1787{
1788 return VArray<float>::For<VArrayImpl_For_VertexWeights>(dverts, defgroup_index);
1789}
1791 const int defgroup_index)
1792{
1793 return VMutableArray<float>::For<VArrayImpl_For_VertexWeights>(dverts, defgroup_index);
1794}
1795
1796void remove_defgroup_index(MutableSpan<MDeformVert> dverts, const int defgroup_index)
1797{
1798 threading::parallel_for(dverts.index_range(), 1024, [&](IndexRange range) {
1799 for (MDeformVert &dvert : dverts.slice(range)) {
1800 MDeformWeight *weight = BKE_defvert_find_index(&dvert, defgroup_index);
1801 BKE_defvert_remove_group(&dvert, weight);
1802 for (MDeformWeight &weight : MutableSpan(dvert.dw, dvert.totweight)) {
1803 if (weight.def_nr > defgroup_index) {
1804 weight.def_nr--;
1805 }
1806 }
1807 }
1808 });
1809}
1810
1812 const Span<int> indices,
1814{
1815 threading::parallel_for(indices.index_range(), 512, [&](const IndexRange range) {
1816 for (const int dst_i : range) {
1817 const int src_i = indices[dst_i];
1818 dst[dst_i].dw = static_cast<MDeformWeight *>(MEM_dupallocN(src[src_i].dw));
1819 dst[dst_i].totweight = src[src_i].totweight;
1820 dst[dst_i].flag = src[src_i].flag;
1821 }
1822 });
1823}
1825 const IndexMask &indices,
1827{
1828 indices.foreach_index(GrainSize(512), [&](const int64_t src_i, const int64_t dst_i) {
1829 dst[dst_i].dw = static_cast<MDeformWeight *>(MEM_dupallocN(src[src_i].dw));
1830 dst[dst_i].totweight = src[src_i].totweight;
1831 dst[dst_i].flag = src[src_i].flag;
1832 });
1833}
1834
1835} // namespace blender::bke
1836
CustomData interface, see also DNA_customdata_types.h.
@ CDT_MIX_REPLACE_ABOVE_THRESHOLD
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
@ CD_SET_DEFAULT
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
@ CD_FAKE_MDEFORMVERT
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
@ DT_LAYERS_ACTIVE_DST
@ DT_LAYERS_INDEX_DST
@ DT_LAYERS_NAME_DST
@ DT_LAYERS_VGROUP_SRC_BONE_SELECT
@ DT_LAYERS_VGROUP_SRC_BONE_DEFORM
@ DT_LAYERS_ALL_SRC
@ DT_LAYERS_ACTIVE_SRC
support for deformation groups and hooks.
MDeformWeight * BKE_defvert_ensure_index(MDeformVert *dv, int defgroup)
Definition deform.cc:814
#define VERTEX_WEIGHT_LOCK_EPSILON
Low-level operations for grease pencil.
void BKE_grease_pencil_vgroup_name_update(Object *ob, const char *old_name, const char *new_name)
Utility functions for vertex groups in grease pencil objects.
General operations, lookup, etc. for blender objects.
void BKE_object_batch_cache_dirty_tag(Object *ob)
Functions for dealing with objects and deform verts, used by painting and tools.
bool * BKE_object_defgroup_subset_from_select_type(struct Object *ob, enum eVGroupSelect subset_type, int *r_defgroup_tot, int *r_subset_count)
void BKE_object_defgroup_remove(struct Object *ob, struct bDeformGroup *defgroup)
struct bDeformGroup * BKE_object_defgroup_add(struct Object *ob)
struct bDeformGroup * BKE_object_defgroup_add_name(struct Object *ob, const char *name)
void BKE_object_defgroup_remove_all(struct Object *ob)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
void copy_vn_fl(float *array_tar, int size, float val)
#define STRNCPY_UTF8(dst, src)
size_t BLI_string_flip_side_name(char *name_dst, const char *name_src, bool strip_number, size_t name_dst_maxncpy) ATTR_NONNULL(1
size_t void BLI_uniquename_cb(UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_maxncpy) ATTR_NONNULL(1
unsigned int uint
#define CLAMP(a, b, c)
#define UNUSED_VARS_NDEBUG(...)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
#define LIKELY(x)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
#define DATA_(msgid)
@ ID_GD_LEGACY
@ ID_ME
@ ID_LT
@ ID_GP
@ CD_MDEFORMVERT
struct MDeformVert MDeformVert
struct MDeformWeight MDeformWeight
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_GPENCIL_LEGACY
@ DG_LOCK_WEIGHT
#define OB_TYPE_SUPPORT_VGROUP(_type)
@ WT_VGROUP_BONE_SELECT
@ WT_VGROUP_ALL
@ WT_VGROUP_BONE_DEFORM
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
constexpr int64_t size() const
constexpr IndexRange index_range() const
Definition BLI_span.hh:671
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
void set_all(Span< float > src) override
Definition deform.cc:1734
void materialize(const IndexMask &mask, float *dst) const override
Definition deform.cc:1743
float get(const int64_t index) const override
Definition deform.cc:1709
void set(const int64_t index, const float value) override
Definition deform.cc:1720
void materialize_to_uninitialized(const IndexMask &mask, float *dst) const override
Definition deform.cc:1760
VArrayImpl_For_VertexWeights(MutableSpan< MDeformVert > dverts, const int dvert_index)
Definition deform.cc:1697
VArrayImpl_For_VertexWeights(Span< MDeformVert > dverts, const int dvert_index)
Definition deform.cc:1702
void data_transfer_layersmapping_add_item(ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights, const void *data_src, void *data_dst, const int data_src_n, const int data_dst_n, const size_t elem_size, const size_t data_size, const size_t data_offset, const uint64_t data_flag, cd_datatransfer_interp interp, void *interp_data)
float data_transfer_interp_float_do(const int mix_mode, const float val_dst, const float val_src, const float mix_factor)
int BKE_object_defgroup_name_index(const Object *ob, const StringRef name)
Definition deform.cc:585
void BKE_defvert_blend_write(BlendWriter *writer, int count, const MDeformVert *dvlist)
Definition deform.cc:1642
void BKE_defbase_blend_write(BlendWriter *writer, const ListBase *defbase)
Definition deform.cc:1635
ListBase * BKE_id_defgroup_list_get_mutable(ID *id)
Definition deform.cc:514
void BKE_defvert_array_free(MDeformVert *dvert, int totvert)
Definition deform.cc:1066
static const int * object_defgroup_active_index_get_p(const Object *ob)
Definition deform.cc:490
void BKE_defvert_array_copy(MDeformVert *dst, const MDeformVert *src, int totvert)
Definition deform.cc:1029
bool BKE_defgroup_listbase_name_find(const ListBase *defbase, const StringRef name, int *r_index, bDeformGroup **r_group)
Definition deform.cc:548
bool BKE_id_supports_vertex_groups(const ID *id)
Definition deform.cc:449
void BKE_defvert_extract_vgroup_to_faceweights(const MDeformVert *dvert, const int defgroup, const int verts_num, const int *corner_verts, const int, const blender::OffsetIndices< int > faces, const bool invert_vgroup, float *r_weights)
Definition deform.cc:1156
int BKE_object_defgroup_active_index_get(const Object *ob)
Definition deform.cc:601
bDeformGroup * BKE_object_defgroup_find_name(const Object *ob, const StringRef name)
Definition deform.cc:520
void BKE_defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int flip_map_num)
Definition deform.cc:424
void BKE_defvert_copy_index(MDeformVert *dvert_dst, const int defgroup_dst, const MDeformVert *dvert_src, const int defgroup_src)
Definition deform.cc:153
void BKE_defvert_normalize(MDeformVert *dvert)
Definition deform.cc:272
float BKE_defvert_lock_relative_weight(const float weight, const MDeformVert *dv, const int defbase_num, const bool *defbase_locked, const bool *defbase_unlocked)
Definition deform.cc:1008
void BKE_defvert_copy_subset(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const bool *vgroup_subset, const int vgroup_num)
Definition deform.cc:102
int BKE_defgroup_name_index(const ListBase *defbase, const StringRef name)
Definition deform.cc:534
float BKE_defvert_array_find_weight_safe(const MDeformVert *dvert, const int index, const int defgroup)
Definition deform.cc:776
bDeformGroup * BKE_defgroup_duplicate(const bDeformGroup *ingroup)
Definition deform.cc:85
bool BKE_object_supports_vertex_groups(const Object *ob)
Definition deform.cc:457
void BKE_defvert_extract_vgroup_to_edgeweights(const MDeformVert *dvert, const int defgroup, const int verts_num, const blender::int2 *edges, const int edges_num, const bool invert_vgroup, float *r_weights)
Definition deform.cc:1100
void BKE_defvert_weight_to_rgb(float r_rgb[3], const float weight)
Definition deform.cc:1596
void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert, const int defgroup, const int verts_num, const int *corner_verts, const int loops_num, const bool invert_vgroup, float *r_weights)
Definition deform.cc:1129
int BKE_object_defgroup_count(const Object *ob)
Definition deform.cc:596
int * BKE_object_defgroup_flip_map_single(const Object *ob, const bool use_default, const int defgroup, int *r_flip_map_num)
Definition deform.cc:673
bool BKE_id_defgroup_name_find(const ID *id, const StringRef name, int *r_index, bDeformGroup **r_group)
Definition deform.cc:571
bool BKE_defvert_is_weight_zero(const MDeformVert *dvert, const int defgroup_tot)
Definition deform.cc:927
void BKE_object_defgroup_active_index_set(Object *ob, const int new_index)
Definition deform.cc:606
const ListBase * BKE_object_defgroup_list(const Object *ob)
Definition deform.cc:579
static bool defgroup_find_name_dupe(const StringRef name, bDeformGroup *dg, Object *ob)
Definition deform.cc:731
int BKE_object_defgroup_flip_index(const Object *ob, int index, const bool use_default)
Definition deform.cc:708
float BKE_defvert_calc_lock_relative_weight(float weight, float locked_weight, float unlocked_weight)
Definition deform.cc:980
int BKE_id_defgroup_name_index(const ID *id, const StringRef name)
Definition deform.cc:543
void BKE_defvert_normalize_lock_map(MDeformVert *dvert, const bool *vgroup_subset, const int vgroup_num, const bool *lock_flags, const int defbase_num)
Definition deform.cc:355
float BKE_defvert_find_weight(const MDeformVert *dvert, const int defgroup)
Definition deform.cc:770
void BKE_defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const bool use_ensure)
Definition deform.cc:177
static void vgroups_datatransfer_interp(const CustomDataTransferLayerMap *laymap, void *dest, const void **sources, const float *weights, const int count, const float mix_factor)
Definition deform.cc:1198
void BKE_defvert_mirror_subset(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const bool *vgroup_subset, const int vgroup_num, const int *flip_map, const int flip_map_num)
Definition deform.cc:115
void BKE_defvert_normalize_subset(MDeformVert *dvert, const bool *vgroup_subset, const int vgroup_num)
Definition deform.cc:235
int BKE_defvert_find_shared(const MDeformVert *dvert_a, const MDeformVert *dvert_b)
Definition deform.cc:911
static bool defgroup_unique_check(void *arg, const char *name)
Definition deform.cc:746
void BKE_object_defgroup_unique_name(bDeformGroup *dg, Object *ob)
Definition deform.cc:752
void BKE_defvert_array_free_elems(MDeformVert *dvert, int totvert)
Definition deform.cc:1048
float BKE_defvert_total_selected_weight(const MDeformVert *dv, int defbase_num, const bool *defbase_sel)
Definition deform.cc:941
void BKE_defvert_normalize_lock_single(MDeformVert *dvert, const bool *vgroup_subset, const int vgroup_num, const uint def_nr_lock)
Definition deform.cc:301
bDeformGroup * BKE_object_defgroup_new(Object *ob, const StringRef name)
Definition deform.cc:51
void BKE_defgroup_copy_list(ListBase *outbase, const ListBase *inbase)
Definition deform.cc:76
float BKE_defvert_multipaint_collective_weight(const MDeformVert *dv, const int defbase_num, const bool *defbase_sel, const int defbase_sel_num, const bool is_normalized)
Definition deform.cc:963
void BKE_defvert_extract_vgroup_to_vertweights(const MDeformVert *dvert, const int defgroup, const int verts_num, const bool invert_vgroup, float *r_weights)
Definition deform.cc:1081
void BKE_defvert_clear(MDeformVert *dvert)
Definition deform.cc:904
ListBase * BKE_object_defgroup_list_mutable(Object *ob)
Definition deform.cc:590
void BKE_defvert_flip(MDeformVert *dvert, const int *flip_map, const int flip_map_num)
Definition deform.cc:410
static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map, const int mix_mode, const float mix_factor, const float *mix_weights, const int num_elem_dst, const bool use_create, const bool use_delete, Object *ob_src, Object *ob_dst, const MDeformVert *data_src, MDeformVert *data_dst, const CustomData *, CustomData *cd_dst, const bool, const int tolayers, const bool *use_layers_src, const int num_layers_src)
Definition deform.cc:1257
void BKE_defvert_add_index_notest(MDeformVert *dvert, const int defgroup, const float weight)
Definition deform.cc:846
void BKE_defvert_blend_read(BlendDataReader *reader, int count, MDeformVert *mdverts)
Definition deform.cc:1659
static int * object_defgroup_unlocked_flip_map_ex(const Object *ob, const bool use_default, const bool use_only_unlocked, int *r_flip_map_num)
Definition deform.cc:613
void BKE_defvert_copy(MDeformVert *dvert_dst, const MDeformVert *dvert_src)
Definition deform.cc:130
void BKE_defvert_sync_mapped(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const int *flip_map, const int flip_map_num, const bool use_ensure)
Definition deform.cc:197
int * BKE_object_defgroup_flip_map(const Object *ob, const bool use_default, int *r_flip_map_num)
Definition deform.cc:661
MDeformWeight * BKE_defvert_ensure_index(MDeformVert *dvert, const int defgroup)
Definition deform.cc:814
void BKE_defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
Definition deform.cc:871
void BKE_defvert_remap(MDeformVert *dvert, const int *map, const int map_len)
Definition deform.cc:223
MDeformWeight * BKE_defvert_find_index(const MDeformVert *dvert, const int defgroup)
Definition deform.cc:795
const ListBase * BKE_id_defgroup_list_get(const ID *id)
Definition deform.cc:464
bool data_transfer_layersmapping_vgroups(ListBase *r_map, const int mix_mode, const float mix_factor, const float *mix_weights, const int num_elem_dst, const bool use_create, const bool use_delete, Object *ob_src, Object *ob_dst, const CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst, const int fromlayers, const int tolayers)
Definition deform.cc:1409
int * BKE_object_defgroup_flip_map_unlocked(const Object *ob, const bool use_default, int *r_flip_map_num)
Definition deform.cc:666
void BKE_object_defgroup_set_name(bDeformGroup *dg, Object *ob, const char *new_name)
Definition deform.cc:758
Lattice lattice
draw_view in_light_buf[] float
int count
#define GS(x)
Definition iris.cc:202
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
void validate_drawing_vertex_groups(GreasePencil &grease_pencil)
void remove_defgroup_index(MutableSpan< MDeformVert > dverts, int defgroup_index)
Definition deform.cc:1796
void gather_deform_verts(Span< MDeformVert > src, Span< int > indices, MutableSpan< MDeformVert > dst)
Definition deform.cc:1811
VMutableArray< float > varray_for_mutable_deform_verts(MutableSpan< MDeformVert > dverts, int defgroup_index)
Definition deform.cc:1790
VArray< float > varray_for_deform_verts(Span< MDeformVert > dverts, int defgroup_index)
Definition deform.cc:1786
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:95
return ret
_W64 unsigned int uintptr_t
Definition stdint.h:119
__int64 int64_t
Definition stdint.h:89
bDeformGroup * dg
Definition deform.cc:728
Definition DNA_ID.h:413
ListBase vertex_group_names
int vertex_group_active_index
void * last
void * first
struct MDeformWeight * dw
unsigned int def_nr
ListBase vertex_group_names
struct bDeformGroup * next
struct bDeformGroup * prev
ListBase vertex_group_names