Blender V4.5
data_transfer.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2014 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "MEM_guardedalloc.h"
10
12#include "DNA_mesh_types.h"
13#include "DNA_meshdata_types.h"
14#include "DNA_object_types.h"
15
16#include "BLI_listbase.h"
17#include "BLI_math_base.h"
18#include "BLI_math_matrix.h"
19#include "BLI_string.h"
20#include "BLI_utildefines.h"
21
22#include "BKE_attribute.hh"
23#include "BKE_customdata.hh"
24#include "BKE_data_transfer.h"
25#include "BKE_deform.hh"
26#include "BKE_mesh.hh"
27#include "BKE_mesh_mapping.hh"
28#include "BKE_mesh_remap.hh"
29#include "BKE_mesh_runtime.hh"
30#include "BKE_mesh_wrapper.hh"
31#include "BKE_modifier.hh"
32#include "BKE_object.hh"
33#include "BKE_report.hh"
34
36
38
40
42 CustomData_MeshMasks *r_data_masks)
43{
44 for (int i = 0; i < DT_TYPE_MAX; i++) {
45 const int dtdata_type = 1 << i;
46 int cddata_type;
47
48 if (!(dtdata_types & dtdata_type)) {
49 continue;
50 }
51
52 cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type);
53 if (!(cddata_type & CD_FAKE)) {
54 if (DT_DATATYPE_IS_VERT(dtdata_type)) {
55 r_data_masks->vmask |= 1LL << cddata_type;
56 }
57 else if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
58 r_data_masks->emask |= 1LL << cddata_type;
59 }
60 else if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
61 r_data_masks->lmask |= 1LL << cddata_type;
62 }
63 else if (DT_DATATYPE_IS_FACE(dtdata_type)) {
64 r_data_masks->pmask |= 1LL << cddata_type;
65 }
66 }
67 else if (cddata_type == CD_FAKE_MDEFORMVERT) {
68 r_data_masks->vmask |= CD_MASK_MDEFORMVERT; /* Exception for vgroups :/ */
69 }
70 else if (cddata_type == CD_FAKE_UV) {
71 r_data_masks->lmask |= CD_MASK_PROP_FLOAT2;
72 }
73 }
74}
75
77 bool *r_advanced_mixing,
78 bool *r_threshold)
79{
80 bool ret = false;
81
82 *r_advanced_mixing = false;
83 *r_threshold = false;
84
85 for (int i = 0; (i < DT_TYPE_MAX) && !(ret && *r_advanced_mixing && *r_threshold); i++) {
86 const int dtdata_type = 1 << i;
87
88 if (!(dtdata_types & dtdata_type)) {
89 continue;
90 }
91
92 switch (dtdata_type) {
93 /* Vertex data */
95 *r_advanced_mixing = true;
96 *r_threshold = true;
97 ret = true;
98 break;
99 case DT_TYPE_SKIN:
100 *r_threshold = true;
101 ret = true;
102 break;
104 ret = true;
105 break;
106 /* Edge data */
108 *r_threshold = true;
109 ret = true;
110 break;
111 case DT_TYPE_SEAM:
112 *r_threshold = true;
113 ret = true;
114 break;
115 case DT_TYPE_CREASE:
116 ret = true;
117 break;
119 ret = true;
120 break;
122 *r_threshold = true;
123 ret = true;
124 break;
125 /* Loop/Poly data */
126 case DT_TYPE_UV:
127 ret = true;
128 break;
133 *r_advanced_mixing = true;
134 *r_threshold = true;
135 ret = true;
136 break;
137 case DT_TYPE_LNOR:
138 *r_advanced_mixing = true;
139 ret = true;
140 break;
142 *r_threshold = true;
143 ret = true;
144 break;
146 *r_threshold = true;
147 ret = true;
148 break;
149 }
150 }
151
152 return ret;
153}
154
156{
157 int i, ret = 0;
158
159 for (i = 0; (i < DT_TYPE_MAX) && (ret ^ (ME_VERT | ME_EDGE | ME_LOOP | ME_POLY)); i++) {
160 const int dtdata_type = 1 << i;
161
162 if (!(dtdata_types & dtdata_type)) {
163 continue;
164 }
165
166 if (DT_DATATYPE_IS_VERT(dtdata_type)) {
167 ret |= ME_VERT;
168 }
169 if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
170 ret |= ME_EDGE;
171 }
172 if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
173 ret |= ME_LOOP;
174 }
175 if (DT_DATATYPE_IS_FACE(dtdata_type)) {
176 ret |= ME_POLY;
177 }
178 }
179
180 return ret;
181}
182
184{
185 switch (dtdata_type) {
187 return CD_FAKE_MDEFORMVERT;
188 case DT_TYPE_SHAPEKEY:
189 return CD_FAKE_SHAPEKEY;
190 case DT_TYPE_SKIN:
191 return CD_MVERT_SKIN;
193 return CD_FAKE_BWEIGHT;
194
196 return CD_FAKE_SHARP;
197 case DT_TYPE_SEAM:
198 return CD_FAKE_SEAM;
199 case DT_TYPE_CREASE:
200 return CD_FAKE_CREASE;
202 return CD_FAKE_BWEIGHT;
204 return CD_FREESTYLE_EDGE;
205
206 case DT_TYPE_UV:
207 return CD_FAKE_UV;
209 return CD_FAKE_SHARP;
211 return CD_FREESTYLE_FACE;
212 case DT_TYPE_LNOR:
213 return CD_FAKE_LNOR;
216 return CD_PROP_BYTE_COLOR;
219 return CD_PROP_COLOR;
220 default:
222 }
223 return 0; /* Should never be reached! */
224}
225
247
248/* ********** */
249
256 Mesh *mesh_dst, const Mesh *mesh_src, const AttrDomainMask mask_domain, const int data_type)
257{
258 if (mesh_dst->active_color_attribute) {
259 return;
260 }
261
262 const AttributeOwner owner_src = AttributeOwner::from_id(const_cast<ID *>(&mesh_src->id));
263 AttributeOwner owner_dst = AttributeOwner::from_id(&mesh_dst->id);
264
265 const StringRef active_color_src =
266 BKE_id_attributes_active_color_name(&mesh_src->id).value_or("");
267
268 if ((data_type == CD_PROP_COLOR) &&
270 owner_src, active_color_src, CD_MASK_PROP_COLOR, ATTR_DOMAIN_MASK_COLOR))
271 {
272 return;
273 }
274 if ((data_type == CD_PROP_BYTE_COLOR) &&
276 owner_src, active_color_src, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_COLOR))
277 {
278 return;
279 }
280
281 if ((data_type == CD_PROP_COLOR) &&
283 owner_dst, active_color_src, CD_MASK_PROP_COLOR, ATTR_DOMAIN_MASK_COLOR))
284 {
285 mesh_dst->active_color_attribute = BLI_strdupn(active_color_src.data(),
286 active_color_src.size());
287 }
288 else if ((data_type == CD_PROP_BYTE_COLOR) &&
290 owner_dst, active_color_src, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_COLOR))
291 {
292 mesh_dst->active_color_attribute = BLI_strdupn(active_color_src.data(),
293 active_color_src.size());
294 }
295 else {
296 CustomDataLayer *first_color_layer = BKE_attribute_from_index(
297 owner_dst, 0, mask_domain, CD_MASK_COLOR_ALL);
298 if (first_color_layer != nullptr) {
299 mesh_dst->active_color_attribute = BLI_strdup(first_color_layer->name);
300 }
301 }
302}
303
310 Mesh *mesh_dst, const Mesh *mesh_src, const AttrDomainMask mask_domain, const int data_type)
311{
312 if (mesh_dst->default_color_attribute) {
313 return;
314 }
315
316 const AttributeOwner owner_src = AttributeOwner::from_id(const_cast<ID *>(&mesh_src->id));
317 AttributeOwner owner_dst = AttributeOwner::from_id(&mesh_dst->id);
318
319 const StringRef default_color_src =
320 BKE_id_attributes_default_color_name(&mesh_src->id).value_or("");
321
322 if ((data_type == CD_PROP_COLOR) &&
324 owner_src, default_color_src, CD_MASK_PROP_COLOR, ATTR_DOMAIN_MASK_COLOR))
325 {
326 return;
327 }
328 if ((data_type == CD_PROP_BYTE_COLOR) &&
330 owner_src, default_color_src, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_COLOR))
331 {
332 return;
333 }
334
335 if ((data_type == CD_PROP_COLOR) &&
337 owner_dst, default_color_src, CD_MASK_PROP_COLOR, ATTR_DOMAIN_MASK_COLOR))
338 {
339 mesh_dst->default_color_attribute = BLI_strdupn(default_color_src.data(),
340 default_color_src.size());
341 }
342 else if ((data_type == CD_PROP_BYTE_COLOR) &&
344 owner_dst, default_color_src, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_COLOR))
345 {
346 mesh_dst->default_color_attribute = BLI_strdupn(default_color_src.data(),
347 default_color_src.size());
348 }
349 else {
350 CustomDataLayer *first_color_layer = BKE_attribute_from_index(
351 owner_dst, 0, mask_domain, CD_MASK_COLOR_ALL);
352 if (first_color_layer != nullptr) {
353 mesh_dst->default_color_attribute = BLI_strdup(first_color_layer->name);
354 }
355 }
356}
357
358/* ********** */
359
361 const int dtdata_type,
362 const bool changed)
363{
364 using namespace blender;
365 if (dtdata_type == DT_TYPE_LNOR) {
366 if (!changed) {
367 return;
368 }
369 /* Bake edited destination loop normals into custom normals again. */
370 CustomData *ldata_dst = &me_dst->corner_data;
371
372 blender::float3 *loop_nors_dst = static_cast<blender::float3 *>(
374
375 bke::MutableAttributeAccessor attributes = me_dst->attributes_for_write();
377 "custom_normal", bke::AttrDomain::Corner);
378 if (!custom_nors_dst) {
379 return;
380 }
382 "sharp_edge", bke::AttrDomain::Edge);
383 const VArraySpan sharp_faces = *attributes.lookup<bool>("sharp_face", bke::AttrDomain::Face);
384 /* Note loop_nors_dst contains our custom normals as transferred from source... */
385 blender::bke::mesh::normals_corner_custom_set(me_dst->vert_positions(),
386 me_dst->faces(),
387 me_dst->corner_verts(),
388 me_dst->corner_edges(),
389 me_dst->vert_to_face_map(),
390 me_dst->vert_normals(),
391 me_dst->face_normals_true(),
392 sharp_faces,
393 sharp_edges.span,
394 {loop_nors_dst, me_dst->corners_num},
395 custom_nors_dst.span);
396 custom_nors_dst.finish();
397 sharp_edges.finish();
399 }
400}
401
402/* ********** */
403
405{
406 switch (cddata_type) {
407 case CD_FAKE_UV:
409 default:
410 break;
411 }
412 return nullptr;
413}
414
415float data_transfer_interp_float_do(const int mix_mode,
416 const float val_dst,
417 const float val_src,
418 const float mix_factor)
419{
420 float val_ret;
421
422 if ((mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && (val_dst < mix_factor)) ||
423 (mix_mode == CDT_MIX_REPLACE_BELOW_THRESHOLD && (val_dst > mix_factor)))
424 {
425 return val_dst; /* Do not affect destination. */
426 }
427
428 switch (mix_mode) {
431 return val_src;
432 case CDT_MIX_MIX:
433 val_ret = (val_dst + val_src) * 0.5f;
434 break;
435 case CDT_MIX_ADD:
436 val_ret = val_dst + val_src;
437 break;
438 case CDT_MIX_SUB:
439 val_ret = val_dst - val_src;
440 break;
441 case CDT_MIX_MUL:
442 val_ret = val_dst * val_src;
443 break;
444 case CDT_MIX_TRANSFER:
445 default:
446 val_ret = val_src;
447 break;
448 }
449 return interpf(val_ret, val_dst, mix_factor);
450}
451
452/* Helpers to match sources and destinations data layers
453 * (also handles 'conversions' in CD_FAKE cases). */
454
456 const int cddata_type,
457 const int mix_mode,
458 const float mix_factor,
459 const float *mix_weights,
460 const void *data_src,
461 void *data_dst,
462 const int data_src_n,
463 const int data_dst_n,
464 const size_t elem_size,
465 const size_t data_size,
466 const size_t data_offset,
467 const uint64_t data_flag,
469 void *interp_data)
470{
472
473 BLI_assert(data_dst != nullptr);
474
475 item->data_type = eCustomDataType(cddata_type);
476 item->mix_mode = mix_mode;
477 item->mix_factor = mix_factor;
478 item->mix_weights = mix_weights;
479
480 item->data_src = data_src;
481 item->data_dst = data_dst;
482 item->data_src_n = data_src_n;
483 item->data_dst_n = data_dst_n;
484 item->elem_size = elem_size;
485
486 item->data_size = data_size;
487 item->data_offset = data_offset;
488 item->data_flag = data_flag;
489
490 item->interp = interp;
491 item->interp_data = interp_data;
492
493 BLI_addtail(r_map, item);
494}
495
497 const int cddata_type,
498 const int mix_mode,
499 const float mix_factor,
500 const float *mix_weights,
501 const void *data_src,
502 void *data_dst,
504 void *interp_data)
505{
506 uint64_t data_flag = 0;
507
508 if (cddata_type == CD_FREESTYLE_EDGE) {
509 data_flag = FREESTYLE_EDGE_MARK;
510 }
511 else if (cddata_type == CD_FREESTYLE_FACE) {
512 data_flag = FREESTYLE_FACE_MARK;
513 }
514
516 cddata_type,
517 mix_mode,
518 mix_factor,
519 mix_weights,
520 data_src,
521 data_dst,
522 0,
523 0,
524 0,
525 0,
526 0,
527 data_flag,
528 interp,
529 interp_data);
530}
531
540 const eCustomDataType cddata_type,
541 const int mix_mode,
542 const float mix_factor,
543 const float *mix_weights,
544 const int num_elem_dst,
545 const bool use_create,
546 const bool use_delete,
547 const CustomData *cd_src,
548 CustomData *cd_dst,
549 const int tolayers,
550 const bool *use_layers_src,
551 const int num_layers_src,
553 void *interp_data)
554{
555 const void *data_src;
556 void *data_dst = nullptr;
557 int idx_src = num_layers_src;
558 int idx_dst, tot_dst = CustomData_number_of_layers(cd_dst, cddata_type);
559 bool *data_dst_to_delete = nullptr;
560
561 if (!use_layers_src) {
562 /* No source at all, we can only delete all destination if requested. */
563 if (use_delete) {
564 idx_dst = tot_dst;
565 while (idx_dst--) {
566 CustomData_free_layer(cd_dst, cddata_type, idx_dst);
567 }
568 }
569 return true;
570 }
571
572 switch (tolayers) {
574 idx_dst = tot_dst;
575
576 /* Find last source actually used! */
577 while (idx_src-- && !use_layers_src[idx_src]) {
578 /* pass */
579 }
580 idx_src++;
581
582 if (idx_dst < idx_src) {
583 if (use_create) {
584 /* Create as much data layers as necessary! */
585 for (; idx_dst < idx_src; idx_dst++) {
587 cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst);
588 }
589 }
590 else {
591 /* Otherwise, just try to map what we can with existing dst data layers. */
592 idx_src = idx_dst;
593 }
594 }
595 else if (use_delete && idx_dst > idx_src) {
596 while (idx_dst-- > idx_src) {
597 CustomData_free_layer(cd_dst, cddata_type, idx_dst);
598 }
599 }
600 if (r_map) {
601 while (idx_src--) {
602 if (!use_layers_src[idx_src]) {
603 continue;
604 }
605 data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src);
606 data_dst = CustomData_get_layer_n_for_write(cd_dst, cddata_type, idx_src, num_elem_dst);
608 cddata_type,
609 mix_mode,
610 mix_factor,
611 mix_weights,
612 data_src,
613 data_dst,
614 interp,
615 interp_data);
616 }
617 }
618 break;
620 if (use_delete) {
621 if (tot_dst) {
622 data_dst_to_delete = MEM_malloc_arrayN<bool>(size_t(tot_dst), __func__);
623 memset(data_dst_to_delete, true, sizeof(*data_dst_to_delete) * size_t(tot_dst));
624 }
625 }
626
627 while (idx_src--) {
628 const char *name;
629
630 if (!use_layers_src[idx_src]) {
631 continue;
632 }
633
634 name = CustomData_get_layer_name(cd_src, cddata_type, idx_src);
635 data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src);
636 idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name);
637 if (idx_dst == -1) {
638 if (use_create) {
640 cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst, name);
641 idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name);
642 }
643 else {
644 /* If we are not allowed to create missing dst data layers,
645 * just skip matching src one. */
646 continue;
647 }
648 }
649 else if (data_dst_to_delete) {
650 data_dst_to_delete[idx_dst] = false;
651 }
652 if (r_map) {
653 data_dst = CustomData_get_layer_n_for_write(cd_dst, cddata_type, idx_dst, num_elem_dst);
655 cddata_type,
656 mix_mode,
657 mix_factor,
658 mix_weights,
659 data_src,
660 data_dst,
661 interp,
662 interp_data);
663 }
664 }
665
666 if (data_dst_to_delete) {
667 /* NOTE:
668 * This won't affect newly created layers, if any, since tot_dst has not been updated!
669 * Also, looping backward ensures us we do not suffer
670 * from index shifting when deleting a layer. */
671 for (idx_dst = tot_dst; idx_dst--;) {
672 if (data_dst_to_delete[idx_dst]) {
673 CustomData_free_layer(cd_dst, cddata_type, idx_dst);
674 }
675 }
676
677 MEM_freeN(data_dst_to_delete);
678 }
679 break;
680 default:
681 return false;
682 }
683
684 return true;
685}
686
688 const eCustomDataType cddata_type,
689 const int mix_mode,
690 const float mix_factor,
691 const float *mix_weights,
692 const int num_elem_dst,
693 const bool use_create,
694 const bool use_delete,
695 const CustomData *cd_src,
696 CustomData *cd_dst,
697 const int fromlayers,
698 const int tolayers,
700 void *interp_data)
701{
702 void *data_dst = nullptr;
703
704 if (CustomData_layertype_is_singleton(cddata_type)) {
705 const void *data_src = CustomData_get_layer(cd_src, cddata_type);
706 if (!data_src) {
707 if (use_delete) {
708 CustomData_free_layer(cd_dst, cddata_type, 0);
709 }
710 return true;
711 }
712
713 data_dst = CustomData_get_layer_for_write(cd_dst, cddata_type, num_elem_dst);
714 if (!data_dst) {
715 if (!use_create) {
716 return true;
717 }
718 data_dst = CustomData_add_layer(
719 cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst);
720 }
721
722 if (r_map) {
724 cddata_type,
725 mix_mode,
726 mix_factor,
727 mix_weights,
728 data_src,
729 data_dst,
730 interp,
731 interp_data);
732 }
733 }
734 else if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) {
735 /* NOTE: use_delete has not much meaning in this case, ignored. */
736
737 int idx_src;
738 if (fromlayers >= 0) { /* Real-layer index */
739 idx_src = fromlayers;
740 }
741 else {
742 idx_src = CustomData_get_active_layer(cd_src, cddata_type);
743 if (idx_src == -1) {
744 return true;
745 }
746 }
747 const void *data_src = CustomData_get_layer_n(cd_src, cddata_type, idx_src);
748 if (!data_src) {
749 return true;
750 }
751
752 int idx_dst;
753 if (tolayers >= 0) { /* Real-layer index */
754 idx_dst = tolayers;
755 data_dst = CustomData_get_layer_n_for_write(cd_dst, cddata_type, idx_dst, num_elem_dst);
756 }
757 else if (tolayers == DT_LAYERS_ACTIVE_DST) {
758 idx_dst = CustomData_get_active_layer(cd_dst, cddata_type);
759 if (idx_dst == -1) {
760 if (!use_create) {
761 return true;
762 }
763 data_dst = CustomData_add_layer(
764 cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst);
765 }
766 else {
767 data_dst = CustomData_get_layer_n_for_write(cd_dst, cddata_type, idx_dst, num_elem_dst);
768 }
769 }
770 else if (tolayers == DT_LAYERS_INDEX_DST) {
771 int num = CustomData_number_of_layers(cd_dst, cddata_type);
772 idx_dst = idx_src;
773 if (num <= idx_dst) {
774 if (!use_create) {
775 return true;
776 }
777 /* Create as much data layers as necessary! */
778 for (; num <= idx_dst; num++) {
779 CustomData_add_layer(cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst);
780 }
781 }
782 data_dst = CustomData_get_layer_n_for_write(cd_dst, cddata_type, idx_dst, num_elem_dst);
783 }
784 else if (tolayers == DT_LAYERS_NAME_DST) {
785 const char *name = CustomData_get_layer_name(cd_src, cddata_type, idx_src);
786 idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name);
787 if (idx_dst == -1) {
788 if (!use_create) {
789 return true;
790 }
792 cd_dst, eCustomDataType(cddata_type), CD_SET_DEFAULT, num_elem_dst, name);
793 idx_dst = CustomData_get_named_layer(cd_dst, cddata_type, name);
794 }
795 data_dst = CustomData_get_layer_n_for_write(cd_dst, cddata_type, idx_dst, num_elem_dst);
796 }
797 else {
798 return false;
799 }
800
801 if (!data_dst) {
802 return false;
803 }
804
805 if (r_map) {
807 cddata_type,
808 mix_mode,
809 mix_factor,
810 mix_weights,
811 data_src,
812 data_dst,
813 interp,
814 interp_data);
815 }
816 }
817 else if (fromlayers == DT_LAYERS_ALL_SRC) {
818 int num_src = CustomData_number_of_layers(cd_src, eCustomDataType(cddata_type));
819 bool *use_layers_src = num_src ? MEM_malloc_arrayN<bool>(size_t(num_src), __func__) : nullptr;
820 bool ret;
821
822 if (use_layers_src) {
823 memset(use_layers_src, true, sizeof(*use_layers_src) * num_src);
824 }
825
827 cddata_type,
828 mix_mode,
829 mix_factor,
830 mix_weights,
831 num_elem_dst,
832 use_create,
833 use_delete,
834 cd_src,
835 cd_dst,
836 tolayers,
837 use_layers_src,
838 num_src,
839 interp,
840 interp_data);
841
842 if (use_layers_src) {
843 MEM_freeN(use_layers_src);
844 }
845 return ret;
846 }
847 else {
848 return false;
849 }
850
851 return true;
852}
853
855 Object *ob_src,
856 Object *ob_dst,
857 const Mesh *me_src,
858 Mesh *me_dst,
859 const int elem_type,
860 int cddata_type,
861 int mix_mode,
862 float mix_factor,
863 const float *mix_weights,
864 const int num_elem_dst,
865 const bool use_create,
866 const bool use_delete,
867 const int fromlayers,
868 const int tolayers,
869 SpaceTransform *space_transform)
870{
871 using namespace blender;
872 const CustomData *cd_src;
873 CustomData *cd_dst;
874
876 void *interp_data = nullptr;
877
878 if (elem_type == ME_VERT) {
879 if (!(cddata_type & CD_FAKE)) {
880 cd_src = &me_src->vert_data;
881 cd_dst = &me_dst->vert_data;
882
884 eCustomDataType(cddata_type),
885 mix_mode,
886 mix_factor,
887 mix_weights,
888 num_elem_dst,
889 use_create,
890 use_delete,
891 cd_src,
892 cd_dst,
893 fromlayers,
894 tolayers,
895 interp,
896 interp_data))
897 {
898 /* We handle specific source selection cases here. */
899 return false;
900 }
901 return true;
902 }
903 if (cddata_type == CD_FAKE_MDEFORMVERT) {
904 bool ret;
905
906 cd_src = &me_src->vert_data;
907 cd_dst = &me_dst->vert_data;
908
910 mix_mode,
911 mix_factor,
912 mix_weights,
913 num_elem_dst,
914 use_create,
915 use_delete,
916 ob_src,
917 ob_dst,
918 cd_src,
919 cd_dst,
920 me_dst != ob_dst->data,
921 fromlayers,
922 tolayers);
923 return ret;
924 }
925 if (cddata_type == CD_FAKE_SHAPEKEY) {
926 /* TODO: leaving shape-keys aside for now, quite specific case,
927 * since we can't access them from mesh vertices :/ */
928 return false;
929 }
930 if (r_map && cddata_type == CD_FAKE_BWEIGHT) {
931 if (!CustomData_get_layer_named(&me_dst->vert_data, CD_PROP_FLOAT, "bevel_weight_vert")) {
935 me_dst->verts_num,
936 "bevel_weight_vert");
937 }
939 r_map,
941 mix_mode,
942 mix_factor,
943 mix_weights,
944 CustomData_get_layer_named(&me_src->vert_data, CD_PROP_FLOAT, "bevel_weight_vert"),
946 &me_dst->vert_data, CD_PROP_FLOAT, "bevel_weight_vert", me_dst->verts_num),
947 interp,
948 interp_data);
949 return true;
950 }
951 }
952 else if (elem_type == ME_EDGE) {
953 if (!(cddata_type & CD_FAKE)) { /* Unused for edges, currently... */
954 cd_src = &me_src->edge_data;
955 cd_dst = &me_dst->edge_data;
956
958 eCustomDataType(cddata_type),
959 mix_mode,
960 mix_factor,
961 mix_weights,
962 num_elem_dst,
963 use_create,
964 use_delete,
965 cd_src,
966 cd_dst,
967 fromlayers,
968 tolayers,
969 interp,
970 interp_data))
971 {
972 /* We handle specific source selection cases here. */
973 return false;
974 }
975 return true;
976 }
977 if (r_map && cddata_type == CD_FAKE_SEAM) {
978 if (!CustomData_has_layer_named(&me_dst->edge_data, CD_PROP_BOOL, "uv_seam")) {
980 &me_dst->edge_data, CD_PROP_BOOL, CD_SET_DEFAULT, me_dst->edges_num, "uv_seam");
981 }
983 r_map,
985 mix_mode,
986 mix_factor,
987 mix_weights,
990 &me_dst->edge_data, CD_PROP_BOOL, "uv_seam", me_dst->edges_num),
991 interp,
992 interp_data);
993 return true;
994 }
995 if (r_map && cddata_type == CD_FAKE_SHARP) {
996 if (!CustomData_has_layer_named(&me_dst->edge_data, CD_PROP_BOOL, "sharp_edge")) {
998 &me_dst->edge_data, CD_PROP_BOOL, CD_SET_DEFAULT, me_dst->edges_num, "sharp_edge");
999 }
1001 r_map,
1003 mix_mode,
1004 mix_factor,
1005 mix_weights,
1006 CustomData_get_layer_named(&me_src->edge_data, CD_PROP_BOOL, "sharp_edge"),
1008 &me_dst->edge_data, CD_PROP_BOOL, "sharp_edge", me_dst->edges_num),
1009 interp,
1010 interp_data);
1011 return true;
1012 }
1013 if (r_map && cddata_type == CD_FAKE_BWEIGHT) {
1014 if (!CustomData_get_layer_named(&me_dst->edge_data, CD_PROP_FLOAT, "bevel_weight_edge")) {
1018 me_dst->edges_num,
1019 "bevel_weight_edge");
1020 }
1022 r_map,
1024 mix_mode,
1025 mix_factor,
1026 mix_weights,
1027 CustomData_get_layer_named(&me_src->edge_data, CD_PROP_FLOAT, "bevel_weight_edge"),
1029 &me_dst->edge_data, CD_PROP_FLOAT, "bevel_weight_edge", me_dst->edges_num),
1030 interp,
1031 interp_data);
1032 return true;
1033 }
1034 if (r_map && cddata_type == CD_FAKE_CREASE) {
1035 if (!CustomData_get_layer_named(&me_dst->edge_data, CD_PROP_FLOAT, "crease_edge")) {
1037 &me_dst->edge_data, CD_PROP_FLOAT, CD_SET_DEFAULT, me_dst->edges_num, "crease_edge");
1038 }
1040 r_map,
1042 mix_mode,
1043 mix_factor,
1044 mix_weights,
1045 CustomData_get_layer_named(&me_src->edge_data, CD_PROP_FLOAT, "crease_edge"),
1047 &me_dst->edge_data, CD_PROP_FLOAT, "crease_edge", me_dst->edges_num),
1048 interp,
1049 interp_data);
1050 return true;
1051 }
1052
1053 return false;
1054 }
1055 else if (elem_type == ME_LOOP) {
1056 if (cddata_type == CD_FAKE_UV) {
1057 cddata_type = CD_PROP_FLOAT2;
1058 }
1059 else if (cddata_type == CD_FAKE_LNOR) {
1060 if (r_map) {
1061 /* Use #CD_NORMAL as a temporary storage for custom normals in 3D vector form.
1062 * A post-process step will convert this layer to "custom_normal". */
1063 float3 *dst_data = static_cast<float3 *>(
1065 if (!dst_data) {
1066 dst_data = static_cast<float3 *>(CustomData_add_layer(
1067 &me_dst->corner_data, CD_NORMAL, CD_SET_DEFAULT, me_dst->corners_num));
1068 }
1069 if (mix_factor != 1.0f || mix_weights) {
1070 MutableSpan(dst_data, me_dst->corners_num).copy_from(me_dst->corner_normals());
1071 }
1072 /* Post-process will convert it back to "custom_normal". */
1074 CD_NORMAL,
1075 mix_mode,
1076 mix_factor,
1077 mix_weights,
1078 me_src->corner_normals().data(),
1079 dst_data,
1081 space_transform);
1082 }
1083 return true;
1084 }
1085
1086 if (!(cddata_type & CD_FAKE)) {
1087 cd_src = &me_src->corner_data;
1088 cd_dst = &me_dst->corner_data;
1089
1091 eCustomDataType(cddata_type),
1092 mix_mode,
1093 mix_factor,
1094 mix_weights,
1095 num_elem_dst,
1096 use_create,
1097 use_delete,
1098 cd_src,
1099 cd_dst,
1100 fromlayers,
1101 tolayers,
1102 interp,
1103 interp_data))
1104 {
1105 /* We handle specific source selection cases here. */
1106 return false;
1107 }
1108 return true;
1109 }
1110
1111 return false;
1112 }
1113 else if (elem_type == ME_POLY) {
1114 if (cddata_type == CD_FAKE_UV) {
1115 cddata_type = CD_PROP_FLOAT2;
1116 }
1117
1118 if (!(cddata_type & CD_FAKE)) {
1119 cd_src = &me_src->face_data;
1120 cd_dst = &me_dst->face_data;
1121
1123 eCustomDataType(cddata_type),
1124 mix_mode,
1125 mix_factor,
1126 mix_weights,
1127 num_elem_dst,
1128 use_create,
1129 use_delete,
1130 cd_src,
1131 cd_dst,
1132 fromlayers,
1133 tolayers,
1134 interp,
1135 interp_data))
1136 {
1137 /* We handle specific source selection cases here. */
1138 return false;
1139 }
1140 return true;
1141 }
1142 if (r_map && cddata_type == CD_FAKE_SHARP) {
1143 if (!CustomData_has_layer_named(&me_dst->face_data, CD_PROP_BOOL, "sharp_face")) {
1145 &me_dst->face_data, CD_PROP_BOOL, CD_SET_DEFAULT, me_dst->faces_num, "sharp_face");
1146 }
1148 r_map,
1150 mix_mode,
1151 mix_factor,
1152 mix_weights,
1153 CustomData_get_layer_named(&me_src->face_data, CD_PROP_BOOL, "sharp_face"),
1155 &me_dst->face_data, CD_PROP_BOOL, "sharp_face", num_elem_dst),
1156 interp,
1157 interp_data);
1158 return true;
1159 }
1160
1161 return false;
1162 }
1163
1164 return false;
1165}
1166
1168 Object *ob_src,
1169 Object *ob_dst,
1170 const int data_types,
1171 const bool use_delete,
1172 const int fromlayers_select[DT_MULTILAYER_INDEX_MAX],
1173 const int tolayers_select[DT_MULTILAYER_INDEX_MAX])
1174{
1175 Mesh *me_dst;
1176
1177 const bool use_create = true; /* We always create needed layers here. */
1178
1179 BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH));
1180
1181 me_dst = static_cast<Mesh *>(ob_dst->data);
1182
1183 /* Get source evaluated mesh. */
1184 const Object *ob_src_eval = DEG_get_evaluated(depsgraph, ob_src);
1185 const Mesh *me_src = BKE_object_get_evaluated_mesh(ob_src_eval);
1186 if (!me_src) {
1187 return;
1188 }
1189
1190 /* Check all possible data types. */
1191 for (int i = 0; i < DT_TYPE_MAX; i++) {
1192 const int dtdata_type = 1 << i;
1193 int cddata_type;
1194 int fromlayers, tolayers, fromto_idx;
1195
1196 if (!(data_types & dtdata_type)) {
1197 continue;
1198 }
1199
1200 cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type);
1201
1202 fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type);
1203
1204 if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
1205 fromlayers = fromlayers_select[fromto_idx];
1206 tolayers = tolayers_select[fromto_idx];
1207 }
1208 else {
1209 fromlayers = tolayers = 0;
1210 }
1211
1212 if (DT_DATATYPE_IS_VERT(dtdata_type)) {
1213 const int num_elem_dst = me_dst->verts_num;
1214
1216 ob_src,
1217 ob_dst,
1218 me_src,
1219 me_dst,
1220 ME_VERT,
1221 cddata_type,
1222 0,
1223 0.0f,
1224 nullptr,
1225 num_elem_dst,
1226 use_create,
1227 use_delete,
1228 fromlayers,
1229 tolayers,
1230 nullptr);
1231 /* Make sure we have active/default color layers if none existed before.
1232 * Use the active/default from src (if it was transferred), otherwise the first. */
1233 if (ELEM(cddata_type, CD_PROP_COLOR, CD_PROP_BYTE_COLOR)) {
1235 me_dst, me_src, ATTR_DOMAIN_MASK_POINT, cddata_type);
1237 me_dst, me_src, ATTR_DOMAIN_MASK_POINT, cddata_type);
1238 }
1239 }
1240 if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
1241 const int num_elem_dst = me_dst->edges_num;
1242
1244 ob_src,
1245 ob_dst,
1246 me_src,
1247 me_dst,
1248 ME_EDGE,
1249 cddata_type,
1250 0,
1251 0.0f,
1252 nullptr,
1253 num_elem_dst,
1254 use_create,
1255 use_delete,
1256 fromlayers,
1257 tolayers,
1258 nullptr);
1259 }
1260 if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
1261 const int num_elem_dst = me_dst->corners_num;
1262
1264 ob_src,
1265 ob_dst,
1266 me_src,
1267 me_dst,
1268 ME_LOOP,
1269 cddata_type,
1270 0,
1271 0.0f,
1272 nullptr,
1273 num_elem_dst,
1274 use_create,
1275 use_delete,
1276 fromlayers,
1277 tolayers,
1278 nullptr);
1279 /* Make sure we have active/default color layers if none existed before.
1280 * Use the active/default from src (if it was transferred), otherwise the first. */
1281 if (ELEM(cddata_type, CD_PROP_COLOR, CD_PROP_BYTE_COLOR)) {
1283 me_dst, me_src, ATTR_DOMAIN_MASK_CORNER, cddata_type);
1285 me_dst, me_src, ATTR_DOMAIN_MASK_CORNER, cddata_type);
1286 }
1287 }
1288 if (DT_DATATYPE_IS_FACE(dtdata_type)) {
1289 const int num_elem_dst = me_dst->faces_num;
1290
1292 ob_src,
1293 ob_dst,
1294 me_src,
1295 me_dst,
1296 ME_POLY,
1297 cddata_type,
1298 0,
1299 0.0f,
1300 nullptr,
1301 num_elem_dst,
1302 use_create,
1303 use_delete,
1304 fromlayers,
1305 tolayers,
1306 nullptr);
1307 }
1308 }
1309}
1310
1312 Object *ob_src,
1313 Object *ob_dst,
1314 Mesh *me_dst,
1315 const int data_types,
1316 bool use_create,
1317 const int map_vert_mode,
1318 const int map_edge_mode,
1319 const int map_loop_mode,
1320 const int map_face_mode,
1321 SpaceTransform *space_transform,
1322 const bool auto_transform,
1323 const float max_distance,
1324 const float ray_radius,
1325 const float islands_handling_precision,
1326 const int fromlayers_select[DT_MULTILAYER_INDEX_MAX],
1327 const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
1328 const int mix_mode,
1329 const float mix_factor,
1330 const char *vgroup_name,
1331 const bool invert_vgroup,
1333{
1334#define VDATA 0
1335#define EDATA 1
1336#define LDATA 2
1337#define PDATA 3
1338#define DATAMAX 4
1339
1340 SpaceTransform auto_space_transform;
1341
1342 const Mesh *me_src;
1343
1344 const MDeformVert *mdef = nullptr;
1345 int vg_idx = -1;
1346 float *weights[DATAMAX] = {nullptr};
1347
1348 MeshPairRemap geom_map[DATAMAX] = {{0}};
1349 bool geom_map_init[DATAMAX] = {false};
1350 ListBase lay_map = {nullptr};
1351 bool changed = false;
1352 bool is_modifier = false;
1353
1354 const bool use_delete = false; /* We never delete data layers from destination here. */
1355
1356 BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH));
1357
1358 if (me_dst) {
1359 /* Never create needed custom layers on passed destination mesh
1360 * (assumed to *not* be ob_dst->data, aka modifier case). */
1361 use_create = false;
1362 is_modifier = true;
1363 }
1364 else {
1365 me_dst = static_cast<Mesh *>(ob_dst->data);
1366 }
1367
1368 if (vgroup_name) {
1369 mdef = static_cast<const MDeformVert *>(
1371 if (mdef) {
1372 vg_idx = BKE_id_defgroup_name_index(&me_dst->id, vgroup_name);
1373 }
1374 }
1375
1376 /* Get source evaluated mesh. */
1377 if (is_modifier) {
1379 }
1380 else {
1381 const Object *ob_eval = DEG_get_evaluated(depsgraph, ob_src);
1382 me_src = BKE_object_get_evaluated_mesh(ob_eval);
1383 }
1384 if (!me_src) {
1385 return changed;
1386 }
1387 BKE_mesh_wrapper_ensure_mdata(const_cast<Mesh *>(me_src));
1388
1389 if (auto_transform) {
1390 if (space_transform == nullptr) {
1391 space_transform = &auto_space_transform;
1392 }
1393
1395 reinterpret_cast<const float(*)[3]>(me_dst->vert_positions().data()),
1396 me_dst->verts_num,
1397 me_src,
1398 space_transform);
1399 }
1400
1401 /* Check all possible data types.
1402 * Note item mappings and destination mix weights are cached. */
1403 for (int i = 0; i < DT_TYPE_MAX; i++) {
1404 const int dtdata_type = 1 << i;
1405 int cddata_type;
1406 int fromlayers, tolayers, fromto_idx;
1407
1408 if (!(data_types & dtdata_type)) {
1409 continue;
1410 }
1411
1412 cddata_type = BKE_object_data_transfer_dttype_to_cdtype(dtdata_type);
1413
1414 fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(dtdata_type);
1415 if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
1416 fromlayers = fromlayers_select[fromto_idx];
1417 tolayers = tolayers_select[fromto_idx];
1418 }
1419 else {
1420 fromlayers = tolayers = 0;
1421 }
1422
1423 if (DT_DATATYPE_IS_VERT(dtdata_type)) {
1424 blender::MutableSpan<blender::float3> positions_dst = me_dst->vert_positions_for_write();
1425 const int num_verts_dst = me_dst->verts_num;
1426
1427 if (!geom_map_init[VDATA]) {
1428 const int num_verts_src = me_src->verts_num;
1429
1430 if ((map_vert_mode == MREMAP_MODE_TOPOLOGY) && (num_verts_dst != num_verts_src)) {
1432 RPT_ERROR,
1433 "Source and destination meshes do not have the same number of vertices, "
1434 "'Topology' mapping cannot be used in this case");
1435 continue;
1436 }
1437 if ((map_vert_mode & MREMAP_USE_EDGE) && (me_src->edges_num == 0)) {
1439 RPT_ERROR,
1440 "Source mesh does not have any edges, "
1441 "none of the 'Edge' mappings can be used in this case");
1442 continue;
1443 }
1444 if ((map_vert_mode & MREMAP_USE_POLY) && (me_src->faces_num == 0)) {
1446 RPT_ERROR,
1447 "Source mesh does not have any faces, "
1448 "none of the 'Face' mappings can be used in this case");
1449 continue;
1450 }
1451 if (ELEM(0, num_verts_dst, num_verts_src)) {
1453 RPT_ERROR,
1454 "Source or destination meshes do not have any vertices, cannot transfer "
1455 "vertex data");
1456 continue;
1457 }
1458
1460 map_vert_mode,
1461 space_transform,
1462 max_distance,
1463 ray_radius,
1464 reinterpret_cast<const float(*)[3]>(positions_dst.data()),
1465 num_verts_dst,
1466 me_src,
1467 me_dst,
1468 &geom_map[VDATA]);
1469 geom_map_init[VDATA] = true;
1470 }
1471
1472 if (mdef && vg_idx != -1 && !weights[VDATA]) {
1473 weights[VDATA] = MEM_malloc_arrayN<float>(size_t(num_verts_dst), __func__);
1475 mdef, vg_idx, num_verts_dst, invert_vgroup, weights[VDATA]);
1476 }
1477
1479 ob_src,
1480 ob_dst,
1481 me_src,
1482 me_dst,
1483 ME_VERT,
1484 cddata_type,
1485 mix_mode,
1486 mix_factor,
1487 weights[VDATA],
1488 num_verts_dst,
1489 use_create,
1490 use_delete,
1491 fromlayers,
1492 tolayers,
1493 space_transform))
1494 {
1495 changed |= (lay_map.first != nullptr);
1496
1497 LISTBASE_FOREACH (CustomDataTransferLayerMap *, lay_mapit, &lay_map) {
1498 CustomData_data_transfer(&geom_map[VDATA], lay_mapit);
1499 }
1500
1501 BLI_freelistN(&lay_map);
1502 }
1503 }
1504 if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
1505 blender::MutableSpan<blender::float3> positions_dst = me_dst->vert_positions_for_write();
1506
1507 const int num_verts_dst = me_dst->verts_num;
1508 const blender::Span<blender::int2> edges_dst = me_dst->edges();
1509
1510 if (!geom_map_init[EDATA]) {
1511 const int num_edges_src = me_src->edges_num;
1512
1513 if ((map_edge_mode == MREMAP_MODE_TOPOLOGY) && (edges_dst.size() != num_edges_src)) {
1515 RPT_ERROR,
1516 "Source and destination meshes do not have the same number of edges, "
1517 "'Topology' mapping cannot be used in this case");
1518 continue;
1519 }
1520 if ((map_edge_mode & MREMAP_USE_POLY) && (me_src->faces_num == 0)) {
1522 RPT_ERROR,
1523 "Source mesh does not have any faces, "
1524 "none of the 'Face' mappings can be used in this case");
1525 continue;
1526 }
1527 if (ELEM(0, edges_dst.size(), num_edges_src)) {
1528 BKE_report(
1529 reports,
1530 RPT_ERROR,
1531 "Source or destination meshes do not have any edges, cannot transfer edge data");
1532 continue;
1533 }
1534
1536 map_edge_mode,
1537 space_transform,
1538 max_distance,
1539 ray_radius,
1540 reinterpret_cast<const float(*)[3]>(positions_dst.data()),
1541 num_verts_dst,
1542 edges_dst.data(),
1543 edges_dst.size(),
1544 me_src,
1545 me_dst,
1546 &geom_map[EDATA]);
1547 geom_map_init[EDATA] = true;
1548 }
1549
1550 if (mdef && vg_idx != -1 && !weights[EDATA]) {
1551 weights[EDATA] = MEM_malloc_arrayN<float>(size_t(edges_dst.size()), __func__);
1553 vg_idx,
1554 num_verts_dst,
1555 edges_dst.data(),
1556 edges_dst.size(),
1557 invert_vgroup,
1558 weights[EDATA]);
1559 }
1560
1562 ob_src,
1563 ob_dst,
1564 me_src,
1565 me_dst,
1566 ME_EDGE,
1567 cddata_type,
1568 mix_mode,
1569 mix_factor,
1570 weights[EDATA],
1571 edges_dst.size(),
1572 use_create,
1573 use_delete,
1574 fromlayers,
1575 tolayers,
1576 space_transform))
1577 {
1578 changed |= (lay_map.first != nullptr);
1579
1580 LISTBASE_FOREACH (CustomDataTransferLayerMap *, lay_mapit, &lay_map) {
1581 CustomData_data_transfer(&geom_map[EDATA], lay_mapit);
1582 }
1583
1584 BLI_freelistN(&lay_map);
1585 }
1586 }
1587 if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
1588 const blender::Span<blender::float3> positions_dst = me_dst->vert_positions();
1589 const int num_verts_dst = me_dst->verts_num;
1590 const blender::OffsetIndices faces_dst = me_dst->faces();
1591 const blender::Span<int> corner_verts_dst = me_dst->corner_verts();
1592
1594
1595 if (!geom_map_init[LDATA]) {
1596 const int num_loops_src = me_src->corners_num;
1597
1598 if ((map_loop_mode == MREMAP_MODE_TOPOLOGY) && (corner_verts_dst.size() != num_loops_src))
1599 {
1601 RPT_ERROR,
1602 "Source and destination meshes do not have the same number of face corners, "
1603 "'Topology' mapping cannot be used in this case");
1604 continue;
1605 }
1606 if ((map_loop_mode & MREMAP_USE_EDGE) && (me_src->edges_num == 0)) {
1608 RPT_ERROR,
1609 "Source mesh does not have any edges, "
1610 "none of the 'Edge' mappings can be used in this case");
1611 continue;
1612 }
1613 if (ELEM(0, corner_verts_dst.size(), num_loops_src)) {
1614 BKE_report(
1615 reports,
1616 RPT_ERROR,
1617 "Source or destination meshes do not have any faces, cannot transfer corner data");
1618 continue;
1619 }
1620
1622 map_loop_mode,
1623 space_transform,
1624 max_distance,
1625 ray_radius,
1626 me_dst,
1627 reinterpret_cast<const float(*)[3]>(positions_dst.data()),
1628 num_verts_dst,
1629 corner_verts_dst.data(),
1630 corner_verts_dst.size(),
1631 faces_dst,
1632 me_src,
1633 island_callback,
1634 islands_handling_precision,
1635 &geom_map[LDATA]);
1636 geom_map_init[LDATA] = true;
1637 }
1638
1639 if (mdef && vg_idx != -1 && !weights[LDATA]) {
1640 weights[LDATA] = MEM_malloc_arrayN<float>(size_t(corner_verts_dst.size()), __func__);
1642 vg_idx,
1643 num_verts_dst,
1644 corner_verts_dst.data(),
1645 corner_verts_dst.size(),
1646 invert_vgroup,
1647 weights[LDATA]);
1648 }
1649
1651 ob_src,
1652 ob_dst,
1653 me_src,
1654 me_dst,
1655 ME_LOOP,
1656 cddata_type,
1657 mix_mode,
1658 mix_factor,
1659 weights[LDATA],
1660 corner_verts_dst.size(),
1661 use_create,
1662 use_delete,
1663 fromlayers,
1664 tolayers,
1665 space_transform))
1666 {
1667 changed |= (lay_map.first != nullptr);
1668
1669 LISTBASE_FOREACH (CustomDataTransferLayerMap *, lay_mapit, &lay_map) {
1670 CustomData_data_transfer(&geom_map[LDATA], lay_mapit);
1671 }
1672
1673 BLI_freelistN(&lay_map);
1674 }
1675 }
1676 if (DT_DATATYPE_IS_FACE(dtdata_type)) {
1677 const blender::Span<blender::float3> positions_dst = me_dst->vert_positions();
1678 const int num_verts_dst = me_dst->verts_num;
1679 const blender::OffsetIndices faces_dst = me_dst->faces();
1680 const blender::Span<int> corner_verts_dst = me_dst->corner_verts();
1681
1682 if (!geom_map_init[PDATA]) {
1683 const int num_faces_src = me_src->faces_num;
1684
1685 if ((map_face_mode == MREMAP_MODE_TOPOLOGY) && (faces_dst.size() != num_faces_src)) {
1687 RPT_ERROR,
1688 "Source and destination meshes do not have the same number of faces, "
1689 "'Topology' mapping cannot be used in this case");
1690 continue;
1691 }
1692 if ((map_face_mode & MREMAP_USE_EDGE) && (me_src->edges_num == 0)) {
1694 RPT_ERROR,
1695 "Source mesh does not have any edges, "
1696 "none of the 'Edge' mappings can be used in this case");
1697 continue;
1698 }
1699 if (ELEM(0, faces_dst.size(), num_faces_src)) {
1700 BKE_report(
1701 reports,
1702 RPT_ERROR,
1703 "Source or destination meshes do not have any faces, cannot transfer face data");
1704 continue;
1705 }
1706
1708 map_face_mode,
1709 space_transform,
1710 max_distance,
1711 ray_radius,
1712 me_dst,
1713 reinterpret_cast<const float(*)[3]>(positions_dst.data()),
1714 num_verts_dst,
1715 corner_verts_dst.data(),
1716 faces_dst,
1717 me_src,
1718 &geom_map[PDATA]);
1719 geom_map_init[PDATA] = true;
1720 }
1721
1722 if (mdef && vg_idx != -1 && !weights[PDATA]) {
1723 weights[PDATA] = MEM_malloc_arrayN<float>(size_t(faces_dst.size()), __func__);
1725 vg_idx,
1726 num_verts_dst,
1727 corner_verts_dst.data(),
1728 corner_verts_dst.size(),
1729 faces_dst,
1730 invert_vgroup,
1731 weights[PDATA]);
1732 }
1733
1735 ob_src,
1736 ob_dst,
1737 me_src,
1738 me_dst,
1739 ME_POLY,
1740 cddata_type,
1741 mix_mode,
1742 mix_factor,
1743 weights[PDATA],
1744 faces_dst.size(),
1745 use_create,
1746 use_delete,
1747 fromlayers,
1748 tolayers,
1749 space_transform))
1750 {
1751 changed |= (lay_map.first != nullptr);
1752
1753 LISTBASE_FOREACH (CustomDataTransferLayerMap *, lay_mapit, &lay_map) {
1754 CustomData_data_transfer(&geom_map[PDATA], lay_mapit);
1755 }
1756
1757 BLI_freelistN(&lay_map);
1758 }
1759 }
1760
1761 data_transfer_dtdata_type_postprocess(me_dst, dtdata_type, changed);
1762 }
1763
1764 for (int i = 0; i < DATAMAX; i++) {
1765 BKE_mesh_remap_free(&geom_map[i]);
1766 MEM_SAFE_FREE(weights[i]);
1767 }
1768
1769 return changed;
1770
1771#undef VDATA
1772#undef EDATA
1773#undef LDATA
1774#undef PDATA
1775#undef DATAMAX
1776}
1777
1779 Object *ob_src,
1780 Object *ob_dst,
1781 const int data_types,
1782 const bool use_create,
1783 const int map_vert_mode,
1784 const int map_edge_mode,
1785 const int map_loop_mode,
1786 const int map_face_mode,
1787 SpaceTransform *space_transform,
1788 const bool auto_transform,
1789 const float max_distance,
1790 const float ray_radius,
1791 const float islands_handling_precision,
1792 const int fromlayers_select[DT_MULTILAYER_INDEX_MAX],
1793 const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
1794 const int mix_mode,
1795 const float mix_factor,
1796 const char *vgroup_name,
1797 const bool invert_vgroup,
1799{
1801 ob_src,
1802 ob_dst,
1803 nullptr,
1804 data_types,
1805 use_create,
1806 map_vert_mode,
1807 map_edge_mode,
1808 map_loop_mode,
1809 map_face_mode,
1810 space_transform,
1811 auto_transform,
1812 max_distance,
1813 ray_radius,
1814 islands_handling_precision,
1815 fromlayers_select,
1816 tolayers_select,
1817 mix_mode,
1818 mix_factor,
1819 vgroup_name,
1820 invert_vgroup,
1821 reports);
1822}
std::optional< blender::StringRef > BKE_id_attributes_default_color_name(const struct ID *id)
CustomDataLayer * BKE_attribute_from_index(AttributeOwner &owner, int lookup_index, AttrDomainMask domain_mask, eCustomDataMask layer_mask)
Definition attribute.cc:899
AttrDomainMask
@ ATTR_DOMAIN_MASK_POINT
@ ATTR_DOMAIN_MASK_CORNER
const struct CustomDataLayer * BKE_attribute_search(const AttributeOwner &owner, blender::StringRef name, eCustomDataMask type, AttrDomainMask domain_mask)
Definition attribute.cc:657
std::optional< blender::StringRef > BKE_id_attributes_active_color_name(const struct ID *id)
#define ATTR_DOMAIN_MASK_COLOR
CustomData interface, see also DNA_customdata_types.h.
void * CustomData_get_layer_named_for_write(CustomData *data, eCustomDataType type, blender::StringRef name, int totelem)
const void * CustomData_get_layer_n(const CustomData *data, eCustomDataType type, int n)
int CustomData_get_named_layer(const CustomData *data, eCustomDataType type, blender::StringRef name)
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
@ CD_SET_DEFAULT
const void * CustomData_get_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
void * CustomData_add_layer_named(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem, blender::StringRef name)
bool CustomData_free_layer(CustomData *data, eCustomDataType type, int index)
bool CustomData_has_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
const char * CustomData_get_layer_name(const CustomData *data, eCustomDataType type, int n)
void(*)(const CustomDataTransferLayerMap *laymap, void *dest, const void **sources, const float *weights, int count, float mix_factor) cd_datatransfer_interp
void CustomData_free_layers(CustomData *data, eCustomDataType type)
void CustomData_data_transfer(const MeshPairRemap *me_remap, const CustomDataTransferLayerMap *laymap)
int CustomData_get_active_layer(const CustomData *data, eCustomDataType type)
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
@ ME_VERT
@ ME_POLY
@ ME_LOOP
@ ME_EDGE
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
bool CustomData_layertype_is_singleton(eCustomDataType type)
int CustomData_number_of_layers(const CustomData *data, eCustomDataType type)
void * CustomData_get_layer_n_for_write(CustomData *data, eCustomDataType type, int n, int totelem)
support for deformation groups and hooks.
void BKE_defvert_extract_vgroup_to_faceweights(const MDeformVert *dvert, int defgroup, int verts_num, const int *corner_verts, int loops_num, blender::OffsetIndices< int > faces, bool invert_vgroup, float *r_weights)
Definition deform.cc:1151
void BKE_defvert_extract_vgroup_to_edgeweights(const MDeformVert *dvert, int defgroup, int verts_num, const blender::int2 *edges, int edges_num, bool invert_vgroup, float *r_weights)
Definition deform.cc:1097
void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert, int defgroup, int verts_num, const int *corner_verts, int loops_num, bool invert_vgroup, float *r_weights)
Definition deform.cc:1125
int BKE_id_defgroup_name_index(const ID *id, blender::StringRef name)
Definition deform.cc:538
void BKE_defvert_extract_vgroup_to_vertweights(const MDeformVert *dvert, int defgroup, int verts_num, bool invert_vgroup, float *r_weights)
Definition deform.cc:1078
bool BKE_mesh_calc_islands_loop_face_edgeseam(const float(*vert_positions)[3], int totvert, const blender::int2 *edges, int totedge, const bool *uv_seams, blender::OffsetIndices< int > faces, const int *corner_verts, const int *corner_edges, int corners_num, MeshIslandStore *r_island_store)
bool(*)(const float(*vert_positions)[3], int totvert, const blender::int2 *edges, int totedge, const bool *uv_seams, blender::OffsetIndices< int > faces, const int *corner_verts, const int *corner_edges, int corners_num, MeshIslandStore *r_island_store) MeshRemapIslandsCalc
void BKE_mesh_remap_calc_loops_from_mesh(int mode, const SpaceTransform *space_transform, float max_dist, float ray_radius, const Mesh *mesh_dst, const float(*vert_positions_dst)[3], int numverts_dst, const int *corner_verts_dst, int numloops_dst, const blender::OffsetIndices< int > faces_dst, const Mesh *me_src, MeshRemapIslandsCalc gen_islands_src, float islands_precision_src, MeshPairRemap *r_map)
void BKE_mesh_remap_calc_edges_from_mesh(int mode, const SpaceTransform *space_transform, float max_dist, float ray_radius, const float(*vert_positions_dst)[3], int numverts_dst, const blender::int2 *edges_dst, int numedges_dst, const Mesh *me_src, Mesh *me_dst, MeshPairRemap *r_map)
void BKE_mesh_remap_free(MeshPairRemap *map)
void BKE_mesh_remap_calc_verts_from_mesh(int mode, const SpaceTransform *space_transform, float max_dist, float ray_radius, const float(*vert_positions_dst)[3], int numverts_dst, const Mesh *me_src, Mesh *me_dst, MeshPairRemap *r_map)
void BKE_mesh_remap_calc_faces_from_mesh(int mode, const SpaceTransform *space_transform, float max_dist, float ray_radius, const Mesh *mesh_dst, const float(*vert_positions_dst)[3], int numverts_dst, const int *corner_verts, const blender::OffsetIndices< int > faces_dst, const Mesh *me_src, MeshPairRemap *r_map)
void BKE_mesh_remap_find_best_match_from_mesh(const float(*vert_positions_dst)[3], int numverts_dst, const Mesh *me_src, SpaceTransform *r_space_transform)
void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval)
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
MINLINE float interpf(float target, float origin, float t)
ATTR_WARN_UNUSED_RESULT const size_t num
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
char * BLI_strdupn(const char *str, size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition string.cc:30
#define ELEM(...)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ CD_PROP_BYTE_COLOR
@ CD_MVERT_SKIN
@ CD_PROP_FLOAT
@ CD_MDEFORMVERT
@ CD_PROP_COLOR
@ CD_PROP_FLOAT2
@ CD_FREESTYLE_EDGE
@ CD_FREESTYLE_FACE
@ FREESTYLE_EDGE_MARK
@ FREESTYLE_FACE_MARK
#define DT_TYPE_MAX
@ DT_TYPE_MLOOPCOL_LOOP
@ DT_TYPE_SKIN
@ DT_TYPE_UV
@ DT_TYPE_MPROPCOL_VERT
@ DT_TYPE_BWEIGHT_VERT
@ DT_TYPE_FREESTYLE_FACE
@ DT_TYPE_SHAPEKEY
@ DT_TYPE_CREASE
@ DT_TYPE_SEAM
@ DT_TYPE_MLOOPCOL_VERT
@ DT_TYPE_LNOR
@ DT_TYPE_MPROPCOL_LOOP
@ DT_TYPE_SHARP_FACE
@ DT_TYPE_MDEFORMVERT
@ DT_TYPE_BWEIGHT_EDGE
@ DT_TYPE_FREESTYLE_EDGE
@ DT_TYPE_SHARP_EDGE
@ DT_LAYERS_ALL_SRC
@ DT_LAYERS_ACTIVE_SRC
@ MREMAP_MODE_TOPOLOGY
@ MREMAP_USE_POLY
@ MREMAP_USE_EDGE
@ CDT_MIX_SUB
@ CDT_MIX_REPLACE_BELOW_THRESHOLD
@ CDT_MIX_REPLACE_ABOVE_THRESHOLD
@ CDT_MIX_ADD
@ CDT_MIX_MUL
@ CDT_MIX_TRANSFER
@ CDT_MIX_MIX
#define DT_DATATYPE_IS_LOOP(_dt)
@ DT_LAYERS_ACTIVE_DST
@ DT_LAYERS_INDEX_DST
@ DT_LAYERS_NAME_DST
#define DT_DATATYPE_IS_EDGE(_dt)
#define DT_DATATYPE_IS_FACE(_dt)
#define DT_DATATYPE_IS_VERT(_dt)
@ DT_MULTILAYER_INDEX_MAX
@ DT_MULTILAYER_INDEX_MDEFORMVERT
@ DT_MULTILAYER_INDEX_INVALID
@ DT_MULTILAYER_INDEX_SHAPEKEY
@ DT_MULTILAYER_INDEX_UV
@ DT_MULTILAYER_INDEX_VCOL_VERT
@ DT_MULTILAYER_INDEX_VCOL_LOOP
Object is a sort of wrapper for general info.
@ OB_MESH
Read Guarded memory(de)allocation.
ReportList * reports
Definition WM_types.hh:1025
BPy_StructRNA * depsgraph
unsigned long long int uint64_t
static AttributeOwner from_id(ID *id)
Definition attribute.cc:43
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:739
constexpr T * data() const
Definition BLI_span.hh:539
constexpr const T * data() const
Definition BLI_span.hh:215
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr int64_t size() const
constexpr const char * data() const
GAttributeReader lookup(const StringRef attribute_id) const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
void customdata_data_transfer_interp_normal_normals(const CustomDataTransferLayerMap *laymap, void *data_dst, const void **sources, const float *weights, const int count, const float mix_factor)
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)
static bool data_transfer_layersmapping_cdlayers(ListBase *r_map, const eCustomDataType cddata_type, 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, const CustomData *cd_src, CustomData *cd_dst, const int fromlayers, const int tolayers, cd_datatransfer_interp interp, void *interp_data)
static MeshRemapIslandsCalc data_transfer_get_loop_islands_generator(const int cddata_type)
bool BKE_object_data_transfer_ex(Depsgraph *depsgraph, Object *ob_src, Object *ob_dst, Mesh *me_dst, const int data_types, bool use_create, const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_face_mode, SpaceTransform *space_transform, const bool auto_transform, const float max_distance, const float ray_radius, const float islands_handling_precision, const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX], const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup, ReportList *reports)
bool BKE_object_data_transfer_mesh(Depsgraph *depsgraph, Object *ob_src, Object *ob_dst, const int data_types, const bool use_create, const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_face_mode, SpaceTransform *space_transform, const bool auto_transform, const float max_distance, const float ray_radius, const float islands_handling_precision, const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX], const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup, ReportList *reports)
void BKE_object_data_transfer_layout(Depsgraph *depsgraph, Object *ob_src, Object *ob_dst, const int data_types, const bool use_delete, const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX])
int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type)
int BKE_object_data_transfer_get_dttypes_item_types(const int dtdata_types)
static void data_transfer_mesh_attributes_transfer_active_color_string(Mesh *mesh_dst, const Mesh *mesh_src, const AttrDomainMask mask_domain, const int data_type)
bool BKE_object_data_transfer_get_dttypes_capacity(const int dtdata_types, bool *r_advanced_mixing, bool *r_threshold)
#define DATAMAX
#define EDATA
int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type)
float data_transfer_interp_float_do(const int mix_mode, const float val_dst, const float val_src, const float mix_factor)
#define VDATA
static void data_transfer_dtdata_type_postprocess(Mesh *me_dst, const int dtdata_type, const bool changed)
void BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types, CustomData_MeshMasks *r_data_masks)
static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map, const eCustomDataType cddata_type, 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, const CustomData *cd_src, CustomData *cd_dst, const int tolayers, const bool *use_layers_src, const int num_layers_src, cd_datatransfer_interp interp, void *interp_data)
#define LDATA
static void data_transfer_mesh_attributes_transfer_default_color_string(Mesh *mesh_dst, const Mesh *mesh_src, const AttrDomainMask mask_domain, const int data_type)
static void data_transfer_layersmapping_add_item_cd(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, cd_datatransfer_interp interp, void *interp_data)
static bool data_transfer_layersmapping_generate(ListBase *r_map, Object *ob_src, Object *ob_dst, const Mesh *me_src, Mesh *me_dst, const int elem_type, int cddata_type, int mix_mode, float mix_factor, const float *mix_weights, const int num_elem_dst, const bool use_create, const bool use_delete, const int fromlayers, const int tolayers, SpaceTransform *space_transform)
#define PDATA
bool data_transfer_layersmapping_vgroups(ListBase *r_map, int mix_mode, float mix_factor, const float *mix_weights, int num_elem_dst, bool use_create, bool use_delete, Object *ob_src, Object *ob_dst, const CustomData *cd_src, CustomData *cd_dst, bool use_dupref_dst, int fromlayers, int tolayers)
Definition deform.cc:1404
@ CD_FAKE_CREASE
@ CD_FAKE_SHARP
@ CD_FAKE_BWEIGHT
@ CD_FAKE_MDEFORMVERT
@ CD_FAKE_SHAPEKEY
VecBase< short, 2 > short2
#define CD_MASK_PROP_BYTE_COLOR
#define CD_MASK_PROP_COLOR
#define CD_MASK_MDEFORMVERT
#define MEM_SAFE_FREE(v)
#define CD_MASK_PROP_FLOAT2
#define CD_MASK_COLOR_ALL
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float interp(const float a, const float b, const float t)
Definition math_base.h:502
void normals_corner_custom_set(Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, Span< int > corner_edges, GroupedSpan< int > vert_to_face_map, Span< float3 > vert_normals, Span< float3 > face_normals, Span< bool > sharp_faces, MutableSpan< bool > sharp_edges, MutableSpan< float3 > r_custom_corner_normals, MutableSpan< short2 > r_clnors_data)
VecBase< float, 3 > float3
return ret
cd_datatransfer_interp interp
Definition DNA_ID.h:404
void * first
int corners_num
CustomData edge_data
int edges_num
CustomData corner_data
CustomData face_data
char * default_color_attribute
CustomData vert_data
int faces_num
int verts_num
char * active_color_attribute
i
Definition text_draw.cc:230