Blender  V2.93
MOD_weld.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
17  * All rights reserved.
18  */
19 
26 /* TODOs:
27  * - Review weight and vertex color interpolation.;
28  */
29 
30 //#define USE_WELD_DEBUG
31 //#define USE_WELD_NORMALS
32 //#define USE_BVHTREEKDOP
33 
34 #include "MEM_guardedalloc.h"
35 
36 #include "BLI_utildefines.h"
37 
38 #include "BLI_alloca.h"
39 #include "BLI_bitmap.h"
40 #include "BLI_kdtree.h"
41 #include "BLI_math.h"
42 
43 #include "BLT_translation.h"
44 
45 #include "DNA_defaults.h"
46 #include "DNA_mesh_types.h"
47 #include "DNA_meshdata_types.h"
48 #include "DNA_modifier_types.h"
49 #include "DNA_object_types.h"
50 #include "DNA_screen_types.h"
51 
52 #ifdef USE_BVHTREEKDOP
53 # include "BKE_bvhutils.h"
54 #endif
55 
56 #include "BKE_context.h"
57 #include "BKE_deform.h"
58 #include "BKE_mesh.h"
59 #include "BKE_modifier.h"
60 #include "BKE_screen.h"
61 
62 #include "UI_interface.h"
63 #include "UI_resources.h"
64 
65 #include "RNA_access.h"
66 
67 #include "DEG_depsgraph.h"
68 
69 #include "MOD_modifiertypes.h"
70 #include "MOD_ui_common.h"
71 
72 /* Indicates when the element was not computed. */
73 #define OUT_OF_CONTEXT (uint)(-1)
74 /* Indicates if the edge or face will be collapsed. */
75 #define ELEM_COLLAPSED (uint)(-2)
76 /* indicates whether an edge or vertex in groups_map will be merged. */
77 #define ELEM_MERGED (uint)(-2)
78 
79 /* Used to indicate a range in an array specifying a group. */
80 struct WeldGroup {
83 };
84 
85 /* Edge groups that will be merged. Final vertices are also indicated. */
86 struct WeldGroupEdge {
87  struct WeldGroup group;
90 };
91 
92 typedef struct WeldVert {
93  /* Indexes relative to the original Mesh. */
97 
98 typedef struct WeldEdge {
99  union {
101  struct {
102  /* Indexes relative to the original Mesh. */
107  };
108  };
110 
111 typedef struct WeldLoop {
112  union {
114  struct {
115  /* Indexes relative to the original Mesh. */
120  };
121  };
123 
124 typedef struct WeldPoly {
125  union {
127  struct {
128  /* Indexes relative to the original Mesh. */
133  /* Final Polygon Size. */
135  /* Group of loops that will be affected. */
136  struct WeldGroup loops;
137  };
138  };
140 
141 typedef struct WeldMesh {
142  /* Group of vertices to be merged. */
145 
146  /* Group of edges to be merged. */
149  /* From the original index of the vertex, this indicates which group it is or is going to be
150  * merged. */
152 
153  /* References all polygons and loops that will be affected. */
160 
161  /* From the actual index of the element in the mesh, it indicates what is the index of the Weld
162  * element above. */
165 
169  uint poly_kill_len; /* Including the new polygons. */
170 
171  /* Size of the affected polygon with more sides. */
174 
175 typedef struct WeldLoopOfPolyIter {
178  const WeldLoop *wloop;
179  const MLoop *mloop;
180  const uint *loop_map;
181  /* Weld group. */
183 
186 
187  /* Return */
191  char type;
193 
194 /* -------------------------------------------------------------------- */
198 #ifdef USE_WELD_DEBUG
200  const WeldPoly *wp,
201  const WeldLoop *wloop,
202  const MLoop *mloop,
203  const uint *loop_map,
204  uint *group_buffer);
205 
207 
208 static void weld_assert_edge_kill_len(const WeldEdge *wedge,
209  const uint wedge_len,
210  const uint supposed_kill_len)
211 {
212  uint kills = 0;
213  const WeldEdge *we = &wedge[0];
214  for (uint i = wedge_len; i--; we++) {
215  uint edge_dest = we->edge_dest;
216  /* Magically includes collapsed edges. */
217  if (edge_dest != OUT_OF_CONTEXT) {
218  kills++;
219  }
220  }
221  BLI_assert(kills == supposed_kill_len);
222 }
223 
224 static void weld_assert_poly_and_loop_kill_len(const WeldPoly *wpoly,
225  const WeldPoly *wpoly_new,
226  const uint wpoly_new_len,
227  const WeldLoop *wloop,
228  const MLoop *mloop,
229  const uint *loop_map,
230  const uint *poly_map,
231  const MPoly *mpoly,
232  const uint mpoly_len,
233  const uint mloop_len,
234  const uint supposed_poly_kill_len,
235  const uint supposed_loop_kill_len)
236 {
237  uint poly_kills = 0;
238  uint loop_kills = mloop_len;
239  const MPoly *mp = &mpoly[0];
240  for (uint i = 0; i < mpoly_len; i++, mp++) {
241  uint poly_ctx = poly_map[i];
242  if (poly_ctx != OUT_OF_CONTEXT) {
243  const WeldPoly *wp = &wpoly[poly_ctx];
244  WeldLoopOfPolyIter iter;
245  if (!weld_iter_loop_of_poly_begin(&iter, wp, wloop, mloop, loop_map, NULL)) {
246  poly_kills++;
247  continue;
248  }
249  else {
250  if (wp->poly_dst != OUT_OF_CONTEXT) {
251  poly_kills++;
252  continue;
253  }
254  uint remain = wp->len;
255  uint l = wp->loop_start;
256  while (remain) {
257  uint l_next = l + 1;
258  uint loop_ctx = loop_map[l];
259  if (loop_ctx != OUT_OF_CONTEXT) {
260  const WeldLoop *wl = &wloop[loop_ctx];
261  if (wl->loop_skip_to != OUT_OF_CONTEXT) {
262  l_next = wl->loop_skip_to;
263  }
264  if (wl->flag != ELEM_COLLAPSED) {
265  loop_kills--;
266  remain--;
267  }
268  }
269  else {
270  loop_kills--;
271  remain--;
272  }
273  l = l_next;
274  }
275  }
276  }
277  else {
278  loop_kills -= mp->totloop;
279  }
280  }
281 
282  const WeldPoly *wp = &wpoly_new[0];
283  for (uint i = wpoly_new_len; i--; wp++) {
284  if (wp->poly_dst != OUT_OF_CONTEXT) {
285  poly_kills++;
286  continue;
287  }
288  uint remain = wp->len;
289  uint l = wp->loop_start;
290  while (remain) {
291  uint l_next = l + 1;
292  uint loop_ctx = loop_map[l];
293  if (loop_ctx != OUT_OF_CONTEXT) {
294  const WeldLoop *wl = &wloop[loop_ctx];
295  if (wl->loop_skip_to != OUT_OF_CONTEXT) {
296  l_next = wl->loop_skip_to;
297  }
298  if (wl->flag != ELEM_COLLAPSED) {
299  loop_kills--;
300  remain--;
301  }
302  }
303  else {
304  loop_kills--;
305  remain--;
306  }
307  l = l_next;
308  }
309  }
310 
311  BLI_assert(poly_kills == supposed_poly_kill_len);
312  BLI_assert(loop_kills == supposed_loop_kill_len);
313 }
314 
315 static void weld_assert_poly_no_vert_repetition(const WeldPoly *wp,
316  const WeldLoop *wloop,
317  const MLoop *mloop,
318  const uint *loop_map)
319 {
320  const uint len = wp->len;
322  WeldLoopOfPolyIter iter;
323  if (!weld_iter_loop_of_poly_begin(&iter, wp, wloop, mloop, loop_map, NULL)) {
324  return;
325  }
326  else {
327  uint i = 0;
328  while (weld_iter_loop_of_poly_next(&iter)) {
329  verts[i++] = iter.v;
330  }
331  }
332  for (uint i = 0; i < len; i++) {
333  uint va = verts[i];
334  for (uint j = i + 1; j < len; j++) {
335  uint vb = verts[j];
336  BLI_assert(va != vb);
337  }
338  }
339 }
340 
341 static void weld_assert_poly_len(const WeldPoly *wp, const WeldLoop *wloop)
342 {
343  if (wp->flag == ELEM_COLLAPSED) {
344  return;
345  }
346 
347  uint len = wp->len;
348  const WeldLoop *wl = &wloop[wp->loops.ofs];
349  BLI_assert(wp->loop_start <= wl->loop_orig);
350 
351  uint end_wloop = wp->loops.ofs + wp->loops.len;
352  const WeldLoop *wl_end = &wloop[end_wloop - 1];
353 
354  uint min_len = 0;
355  for (; wl <= wl_end; wl++) {
356  BLI_assert(wl->loop_skip_to == OUT_OF_CONTEXT); /* Not for this case. */
357  if (wl->flag != ELEM_COLLAPSED) {
358  min_len++;
359  }
360  }
361  BLI_assert(len >= min_len);
362 
363  uint max_len = wp->loop_end - wp->loop_start + 1;
364  BLI_assert(len <= max_len);
365 }
366 #endif
369 /* -------------------------------------------------------------------- */
373 static void weld_vert_ctx_alloc_and_setup(const uint mvert_len,
374  uint *r_vert_dest_map,
375  WeldVert **r_wvert,
376  uint *r_wvert_len)
377 {
378  /* Vert Context. */
379  uint wvert_len = 0;
380 
381  WeldVert *wvert, *wv;
382  wvert = MEM_mallocN(sizeof(*wvert) * mvert_len, __func__);
383  wv = &wvert[0];
384 
385  uint *v_dest_iter = &r_vert_dest_map[0];
386  for (uint i = 0; i < mvert_len; i++, v_dest_iter++) {
387  if (*v_dest_iter != OUT_OF_CONTEXT) {
388  wv->vert_dest = *v_dest_iter;
389  wv->vert_orig = i;
390  wv++;
391  wvert_len++;
392  }
393  }
394 
395  *r_wvert = MEM_reallocN(wvert, sizeof(*wvert) * wvert_len);
396  *r_wvert_len = wvert_len;
397 }
398 
399 static void weld_vert_groups_setup(const uint mvert_len,
400  const uint wvert_len,
401  const WeldVert *wvert,
402  const uint *vert_dest_map,
403  uint *r_vert_groups_map,
404  uint **r_vert_groups_buffer,
405  struct WeldGroup **r_vert_groups)
406 {
407  /* Get weld vert groups. */
408 
409  uint wgroups_len = 0;
410  const uint *vert_dest_iter = &vert_dest_map[0];
411  uint *group_map_iter = &r_vert_groups_map[0];
412  for (uint i = 0; i < mvert_len; i++, group_map_iter++, vert_dest_iter++) {
413  uint vert_dest = *vert_dest_iter;
414  if (vert_dest != OUT_OF_CONTEXT) {
415  if (vert_dest != i) {
416  *group_map_iter = ELEM_MERGED;
417  }
418  else {
419  *group_map_iter = wgroups_len;
420  wgroups_len++;
421  }
422  }
423  else {
424  *group_map_iter = OUT_OF_CONTEXT;
425  }
426  }
427 
428  struct WeldGroup *wgroups = MEM_callocN(sizeof(*wgroups) * wgroups_len, __func__);
429 
430  const WeldVert *wv = &wvert[0];
431  for (uint i = wvert_len; i--; wv++) {
432  uint group_index = r_vert_groups_map[wv->vert_dest];
433  wgroups[group_index].len++;
434  }
435 
436  uint ofs = 0;
437  struct WeldGroup *wg_iter = &wgroups[0];
438  for (uint i = wgroups_len; i--; wg_iter++) {
439  wg_iter->ofs = ofs;
440  ofs += wg_iter->len;
441  }
442 
443  BLI_assert(ofs == wvert_len);
444 
445  uint *groups_buffer = MEM_mallocN(sizeof(*groups_buffer) * ofs, __func__);
446  wv = &wvert[0];
447  for (uint i = wvert_len; i--; wv++) {
448  uint group_index = r_vert_groups_map[wv->vert_dest];
449  groups_buffer[wgroups[group_index].ofs++] = wv->vert_orig;
450  }
451 
452  wg_iter = &wgroups[0];
453  for (uint i = wgroups_len; i--; wg_iter++) {
454  wg_iter->ofs -= wg_iter->len;
455  }
456 
457  *r_vert_groups = wgroups;
458  *r_vert_groups_buffer = groups_buffer;
459 }
460 
463 /* -------------------------------------------------------------------- */
467 static void weld_edge_ctx_setup(const uint mvert_len,
468  const uint wedge_len,
469  struct WeldGroup *r_vlinks,
470  uint *r_edge_dest_map,
471  WeldEdge *r_wedge,
472  uint *r_edge_kiil_len)
473 {
474  WeldEdge *we;
475 
476  /* Setup Edge Overlap. */
477  uint edge_kill_len = 0;
478 
479  struct WeldGroup *vl_iter, *v_links;
480  v_links = r_vlinks;
481  vl_iter = &v_links[0];
482 
483  we = &r_wedge[0];
484  for (uint i = wedge_len; i--; we++) {
485  uint dst_vert_a = we->vert_a;
486  uint dst_vert_b = we->vert_b;
487 
488  if (dst_vert_a == dst_vert_b) {
490  r_edge_dest_map[we->edge_orig] = ELEM_COLLAPSED;
491  we->flag = ELEM_COLLAPSED;
492  edge_kill_len++;
493  continue;
494  }
495 
496  v_links[dst_vert_a].len++;
497  v_links[dst_vert_b].len++;
498  }
499 
500  uint link_len = 0;
501  vl_iter = &v_links[0];
502  for (uint i = mvert_len; i--; vl_iter++) {
503  vl_iter->ofs = link_len;
504  link_len += vl_iter->len;
505  }
506 
507  if (link_len) {
508  uint *link_edge_buffer = MEM_mallocN(sizeof(*link_edge_buffer) * link_len, __func__);
509 
510  we = &r_wedge[0];
511  for (uint i = 0; i < wedge_len; i++, we++) {
512  if (we->flag == ELEM_COLLAPSED) {
513  continue;
514  }
515 
516  uint dst_vert_a = we->vert_a;
517  uint dst_vert_b = we->vert_b;
518 
519  link_edge_buffer[v_links[dst_vert_a].ofs++] = i;
520  link_edge_buffer[v_links[dst_vert_b].ofs++] = i;
521  }
522 
523  vl_iter = &v_links[0];
524  for (uint i = mvert_len; i--; vl_iter++) {
525  /* Fix offset */
526  vl_iter->ofs -= vl_iter->len;
527  }
528 
529  we = &r_wedge[0];
530  for (uint i = 0; i < wedge_len; i++, we++) {
531  if (we->edge_dest != OUT_OF_CONTEXT) {
532  /* No need to retest edges.
533  * (Already includes collapsed edges). */
534  continue;
535  }
536 
537  uint dst_vert_a = we->vert_a;
538  uint dst_vert_b = we->vert_b;
539 
540  struct WeldGroup *link_a = &v_links[dst_vert_a];
541  struct WeldGroup *link_b = &v_links[dst_vert_b];
542 
543  uint edges_len_a = link_a->len;
544  uint edges_len_b = link_b->len;
545 
546  if (edges_len_a <= 1 || edges_len_b <= 1) {
547  continue;
548  }
549 
550  uint *edges_ctx_a = &link_edge_buffer[link_a->ofs];
551  uint *edges_ctx_b = &link_edge_buffer[link_b->ofs];
552  uint edge_orig = we->edge_orig;
553 
554  for (; edges_len_a--; edges_ctx_a++) {
555  uint e_ctx_a = *edges_ctx_a;
556  if (e_ctx_a == i) {
557  continue;
558  }
559  while (edges_len_b && *edges_ctx_b < e_ctx_a) {
560  edges_ctx_b++;
561  edges_len_b--;
562  }
563  if (edges_len_b == 0) {
564  break;
565  }
566  uint e_ctx_b = *edges_ctx_b;
567  if (e_ctx_a == e_ctx_b) {
568  WeldEdge *we_b = &r_wedge[e_ctx_b];
569  BLI_assert(ELEM(we_b->vert_a, dst_vert_a, dst_vert_b));
570  BLI_assert(ELEM(we_b->vert_b, dst_vert_a, dst_vert_b));
572  BLI_assert(we_b->edge_orig != edge_orig);
573  r_edge_dest_map[we_b->edge_orig] = edge_orig;
574  we_b->edge_dest = edge_orig;
575  edge_kill_len++;
576  }
577  }
578  }
579 
580 #ifdef USE_WELD_DEBUG
581  weld_assert_edge_kill_len(r_wedge, wedge_len, edge_kill_len);
582 #endif
583 
584  MEM_freeN(link_edge_buffer);
585  }
586 
587  *r_edge_kiil_len = edge_kill_len;
588 }
589 
590 static void weld_edge_ctx_alloc(const MEdge *medge,
591  const uint medge_len,
592  const uint *vert_dest_map,
593  uint *r_edge_dest_map,
594  uint **r_edge_ctx_map,
595  WeldEdge **r_wedge,
596  uint *r_wedge_len)
597 {
598  /* Edge Context. */
599  uint *edge_map = MEM_mallocN(sizeof(*edge_map) * medge_len, __func__);
600  uint wedge_len = 0;
601 
602  WeldEdge *wedge, *we;
603  wedge = MEM_mallocN(sizeof(*wedge) * medge_len, __func__);
604  we = &wedge[0];
605 
606  const MEdge *me = &medge[0];
607  uint *e_dest_iter = &r_edge_dest_map[0];
608  uint *iter = &edge_map[0];
609  for (uint i = 0; i < medge_len; i++, me++, iter++, e_dest_iter++) {
610  uint v1 = me->v1;
611  uint v2 = me->v2;
612  uint v_dest_1 = vert_dest_map[v1];
613  uint v_dest_2 = vert_dest_map[v2];
614  if ((v_dest_1 != OUT_OF_CONTEXT) || (v_dest_2 != OUT_OF_CONTEXT)) {
615  we->vert_a = (v_dest_1 != OUT_OF_CONTEXT) ? v_dest_1 : v1;
616  we->vert_b = (v_dest_2 != OUT_OF_CONTEXT) ? v_dest_2 : v2;
618  we->edge_orig = i;
619  we++;
620  *e_dest_iter = i;
621  *iter = wedge_len++;
622  }
623  else {
624  *e_dest_iter = OUT_OF_CONTEXT;
625  *iter = OUT_OF_CONTEXT;
626  }
627  }
628 
629  *r_wedge = MEM_reallocN(wedge, sizeof(*wedge) * wedge_len);
630  *r_wedge_len = wedge_len;
631  *r_edge_ctx_map = edge_map;
632 }
633 
634 static void weld_edge_groups_setup(const uint medge_len,
635  const uint edge_kill_len,
636  const uint wedge_len,
637  WeldEdge *wedge,
638  const uint *wedge_map,
639  uint *r_edge_groups_map,
640  uint **r_edge_groups_buffer,
641  struct WeldGroupEdge **r_edge_groups)
642 {
643 
644  /* Get weld edge groups. */
645 
646  struct WeldGroupEdge *wegroups, *wegrp_iter;
647 
648  uint wgroups_len = wedge_len - edge_kill_len;
649  wegroups = MEM_callocN(sizeof(*wegroups) * wgroups_len, __func__);
650  wegrp_iter = &wegroups[0];
651 
652  wgroups_len = 0;
653  const uint *edge_ctx_iter = &wedge_map[0];
654  uint *group_map_iter = &r_edge_groups_map[0];
655  for (uint i = medge_len; i--; edge_ctx_iter++, group_map_iter++) {
656  uint edge_ctx = *edge_ctx_iter;
657  if (edge_ctx != OUT_OF_CONTEXT) {
658  WeldEdge *we = &wedge[edge_ctx];
659  uint edge_dest = we->edge_dest;
660  if (edge_dest != OUT_OF_CONTEXT) {
661  BLI_assert(edge_dest != we->edge_orig);
662  *group_map_iter = ELEM_MERGED;
663  }
664  else {
665  we->edge_dest = we->edge_orig;
666  wegrp_iter->v1 = we->vert_a;
667  wegrp_iter->v2 = we->vert_b;
668  *group_map_iter = wgroups_len;
669  wgroups_len++;
670  wegrp_iter++;
671  }
672  }
673  else {
674  *group_map_iter = OUT_OF_CONTEXT;
675  }
676  }
677 
678  BLI_assert(wgroups_len == wedge_len - edge_kill_len);
679 
680  WeldEdge *we = &wedge[0];
681  for (uint i = wedge_len; i--; we++) {
682  if (we->flag == ELEM_COLLAPSED) {
683  continue;
684  }
685  uint group_index = r_edge_groups_map[we->edge_dest];
686  wegroups[group_index].group.len++;
687  }
688 
689  uint ofs = 0;
690  wegrp_iter = &wegroups[0];
691  for (uint i = wgroups_len; i--; wegrp_iter++) {
692  wegrp_iter->group.ofs = ofs;
693  ofs += wegrp_iter->group.len;
694  }
695 
696  uint *groups_buffer = MEM_mallocN(sizeof(*groups_buffer) * ofs, __func__);
697  we = &wedge[0];
698  for (uint i = wedge_len; i--; we++) {
699  if (we->flag == ELEM_COLLAPSED) {
700  continue;
701  }
702  uint group_index = r_edge_groups_map[we->edge_dest];
703  groups_buffer[wegroups[group_index].group.ofs++] = we->edge_orig;
704  }
705 
706  wegrp_iter = &wegroups[0];
707  for (uint i = wgroups_len; i--; wegrp_iter++) {
708  wegrp_iter->group.ofs -= wegrp_iter->group.len;
709  }
710 
711  *r_edge_groups_buffer = groups_buffer;
712  *r_edge_groups = wegroups;
713 }
714 
717 /* -------------------------------------------------------------------- */
722  const WeldPoly *wp,
723  const WeldLoop *wloop,
724  const MLoop *mloop,
725  const uint *loop_map,
726  uint *group_buffer)
727 {
728  if (wp->flag == ELEM_COLLAPSED) {
729  return false;
730  }
731 
732  iter->loop_start = wp->loop_start;
733  iter->loop_end = wp->loop_end;
734  iter->wloop = wloop;
735  iter->mloop = mloop;
736  iter->loop_map = loop_map;
737  iter->group = group_buffer;
738 
739  uint group_len = 0;
740  if (group_buffer) {
741  /* First loop group needs more attention. */
742  uint loop_start, loop_end, l;
743  loop_start = iter->loop_start;
744  loop_end = l = iter->loop_end;
745  while (l >= loop_start) {
746  const uint loop_ctx = loop_map[l];
747  if (loop_ctx != OUT_OF_CONTEXT) {
748  const WeldLoop *wl = &wloop[loop_ctx];
749  if (wl->flag == ELEM_COLLAPSED) {
750  l--;
751  continue;
752  }
753  }
754  break;
755  }
756  if (l != loop_end) {
757  group_len = loop_end - l;
758  int i = 0;
759  while (l < loop_end) {
760  iter->group[i++] = ++l;
761  }
762  }
763  }
764  iter->group_len = group_len;
765 
766  iter->l_next = iter->loop_start;
767 #ifdef USE_WELD_DEBUG
768  iter->v = OUT_OF_CONTEXT;
769 #endif
770  return true;
771 }
772 
774 {
775  uint loop_end = iter->loop_end;
776  const WeldLoop *wloop = iter->wloop;
777  const uint *loop_map = iter->loop_map;
778  uint l = iter->l_curr = iter->l_next;
779  if (l == iter->loop_start) {
780  /* `grupo_len` is already calculated in the first loop */
781  }
782  else {
783  iter->group_len = 0;
784  }
785  while (l <= loop_end) {
786  uint l_next = l + 1;
787  const uint loop_ctx = loop_map[l];
788  if (loop_ctx != OUT_OF_CONTEXT) {
789  const WeldLoop *wl = &wloop[loop_ctx];
790  if (wl->loop_skip_to != OUT_OF_CONTEXT) {
791  l_next = wl->loop_skip_to;
792  }
793  if (wl->flag == ELEM_COLLAPSED) {
794  if (iter->group) {
795  iter->group[iter->group_len++] = l;
796  }
797  l = l_next;
798  continue;
799  }
800 #ifdef USE_WELD_DEBUG
801  BLI_assert(iter->v != wl->vert);
802 #endif
803  iter->v = wl->vert;
804  iter->e = wl->edge;
805  iter->type = 1;
806  }
807  else {
808  const MLoop *ml = &iter->mloop[l];
809 #ifdef USE_WELD_DEBUG
810  BLI_assert(iter->v != ml->v);
811 #endif
812  iter->v = ml->v;
813  iter->e = ml->e;
814  iter->type = 0;
815  }
816  if (iter->group) {
817  iter->group[iter->group_len++] = l;
818  }
819  iter->l_next = l_next;
820  return true;
821  }
822 
823  return false;
824 }
825 
826 static void weld_poly_loop_ctx_alloc(const MPoly *mpoly,
827  const uint mpoly_len,
828  const MLoop *mloop,
829  const uint mloop_len,
830  const uint *vert_dest_map,
831  const uint *edge_dest_map,
832  WeldMesh *r_weld_mesh)
833 {
834  /* Loop/Poly Context. */
835  uint *loop_map = MEM_mallocN(sizeof(*loop_map) * mloop_len, __func__);
836  uint *poly_map = MEM_mallocN(sizeof(*poly_map) * mpoly_len, __func__);
837  uint wloop_len = 0;
838  uint wpoly_len = 0;
839  uint max_ctx_poly_len = 4;
840 
841  WeldLoop *wloop, *wl;
842  wloop = MEM_mallocN(sizeof(*wloop) * mloop_len, __func__);
843  wl = &wloop[0];
844 
845  WeldPoly *wpoly, *wp;
846  wpoly = MEM_mallocN(sizeof(*wpoly) * mpoly_len, __func__);
847  wp = &wpoly[0];
848 
849  uint maybe_new_poly = 0;
850 
851  const MPoly *mp = &mpoly[0];
852  uint *iter = &poly_map[0];
853  uint *loop_map_iter = &loop_map[0];
854  for (uint i = 0; i < mpoly_len; i++, mp++, iter++) {
855  const uint loopstart = mp->loopstart;
856  const uint totloop = mp->totloop;
857 
858  uint vert_ctx_len = 0;
859 
860  uint l = loopstart;
861  uint prev_wloop_len = wloop_len;
862  const MLoop *ml = &mloop[l];
863  for (uint j = totloop; j--; l++, ml++, loop_map_iter++) {
864  uint v = ml->v;
865  uint e = ml->e;
866  uint v_dest = vert_dest_map[v];
867  uint e_dest = edge_dest_map[e];
868  bool is_vert_ctx = v_dest != OUT_OF_CONTEXT;
869  bool is_edge_ctx = e_dest != OUT_OF_CONTEXT;
870  if (is_vert_ctx) {
871  vert_ctx_len++;
872  }
873  if (is_vert_ctx || is_edge_ctx) {
874  wl->vert = is_vert_ctx ? v_dest : v;
875  wl->edge = is_edge_ctx ? e_dest : e;
876  wl->loop_orig = l;
878  wl++;
879 
880  *loop_map_iter = wloop_len++;
881  }
882  else {
883  *loop_map_iter = OUT_OF_CONTEXT;
884  }
885  }
886  if (wloop_len != prev_wloop_len) {
887  uint loops_len = wloop_len - prev_wloop_len;
888 
889  wp->poly_dst = OUT_OF_CONTEXT;
890  wp->poly_orig = i;
891  wp->loops.len = loops_len;
892  wp->loops.ofs = prev_wloop_len;
893  wp->loop_start = loopstart;
894  wp->loop_end = loopstart + totloop - 1;
895  wp->len = totloop;
896  wp++;
897 
898  *iter = wpoly_len++;
899  if (totloop > 5 && vert_ctx_len > 1) {
900  uint max_new = (totloop / 3) - 1;
901  vert_ctx_len /= 2;
902  maybe_new_poly += MIN2(max_new, vert_ctx_len);
903  CLAMP_MIN(max_ctx_poly_len, totloop);
904  }
905  }
906  else {
907  *iter = OUT_OF_CONTEXT;
908  }
909  }
910 
911  if (mpoly_len < (wpoly_len + maybe_new_poly)) {
912  WeldPoly *wpoly_tmp = wpoly;
913  wpoly = MEM_mallocN(sizeof(*wpoly) * ((size_t)wpoly_len + maybe_new_poly), __func__);
914  memcpy(wpoly, wpoly_tmp, sizeof(*wpoly) * wpoly_len);
915  MEM_freeN(wpoly_tmp);
916  }
917 
918  WeldPoly *poly_new = &wpoly[wpoly_len];
919 
920  r_weld_mesh->wloop = MEM_reallocN(wloop, sizeof(*wloop) * wloop_len);
921  r_weld_mesh->wpoly = wpoly;
922  r_weld_mesh->wpoly_new = poly_new;
923  r_weld_mesh->wloop_len = wloop_len;
924  r_weld_mesh->wpoly_len = wpoly_len;
925  r_weld_mesh->wpoly_new_len = 0;
926  r_weld_mesh->loop_map = loop_map;
927  r_weld_mesh->poly_map = poly_map;
928  r_weld_mesh->max_poly_len = max_ctx_poly_len;
929 }
930 
931 static void weld_poly_split_recursive(const uint *vert_dest_map,
932 #ifdef USE_WELD_DEBUG
933  const MLoop *mloop,
934 #endif
935  uint ctx_verts_len,
936  WeldPoly *r_wp,
937  WeldMesh *r_weld_mesh,
938  uint *r_poly_kill,
939  uint *r_loop_kill)
940 {
941  uint poly_len = r_wp->len;
942  if (poly_len > 3 && ctx_verts_len > 1) {
943  const uint ctx_loops_len = r_wp->loops.len;
944  const uint ctx_loops_ofs = r_wp->loops.ofs;
945  WeldLoop *wloop = r_weld_mesh->wloop;
946  WeldPoly *wpoly_new = r_weld_mesh->wpoly_new;
947 
948  uint loop_kill = 0;
949 
950  WeldLoop *poly_loops = &wloop[ctx_loops_ofs];
951  WeldLoop *wla = &poly_loops[0];
952  WeldLoop *wla_prev = &poly_loops[ctx_loops_len - 1];
953  while (wla_prev->flag == ELEM_COLLAPSED) {
954  wla_prev--;
955  }
956  const uint la_len = ctx_loops_len - 1;
957  for (uint la = 0; la < la_len; la++, wla++) {
958  wa_continue:
959  if (wla->flag == ELEM_COLLAPSED) {
960  continue;
961  }
962  uint vert_a = wla->vert;
963  /* Only test vertices that will be merged. */
964  if (vert_dest_map[vert_a] != OUT_OF_CONTEXT) {
965  uint lb = la + 1;
966  WeldLoop *wlb = wla + 1;
967  WeldLoop *wlb_prev = wla;
968  uint killed_ab = 0;
969  ctx_verts_len = 1;
970  for (; lb < ctx_loops_len; lb++, wlb++) {
972  if (wlb->flag == ELEM_COLLAPSED) {
973  killed_ab++;
974  continue;
975  }
976  uint vert_b = wlb->vert;
977  if (vert_dest_map[vert_b] != OUT_OF_CONTEXT) {
978  ctx_verts_len++;
979  }
980  if (vert_a == vert_b) {
981  const uint dist_a = wlb->loop_orig - wla->loop_orig - killed_ab;
982  const uint dist_b = poly_len - dist_a;
983 
984  BLI_assert(dist_a != 0 && dist_b != 0);
985  if (dist_a == 1 || dist_b == 1) {
986  BLI_assert(dist_a != dist_b);
987  BLI_assert((wla->flag == ELEM_COLLAPSED) || (wlb->flag == ELEM_COLLAPSED));
988  }
989  else {
990  WeldLoop *wl_tmp = NULL;
991  if (dist_a == 2) {
992  wl_tmp = wlb_prev;
993  BLI_assert(wla->flag != ELEM_COLLAPSED);
994  BLI_assert(wl_tmp->flag != ELEM_COLLAPSED);
995  wla->flag = ELEM_COLLAPSED;
996  wl_tmp->flag = ELEM_COLLAPSED;
997  loop_kill += 2;
998  poly_len -= 2;
999  }
1000  if (dist_b == 2) {
1001  if (wl_tmp != NULL) {
1002  r_wp->flag = ELEM_COLLAPSED;
1003  *r_poly_kill += 1;
1004  }
1005  else {
1006  wl_tmp = wla_prev;
1007  BLI_assert(wlb->flag != ELEM_COLLAPSED);
1008  BLI_assert(wl_tmp->flag != ELEM_COLLAPSED);
1009  wlb->flag = ELEM_COLLAPSED;
1010  wl_tmp->flag = ELEM_COLLAPSED;
1011  }
1012  loop_kill += 2;
1013  poly_len -= 2;
1014  }
1015  if (wl_tmp == NULL) {
1016  const uint new_loops_len = lb - la;
1017  const uint new_loops_ofs = ctx_loops_ofs + la;
1018 
1019  WeldPoly *new_wp = &wpoly_new[r_weld_mesh->wpoly_new_len++];
1020  new_wp->poly_dst = OUT_OF_CONTEXT;
1021  new_wp->poly_orig = r_wp->poly_orig;
1022  new_wp->loops.len = new_loops_len;
1023  new_wp->loops.ofs = new_loops_ofs;
1024  new_wp->loop_start = wla->loop_orig;
1025  new_wp->loop_end = wlb_prev->loop_orig;
1026  new_wp->len = dist_a;
1027  weld_poly_split_recursive(vert_dest_map,
1028 #ifdef USE_WELD_DEBUG
1029  mloop,
1030 #endif
1031  ctx_verts_len,
1032  new_wp,
1033  r_weld_mesh,
1034  r_poly_kill,
1035  r_loop_kill);
1036  BLI_assert(dist_b == poly_len - dist_a);
1037  poly_len = dist_b;
1038  if (wla_prev->loop_orig > wla->loop_orig) {
1039  /* New start. */
1040  r_wp->loop_start = wlb->loop_orig;
1041  }
1042  else {
1043  /* The `loop_start` doesn't change but some loops must be skipped. */
1044  wla_prev->loop_skip_to = wlb->loop_orig;
1045  }
1046  wla = wlb;
1047  la = lb;
1048  goto wa_continue;
1049  }
1050  break;
1051  }
1052  }
1053  if (wlb->flag != ELEM_COLLAPSED) {
1054  wlb_prev = wlb;
1055  }
1056  }
1057  }
1058  if (wla->flag != ELEM_COLLAPSED) {
1059  wla_prev = wla;
1060  }
1061  }
1062  r_wp->len = poly_len;
1063  *r_loop_kill += loop_kill;
1064 
1065 #ifdef USE_WELD_DEBUG
1066  weld_assert_poly_no_vert_repetition(r_wp, wloop, mloop, r_weld_mesh->loop_map);
1067 #endif
1068  }
1069 }
1070 
1071 static void weld_poly_loop_ctx_setup(const MLoop *mloop,
1072 #ifdef USE_WELD_DEBUG
1073  const MPoly *mpoly,
1074  const uint mpoly_len,
1075  const uint mloop_len,
1076 #endif
1077  const uint mvert_len,
1078  const uint *vert_dest_map,
1079  const uint remain_edge_ctx_len,
1080  struct WeldGroup *r_vlinks,
1081  WeldMesh *r_weld_mesh)
1082 {
1083  uint poly_kill_len, loop_kill_len, wpoly_len, wpoly_new_len;
1084 
1085  WeldPoly *wpoly_new, *wpoly, *wp;
1086  WeldLoop *wloop, *wl;
1087 
1088  wpoly = r_weld_mesh->wpoly;
1089  wloop = r_weld_mesh->wloop;
1090  wpoly_new = r_weld_mesh->wpoly_new;
1091  wpoly_len = r_weld_mesh->wpoly_len;
1092  wpoly_new_len = 0;
1093  poly_kill_len = 0;
1094  loop_kill_len = 0;
1095 
1096  const uint *loop_map = r_weld_mesh->loop_map;
1097 
1098  if (remain_edge_ctx_len) {
1099 
1100  /* Setup Poly/Loop. */
1101 
1102  wp = &wpoly[0];
1103  for (uint i = wpoly_len; i--; wp++) {
1104  const uint ctx_loops_len = wp->loops.len;
1105  const uint ctx_loops_ofs = wp->loops.ofs;
1106 
1107  uint poly_len = wp->len;
1108  uint ctx_verts_len = 0;
1109  wl = &wloop[ctx_loops_ofs];
1110  for (uint l = ctx_loops_len; l--; wl++) {
1111  const uint edge_dest = wl->edge;
1112  if (edge_dest == ELEM_COLLAPSED) {
1113  wl->flag = ELEM_COLLAPSED;
1114  if (poly_len == 3) {
1115  wp->flag = ELEM_COLLAPSED;
1116  poly_kill_len++;
1117  loop_kill_len += 3;
1118  poly_len = 0;
1119  break;
1120  }
1121  loop_kill_len++;
1122  poly_len--;
1123  }
1124  else {
1125  const uint vert_dst = wl->vert;
1126  if (vert_dest_map[vert_dst] != OUT_OF_CONTEXT) {
1127  ctx_verts_len++;
1128  }
1129  }
1130  }
1131 
1132  if (poly_len) {
1133  wp->len = poly_len;
1134 #ifdef USE_WELD_DEBUG
1135  weld_assert_poly_len(wp, wloop);
1136 #endif
1137 
1138  weld_poly_split_recursive(vert_dest_map,
1139 #ifdef USE_WELD_DEBUG
1140  mloop,
1141 #endif
1142  ctx_verts_len,
1143  wp,
1144  r_weld_mesh,
1145  &poly_kill_len,
1146  &loop_kill_len);
1147 
1148  wpoly_new_len = r_weld_mesh->wpoly_new_len;
1149  }
1150  }
1151 
1152 #ifdef USE_WELD_DEBUG
1153  weld_assert_poly_and_loop_kill_len(wpoly,
1154  wpoly_new,
1155  wpoly_new_len,
1156  wloop,
1157  mloop,
1158  loop_map,
1159  r_weld_mesh->poly_map,
1160  mpoly,
1161  mpoly_len,
1162  mloop_len,
1163  poly_kill_len,
1164  loop_kill_len);
1165 #endif
1166 
1167  /* Setup Polygon Overlap. */
1168 
1169  uint wpoly_and_new_len = wpoly_len + wpoly_new_len;
1170 
1171  struct WeldGroup *vl_iter, *v_links = r_vlinks;
1172  memset(v_links, 0, sizeof(*v_links) * mvert_len);
1173 
1174  wp = &wpoly[0];
1175  for (uint i = wpoly_and_new_len; i--; wp++) {
1176  WeldLoopOfPolyIter iter;
1177  if (weld_iter_loop_of_poly_begin(&iter, wp, wloop, mloop, loop_map, NULL)) {
1178  while (weld_iter_loop_of_poly_next(&iter)) {
1179  v_links[iter.v].len++;
1180  }
1181  }
1182  }
1183 
1184  uint link_len = 0;
1185  vl_iter = &v_links[0];
1186  for (uint i = mvert_len; i--; vl_iter++) {
1187  vl_iter->ofs = link_len;
1188  link_len += vl_iter->len;
1189  }
1190 
1191  if (link_len) {
1192  uint *link_poly_buffer = MEM_mallocN(sizeof(*link_poly_buffer) * link_len, __func__);
1193 
1194  wp = &wpoly[0];
1195  for (uint i = 0; i < wpoly_and_new_len; i++, wp++) {
1196  WeldLoopOfPolyIter iter;
1197  if (weld_iter_loop_of_poly_begin(&iter, wp, wloop, mloop, loop_map, NULL)) {
1198  while (weld_iter_loop_of_poly_next(&iter)) {
1199  link_poly_buffer[v_links[iter.v].ofs++] = i;
1200  }
1201  }
1202  }
1203 
1204  vl_iter = &v_links[0];
1205  for (uint i = mvert_len; i--; vl_iter++) {
1206  /* Fix offset */
1207  vl_iter->ofs -= vl_iter->len;
1208  }
1209 
1210  uint polys_len_a, polys_len_b, *polys_ctx_a, *polys_ctx_b, p_ctx_a, p_ctx_b;
1211  polys_len_b = p_ctx_b = 0; /* silence warnings */
1212 
1213  wp = &wpoly[0];
1214  for (uint i = 0; i < wpoly_and_new_len; i++, wp++) {
1215  if (wp->poly_dst != OUT_OF_CONTEXT) {
1216  /* No need to retest poly.
1217  * (Already includes collapsed polygons). */
1218  continue;
1219  }
1220 
1221  WeldLoopOfPolyIter iter;
1222  weld_iter_loop_of_poly_begin(&iter, wp, wloop, mloop, loop_map, NULL);
1224  struct WeldGroup *link_a = &v_links[iter.v];
1225  polys_len_a = link_a->len;
1226  if (polys_len_a == 1) {
1227  BLI_assert(link_poly_buffer[link_a->ofs] == i);
1228  continue;
1229  }
1230  uint wp_len = wp->len;
1231  polys_ctx_a = &link_poly_buffer[link_a->ofs];
1232  for (; polys_len_a--; polys_ctx_a++) {
1233  p_ctx_a = *polys_ctx_a;
1234  if (p_ctx_a == i) {
1235  continue;
1236  }
1237 
1238  WeldPoly *wp_tmp = &wpoly[p_ctx_a];
1239  if (wp_tmp->len != wp_len) {
1240  continue;
1241  }
1242 
1243  WeldLoopOfPolyIter iter_b = iter;
1244  while (weld_iter_loop_of_poly_next(&iter_b)) {
1245  struct WeldGroup *link_b = &v_links[iter_b.v];
1246  polys_len_b = link_b->len;
1247  if (polys_len_b == 1) {
1248  BLI_assert(link_poly_buffer[link_b->ofs] == i);
1249  polys_len_b = 0;
1250  break;
1251  }
1252 
1253  polys_ctx_b = &link_poly_buffer[link_b->ofs];
1254  for (; polys_len_b; polys_len_b--, polys_ctx_b++) {
1255  p_ctx_b = *polys_ctx_b;
1256  if (p_ctx_b < p_ctx_a) {
1257  continue;
1258  }
1259  if (p_ctx_b >= p_ctx_a) {
1260  if (p_ctx_b > p_ctx_a) {
1261  polys_len_b = 0;
1262  }
1263  break;
1264  }
1265  }
1266  if (polys_len_b == 0) {
1267  break;
1268  }
1269  }
1270  if (polys_len_b == 0) {
1271  continue;
1272  }
1273  BLI_assert(p_ctx_a > i);
1274  BLI_assert(p_ctx_a == p_ctx_b);
1275  BLI_assert(wp_tmp->poly_dst == OUT_OF_CONTEXT);
1276  BLI_assert(wp_tmp != wp);
1277  wp_tmp->poly_dst = wp->poly_orig;
1278  loop_kill_len += wp_tmp->len;
1279  poly_kill_len++;
1280  }
1281  }
1282  MEM_freeN(link_poly_buffer);
1283  }
1284  }
1285  else {
1286  poly_kill_len = r_weld_mesh->wpoly_len;
1287  loop_kill_len = r_weld_mesh->wloop_len;
1288 
1289  wp = &wpoly[0];
1290  for (uint i = wpoly_len; i--; wp++) {
1291  wp->flag = ELEM_COLLAPSED;
1292  }
1293  }
1294 
1295 #ifdef USE_WELD_DEBUG
1296  weld_assert_poly_and_loop_kill_len(wpoly,
1297  wpoly_new,
1298  wpoly_new_len,
1299  wloop,
1300  mloop,
1301  loop_map,
1302  r_weld_mesh->poly_map,
1303  mpoly,
1304  mpoly_len,
1305  mloop_len,
1306  poly_kill_len,
1307  loop_kill_len);
1308 #endif
1309 
1310  r_weld_mesh->wpoly_new = wpoly_new;
1311  r_weld_mesh->poly_kill_len = poly_kill_len;
1312  r_weld_mesh->loop_kill_len = loop_kill_len;
1313 }
1314 
1317 /* -------------------------------------------------------------------- */
1322  uint *vert_dest_map,
1323  const uint vert_kill_len,
1324  WeldMesh *r_weld_mesh)
1325 {
1326  const MEdge *medge = mesh->medge;
1327  const MLoop *mloop = mesh->mloop;
1328  const MPoly *mpoly = mesh->mpoly;
1329  const uint mvert_len = mesh->totvert;
1330  const uint medge_len = mesh->totedge;
1331  const uint mloop_len = mesh->totloop;
1332  const uint mpoly_len = mesh->totpoly;
1333 
1334  uint *edge_dest_map = MEM_mallocN(sizeof(*edge_dest_map) * medge_len, __func__);
1335  struct WeldGroup *v_links = MEM_callocN(sizeof(*v_links) * mvert_len, __func__);
1336 
1337  WeldVert *wvert;
1338  uint wvert_len;
1339  r_weld_mesh->vert_kill_len = vert_kill_len;
1340  weld_vert_ctx_alloc_and_setup(mvert_len, vert_dest_map, &wvert, &wvert_len);
1341 
1342  uint *edge_ctx_map;
1343  WeldEdge *wedge;
1344  uint wedge_len;
1346  medge, medge_len, vert_dest_map, edge_dest_map, &edge_ctx_map, &wedge, &wedge_len);
1347 
1349  mvert_len, wedge_len, v_links, edge_dest_map, wedge, &r_weld_mesh->edge_kill_len);
1350 
1352  mpoly, mpoly_len, mloop, mloop_len, vert_dest_map, edge_dest_map, r_weld_mesh);
1353 
1355 #ifdef USE_WELD_DEBUG
1356  mpoly,
1357  mpoly_len,
1358  mloop_len,
1359 #endif
1360  mvert_len,
1361  vert_dest_map,
1362  wedge_len - r_weld_mesh->edge_kill_len,
1363  v_links,
1364  r_weld_mesh);
1365 
1366  weld_vert_groups_setup(mvert_len,
1367  wvert_len,
1368  wvert,
1369  vert_dest_map,
1370  vert_dest_map,
1371  &r_weld_mesh->vert_groups_buffer,
1372  &r_weld_mesh->vert_groups);
1373 
1374  weld_edge_groups_setup(medge_len,
1375  r_weld_mesh->edge_kill_len,
1376  wedge_len,
1377  wedge,
1378  edge_ctx_map,
1379  edge_dest_map,
1380  &r_weld_mesh->edge_groups_buffer,
1381  &r_weld_mesh->edge_groups);
1382 
1383  r_weld_mesh->edge_groups_map = edge_dest_map;
1384  MEM_freeN(v_links);
1385  MEM_freeN(wvert);
1386  MEM_freeN(edge_ctx_map);
1387  MEM_freeN(wedge);
1388 }
1389 
1390 static void weld_mesh_context_free(WeldMesh *weld_mesh)
1391 {
1392  MEM_freeN(weld_mesh->vert_groups);
1393  MEM_freeN(weld_mesh->vert_groups_buffer);
1394 
1395  MEM_freeN(weld_mesh->edge_groups);
1396  MEM_freeN(weld_mesh->edge_groups_buffer);
1397  MEM_freeN(weld_mesh->edge_groups_map);
1398 
1399  MEM_freeN(weld_mesh->wloop);
1400  MEM_freeN(weld_mesh->wpoly);
1401  MEM_freeN(weld_mesh->loop_map);
1402  MEM_freeN(weld_mesh->poly_map);
1403 }
1404 
1407 /* -------------------------------------------------------------------- */
1411 static void customdata_weld(
1412  const CustomData *source, CustomData *dest, const uint *src_indices, int count, int dest_index)
1413 {
1414  if (count == 1) {
1415  CustomData_copy_data(source, dest, src_indices[0], dest_index, 1);
1416  return;
1417  }
1418 
1419  CustomData_interp(source, dest, (const int *)src_indices, NULL, NULL, count, dest_index);
1420 
1421  int src_i, dest_i;
1422  int j;
1423 
1424  float co[3] = {0.0f, 0.0f, 0.0f};
1425 #ifdef USE_WELD_NORMALS
1426  float no[3] = {0.0f, 0.0f, 0.0f};
1427 #endif
1428  uint crease = 0;
1429  uint bweight = 0;
1430  short flag = 0;
1431 
1432  /* interpolates a layer at a time */
1433  dest_i = 0;
1434  for (src_i = 0; src_i < source->totlayer; src_i++) {
1435  const int type = source->layers[src_i].type;
1436 
1437  /* find the first dest layer with type >= the source type
1438  * (this should work because layers are ordered by type)
1439  */
1440  while (dest_i < dest->totlayer && dest->layers[dest_i].type < type) {
1441  dest_i++;
1442  }
1443 
1444  /* if there are no more dest layers, we're done */
1445  if (dest_i == dest->totlayer) {
1446  break;
1447  }
1448 
1449  /* if we found a matching layer, add the data */
1450  if (dest->layers[dest_i].type == type) {
1451  void *src_data = source->layers[src_i].data;
1452 
1453  if (type == CD_MVERT) {
1454  for (j = 0; j < count; j++) {
1455  MVert *mv_src = &((MVert *)src_data)[src_indices[j]];
1456  add_v3_v3(co, mv_src->co);
1457 #ifdef USE_WELD_NORMALS
1458  short *mv_src_no = mv_src->no;
1459  no[0] += mv_src_no[0];
1460  no[1] += mv_src_no[1];
1461  no[2] += mv_src_no[2];
1462 #endif
1463  bweight += mv_src->bweight;
1464  flag |= mv_src->flag;
1465  }
1466  }
1467  else if (type == CD_MEDGE) {
1468  for (j = 0; j < count; j++) {
1469  MEdge *me_src = &((MEdge *)src_data)[src_indices[j]];
1470  crease += me_src->crease;
1471  bweight += me_src->bweight;
1472  flag |= me_src->flag;
1473  }
1474  }
1475  else if (CustomData_layer_has_interp(dest, dest_i)) {
1476  /* Already calculated.
1477  * TODO: Optimize by exposing `typeInfo->interp`. */
1478  }
1479  else if (CustomData_layer_has_math(dest, dest_i)) {
1480  const int size = CustomData_sizeof(type);
1481  void *dst_data = dest->layers[dest_i].data;
1482  void *v_dst = POINTER_OFFSET(dst_data, (size_t)dest_index * size);
1483  for (j = 0; j < count; j++) {
1485  type, v_dst, POINTER_OFFSET(src_data, (size_t)src_indices[j] * size));
1486  }
1487  }
1488  else {
1489  CustomData_copy_layer_type_data(source, dest, type, src_indices[0], dest_index, 1);
1490  }
1491 
1492  /* if there are multiple source & dest layers of the same type,
1493  * we don't want to copy all source layers to the same dest, so
1494  * increment dest_i
1495  */
1496  dest_i++;
1497  }
1498  }
1499 
1500  float fac = 1.0f / count;
1501 
1502  for (dest_i = 0; dest_i < dest->totlayer; dest_i++) {
1503  CustomDataLayer *layer_dst = &dest->layers[dest_i];
1504  const int type = layer_dst->type;
1505  if (type == CD_MVERT) {
1506  MVert *mv = &((MVert *)layer_dst->data)[dest_index];
1507  mul_v3_fl(co, fac);
1508  bweight *= fac;
1509  CLAMP_MAX(bweight, 255);
1510 
1511  copy_v3_v3(mv->co, co);
1512 #ifdef USE_WELD_NORMALS
1513  mul_v3_fl(no, fac);
1514  short *mv_no = mv->no;
1515  mv_no[0] = (short)no[0];
1516  mv_no[1] = (short)no[1];
1517  mv_no[2] = (short)no[2];
1518 #endif
1519 
1520  mv->flag = (char)flag;
1521  mv->bweight = (char)bweight;
1522  }
1523  else if (type == CD_MEDGE) {
1524  MEdge *me = &((MEdge *)layer_dst->data)[dest_index];
1525  crease *= fac;
1526  bweight *= fac;
1527  CLAMP_MAX(crease, 255);
1528  CLAMP_MAX(bweight, 255);
1529 
1530  me->crease = (char)crease;
1531  me->bweight = (char)bweight;
1532  me->flag = flag;
1533  }
1534  else if (CustomData_layer_has_interp(dest, dest_i)) {
1535  /* Already calculated. */
1536  }
1537  else if (CustomData_layer_has_math(dest, dest_i)) {
1538  const int size = CustomData_sizeof(type);
1539  void *dst_data = layer_dst->data;
1540  void *v_dst = POINTER_OFFSET(dst_data, (size_t)dest_index * size);
1541  CustomData_data_multiply(type, v_dst, fac);
1542  }
1543  }
1544 }
1545 
1548 /* -------------------------------------------------------------------- */
1552 #ifdef USE_BVHTREEKDOP
1553 struct WeldOverlapData {
1554  const MVert *mvert;
1555  float merge_dist_sq;
1556 };
1557 static bool bvhtree_weld_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread))
1558 {
1559  if (index_a < index_b) {
1560  struct WeldOverlapData *data = userdata;
1561  const MVert *mvert = data->mvert;
1562  const float dist_sq = len_squared_v3v3(mvert[index_a].co, mvert[index_b].co);
1563  BLI_assert(dist_sq <= ((data->merge_dist_sq + FLT_EPSILON) * 3));
1564  return dist_sq <= data->merge_dist_sq;
1565  }
1566  return false;
1567 }
1568 #endif
1569 
1572  float co[3];
1574 };
1575 
1577 {
1578  Mesh *result = mesh;
1579 
1580  Object *ob = ctx->object;
1581  BLI_bitmap *v_mask = NULL;
1582  int v_mask_act = 0;
1583 
1584  const MVert *mvert;
1585  const MLoop *mloop;
1586  const MPoly *mpoly, *mp;
1587  uint totvert, totedge, totloop, totpoly;
1588 
1589  mvert = mesh->mvert;
1590  totvert = mesh->totvert;
1591 
1592  /* Vertex Group. */
1593  const int defgrp_index = BKE_object_defgroup_name_index(ob, wmd->defgrp_name);
1594  if (defgrp_index != -1) {
1595  MDeformVert *dvert, *dv;
1596  dvert = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT);
1597  if (dvert) {
1598  const bool invert_vgroup = (wmd->flag & MOD_WELD_INVERT_VGROUP) != 0;
1599  dv = &dvert[0];
1600  v_mask = BLI_BITMAP_NEW(totvert, __func__);
1601  for (uint i = 0; i < totvert; i++, dv++) {
1602  const bool found = BKE_defvert_find_weight(dv, defgrp_index) > 0.0f;
1603  if (found != invert_vgroup) {
1604  BLI_BITMAP_ENABLE(v_mask, i);
1605  v_mask_act++;
1606  }
1607  }
1608  }
1609  }
1610 
1611  /* From the original index of the vertex.
1612  * This indicates which vert it is or is going to be merged. */
1613  uint *vert_dest_map = MEM_malloc_arrayN(totvert, sizeof(*vert_dest_map), __func__);
1614  uint vert_kill_len = 0;
1615  if (wmd->mode == MOD_WELD_MODE_ALL)
1616 #ifdef USE_BVHTREEKDOP
1617  {
1618  /* Get overlap map. */
1619  struct BVHTreeFromMesh treedata;
1620  BVHTree *bvhtree = bvhtree_from_mesh_verts_ex(&treedata,
1621  mvert,
1622  totvert,
1623  false,
1624  v_mask,
1625  v_mask_act,
1626  wmd->merge_dist / 2,
1627  2,
1628  6,
1629  0,
1630  NULL,
1631  NULL);
1632 
1633  if (bvhtree) {
1634  struct WeldOverlapData data;
1635  data.mvert = mvert;
1636  data.merge_dist_sq = square_f(wmd->merge_dist);
1637 
1638  uint overlap_len;
1639  BVHTreeOverlap *overlap = BLI_bvhtree_overlap_ex(bvhtree,
1640  bvhtree,
1641  &overlap_len,
1642  bvhtree_weld_overlap_cb,
1643  &data,
1644  1,
1646 
1647  free_bvhtree_from_mesh(&treedata);
1648  if (overlap) {
1649  range_vn_u(vert_dest_map, totvert, 0);
1650 
1651  const BVHTreeOverlap *overlap_iter = &overlap[0];
1652  for (uint i = 0; i < overlap_len; i++, overlap_iter++) {
1653  uint indexA = overlap_iter->indexA;
1654  uint indexB = overlap_iter->indexB;
1655 
1656  BLI_assert(indexA < indexB);
1657 
1658  uint va_dst = vert_dest_map[indexA];
1659  while (va_dst != vert_dest_map[va_dst]) {
1660  va_dst = vert_dest_map[va_dst];
1661  }
1662  uint vb_dst = vert_dest_map[indexB];
1663  while (vb_dst != vert_dest_map[vb_dst]) {
1664  vb_dst = vert_dest_map[vb_dst];
1665  }
1666  if (va_dst == vb_dst) {
1667  continue;
1668  }
1669  if (va_dst > vb_dst) {
1670  SWAP(uint, va_dst, vb_dst);
1671  }
1672  vert_kill_len++;
1673  vert_dest_map[vb_dst] = va_dst;
1674  }
1675 
1676  /* Fix #r_vert_dest_map for next step. */
1677  for (uint i = 0; i < totvert; i++) {
1678  if (i == vert_dest_map[i]) {
1679  vert_dest_map[i] = OUT_OF_CONTEXT;
1680  }
1681  else {
1682  uint v = i;
1683  while (v != vert_dest_map[v] && vert_dest_map[v] != OUT_OF_CONTEXT) {
1684  v = vert_dest_map[v];
1685  }
1686  vert_dest_map[v] = v;
1687  vert_dest_map[i] = v;
1688  }
1689  }
1690 
1691  MEM_freeN(overlap);
1692  }
1693  }
1694  }
1695 #else
1696  {
1697  KDTree_3d *tree = BLI_kdtree_3d_new(v_mask ? v_mask_act : totvert);
1698  for (uint i = 0; i < totvert; i++) {
1699  if (!v_mask || BLI_BITMAP_TEST(v_mask, i)) {
1700  BLI_kdtree_3d_insert(tree, i, mvert[i].co);
1701  }
1702  vert_dest_map[i] = OUT_OF_CONTEXT;
1703  }
1704 
1705  BLI_kdtree_3d_balance(tree);
1706  vert_kill_len = BLI_kdtree_3d_calc_duplicates_fast(
1707  tree, wmd->merge_dist, false, (int *)vert_dest_map);
1708  BLI_kdtree_3d_free(tree);
1709  }
1710 #endif
1711  else {
1713 
1714  MEdge *medge, *me;
1715 
1716  medge = mesh->medge;
1717  totvert = mesh->totvert;
1718  totedge = mesh->totedge;
1719 
1720  struct WeldVertexCluster *vert_clusters = MEM_malloc_arrayN(
1721  totvert, sizeof(*vert_clusters), __func__);
1722  struct WeldVertexCluster *vc = &vert_clusters[0];
1723  for (uint i = 0; i < totvert; i++, vc++) {
1724  copy_v3_v3(vc->co, mvert[i].co);
1725  vc->merged_verts = 0;
1726  }
1727  const float merge_dist_sq = square_f(wmd->merge_dist);
1728 
1729  range_vn_u(vert_dest_map, totvert, 0);
1730 
1731  /* Collapse Edges that are shorter than the threshold. */
1732  me = &medge[0];
1733  for (uint i = 0; i < totedge; i++, me++) {
1734  uint v1 = me->v1;
1735  uint v2 = me->v2;
1736 
1737  while (v1 != vert_dest_map[v1]) {
1738  v1 = vert_dest_map[v1];
1739  }
1740  while (v2 != vert_dest_map[v2]) {
1741  v2 = vert_dest_map[v2];
1742  }
1743  if (v1 == v2) {
1744  continue;
1745  }
1746  if (v_mask && (!BLI_BITMAP_TEST(v_mask, v1) || !BLI_BITMAP_TEST(v_mask, v2))) {
1747  continue;
1748  }
1749  if (v1 > v2) {
1750  SWAP(uint, v1, v2);
1751  }
1752  struct WeldVertexCluster *v1_cluster = &vert_clusters[v1];
1753  struct WeldVertexCluster *v2_cluster = &vert_clusters[v2];
1754 
1755  float edgedir[3];
1756  sub_v3_v3v3(edgedir, v2_cluster->co, v1_cluster->co);
1757  const float dist_sq = len_squared_v3(edgedir);
1758  if (dist_sq <= merge_dist_sq) {
1759  float influence = (v2_cluster->merged_verts + 1) /
1760  (float)(v1_cluster->merged_verts + v2_cluster->merged_verts + 2);
1761  madd_v3_v3fl(v1_cluster->co, edgedir, influence);
1762 
1763  v1_cluster->merged_verts += v2_cluster->merged_verts + 1;
1764  vert_dest_map[v2] = v1;
1765  vert_kill_len++;
1766  }
1767  }
1768 
1769  MEM_freeN(vert_clusters);
1770 
1771  for (uint i = 0; i < totvert; i++) {
1772  if (i == vert_dest_map[i]) {
1773  vert_dest_map[i] = OUT_OF_CONTEXT;
1774  }
1775  else {
1776  uint v = i;
1777  while ((v != vert_dest_map[v]) && (vert_dest_map[v] != OUT_OF_CONTEXT)) {
1778  v = vert_dest_map[v];
1779  }
1780  vert_dest_map[v] = v;
1781  vert_dest_map[i] = v;
1782  }
1783  }
1784  }
1785 
1786  if (v_mask) {
1787  MEM_freeN(v_mask);
1788  }
1789 
1790  if (vert_kill_len) {
1791  WeldMesh weld_mesh;
1792  weld_mesh_context_create(mesh, vert_dest_map, vert_kill_len, &weld_mesh);
1793 
1794  mloop = mesh->mloop;
1795  mpoly = mesh->mpoly;
1796 
1797  totedge = mesh->totedge;
1798  totloop = mesh->totloop;
1799  totpoly = mesh->totpoly;
1800 
1801  const int result_nverts = totvert - weld_mesh.vert_kill_len;
1802  const int result_nedges = totedge - weld_mesh.edge_kill_len;
1803  const int result_nloops = totloop - weld_mesh.loop_kill_len;
1804  const int result_npolys = totpoly - weld_mesh.poly_kill_len + weld_mesh.wpoly_new_len;
1805 
1807  mesh, result_nverts, result_nedges, 0, result_nloops, result_npolys);
1808 
1809  /* Vertices */
1810 
1811  uint *vert_final = vert_dest_map;
1812  uint *index_iter = &vert_final[0];
1813  int dest_index = 0;
1814  for (uint i = 0; i < totvert; i++, index_iter++) {
1815  int source_index = i;
1816  int count = 0;
1817  while (i < totvert && *index_iter == OUT_OF_CONTEXT) {
1818  *index_iter = dest_index + count;
1819  index_iter++;
1820  count++;
1821  i++;
1822  }
1823  if (count) {
1824  CustomData_copy_data(&mesh->vdata, &result->vdata, source_index, dest_index, count);
1825  dest_index += count;
1826  }
1827  if (i == totvert) {
1828  break;
1829  }
1830  if (*index_iter != ELEM_MERGED) {
1831  struct WeldGroup *wgroup = &weld_mesh.vert_groups[*index_iter];
1832  customdata_weld(&mesh->vdata,
1833  &result->vdata,
1834  &weld_mesh.vert_groups_buffer[wgroup->ofs],
1835  wgroup->len,
1836  dest_index);
1837  *index_iter = dest_index;
1838  dest_index++;
1839  }
1840  }
1841 
1842  BLI_assert(dest_index == result_nverts);
1843 
1844  /* Edges */
1845 
1846  uint *edge_final = weld_mesh.edge_groups_map;
1847  index_iter = &edge_final[0];
1848  dest_index = 0;
1849  for (uint i = 0; i < totedge; i++, index_iter++) {
1850  int source_index = i;
1851  int count = 0;
1852  while (i < totedge && *index_iter == OUT_OF_CONTEXT) {
1853  *index_iter = dest_index + count;
1854  index_iter++;
1855  count++;
1856  i++;
1857  }
1858  if (count) {
1859  CustomData_copy_data(&mesh->edata, &result->edata, source_index, dest_index, count);
1860  MEdge *me = &result->medge[dest_index];
1861  dest_index += count;
1862  for (; count--; me++) {
1863  me->v1 = vert_final[me->v1];
1864  me->v2 = vert_final[me->v2];
1865  }
1866  }
1867  if (i == totedge) {
1868  break;
1869  }
1870  if (*index_iter != ELEM_MERGED) {
1871  struct WeldGroupEdge *wegrp = &weld_mesh.edge_groups[*index_iter];
1872  customdata_weld(&mesh->edata,
1873  &result->edata,
1874  &weld_mesh.edge_groups_buffer[wegrp->group.ofs],
1875  wegrp->group.len,
1876  dest_index);
1877  MEdge *me = &result->medge[dest_index];
1878  me->v1 = vert_final[wegrp->v1];
1879  me->v2 = vert_final[wegrp->v2];
1880  me->flag |= ME_LOOSEEDGE;
1881 
1882  *index_iter = dest_index;
1883  dest_index++;
1884  }
1885  }
1886 
1887  BLI_assert(dest_index == result_nedges);
1888 
1889  /* Polys/Loops */
1890 
1891  mp = &mpoly[0];
1892  MPoly *r_mp = &result->mpoly[0];
1893  MLoop *r_ml = &result->mloop[0];
1894  uint r_i = 0;
1895  int loop_cur = 0;
1896  uint *group_buffer = BLI_array_alloca(group_buffer, weld_mesh.max_poly_len);
1897  for (uint i = 0; i < totpoly; i++, mp++) {
1898  int loop_start = loop_cur;
1899  uint poly_ctx = weld_mesh.poly_map[i];
1900  if (poly_ctx == OUT_OF_CONTEXT) {
1901  uint mp_loop_len = mp->totloop;
1902  CustomData_copy_data(&mesh->ldata, &result->ldata, mp->loopstart, loop_cur, mp_loop_len);
1903  loop_cur += mp_loop_len;
1904  for (; mp_loop_len--; r_ml++) {
1905  r_ml->v = vert_final[r_ml->v];
1906  r_ml->e = edge_final[r_ml->e];
1907  }
1908  }
1909  else {
1910  WeldPoly *wp = &weld_mesh.wpoly[poly_ctx];
1911  WeldLoopOfPolyIter iter;
1913  &iter, wp, weld_mesh.wloop, mloop, weld_mesh.loop_map, group_buffer)) {
1914  continue;
1915  }
1916 
1917  if (wp->poly_dst != OUT_OF_CONTEXT) {
1918  continue;
1919  }
1920  while (weld_iter_loop_of_poly_next(&iter)) {
1921  customdata_weld(&mesh->ldata, &result->ldata, group_buffer, iter.group_len, loop_cur);
1922  uint v = vert_final[iter.v];
1923  uint e = edge_final[iter.e];
1924  r_ml->v = v;
1925  r_ml->e = e;
1926  r_ml++;
1927  loop_cur++;
1928  if (iter.type) {
1929  result->medge[e].flag &= ~ME_LOOSEEDGE;
1930  }
1931  BLI_assert((result->medge[e].flag & ME_LOOSEEDGE) == 0);
1932  }
1933  }
1934 
1935  CustomData_copy_data(&mesh->pdata, &result->pdata, i, r_i, 1);
1936  r_mp->loopstart = loop_start;
1937  r_mp->totloop = loop_cur - loop_start;
1938  r_mp++;
1939  r_i++;
1940  }
1941 
1942  WeldPoly *wp = &weld_mesh.wpoly_new[0];
1943  for (uint i = 0; i < weld_mesh.wpoly_new_len; i++, wp++) {
1944  int loop_start = loop_cur;
1945  WeldLoopOfPolyIter iter;
1947  &iter, wp, weld_mesh.wloop, mloop, weld_mesh.loop_map, group_buffer)) {
1948  continue;
1949  }
1950 
1951  if (wp->poly_dst != OUT_OF_CONTEXT) {
1952  continue;
1953  }
1954  while (weld_iter_loop_of_poly_next(&iter)) {
1955  customdata_weld(&mesh->ldata, &result->ldata, group_buffer, iter.group_len, loop_cur);
1956  uint v = vert_final[iter.v];
1957  uint e = edge_final[iter.e];
1958  r_ml->v = v;
1959  r_ml->e = e;
1960  r_ml++;
1961  loop_cur++;
1962  if (iter.type) {
1963  result->medge[e].flag &= ~ME_LOOSEEDGE;
1964  }
1965  BLI_assert((result->medge[e].flag & ME_LOOSEEDGE) == 0);
1966  }
1967 
1968  r_mp->loopstart = loop_start;
1969  r_mp->totloop = loop_cur - loop_start;
1970  r_mp++;
1971  r_i++;
1972  }
1973 
1974  BLI_assert((int)r_i == result_npolys);
1975  BLI_assert(loop_cur == result_nloops);
1976 
1977  /* is this needed? */
1978  /* recalculate normals */
1979  result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
1980 
1981  weld_mesh_context_free(&weld_mesh);
1982  }
1983 
1984  MEM_freeN(vert_dest_map);
1985  return result;
1986 }
1987 
1989 {
1990  WeldModifierData *wmd = (WeldModifierData *)md;
1991  return weldModifier_doWeld(wmd, ctx, mesh);
1992 }
1993 
1994 static void initData(ModifierData *md)
1995 {
1996  WeldModifierData *wmd = (WeldModifierData *)md;
1997 
1998  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier));
1999 
2001 }
2002 
2003 static void requiredDataMask(Object *UNUSED(ob),
2004  ModifierData *md,
2005  CustomData_MeshMasks *r_cddata_masks)
2006 {
2007  WeldModifierData *wmd = (WeldModifierData *)md;
2008 
2009  /* Ask for vertexgroups if we need them. */
2010  if (wmd->defgrp_name[0] != '\0') {
2011  r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
2012  }
2013 }
2014 
2015 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
2016 {
2017  uiLayout *layout = panel->layout;
2018 
2019  PointerRNA ob_ptr;
2021 
2022  uiLayoutSetPropSep(layout, true);
2023 
2024  uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
2025  uiItemR(layout, ptr, "merge_threshold", 0, IFACE_("Distance"), ICON_NONE);
2026  modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
2027 
2028  modifier_panel_end(layout, ptr);
2029 }
2030 
2031 static void panelRegister(ARegionType *region_type)
2032 {
2034 }
2035 
2037  /* name */ "Weld",
2038  /* structName */ "WeldModifierData",
2039  /* structSize */ sizeof(WeldModifierData),
2040  /* srna */ &RNA_WeldModifier,
2041  /* type */ eModifierTypeType_Constructive,
2045  /* icon */ ICON_AUTOMERGE_OFF, /* TODO: Use correct icon. */
2046 
2047  /* copyData */ BKE_modifier_copydata_generic,
2048 
2049  /* deformVerts */ NULL,
2050  /* deformMatrices */ NULL,
2051  /* deformVertsEM */ NULL,
2052  /* deformMatricesEM */ NULL,
2053  /* modifyMesh */ modifyMesh,
2054  /* modifyHair */ NULL,
2055  /* modifyGeometrySet */ NULL,
2056  /* modifyVolume */ NULL,
2057 
2058  /* initData */ initData,
2059  /* requiredDataMask */ requiredDataMask,
2060  /* freeData */ NULL,
2061  /* isDisabled */ NULL,
2062  /* updateDepsgraph */ NULL,
2063  /* dependsOnTime */ NULL,
2064  /* dependsOnNormals */ NULL,
2065  /* foreachIDLink */ NULL,
2066  /* foreachTexLink */ NULL,
2067  /* freeRuntimeData */ NULL,
2068  /* panelRegister */ panelRegister,
2069  /* blendWrite */ NULL,
2070  /* blendRead */ NULL,
2071 };
2072 
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
Definition: bvhutils.c:1701
BVHTree * bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data, const struct MVert *vert, const int verts_num, const bool vert_allocated, const BLI_bitmap *mask, int verts_num_active, float epsilon, int tree_type, int axis, const BVHCacheType bvh_cache_type, struct BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
void CustomData_copy_layer_type_data(const struct CustomData *source, struct CustomData *destination, int type, int source_index, int destination_index, int count)
bool CustomData_layer_has_interp(const struct CustomData *data, int layer_n)
Definition: customdata.c:3832
void CustomData_data_add(int type, void *data1, const void *data2)
Definition: customdata.c:3967
void CustomData_interp(const struct CustomData *source, struct CustomData *dest, const int *src_indices, const float *weights, const float *sub_weights, int count, int dest_index)
void CustomData_data_multiply(int type, void *data, float fac)
Definition: customdata.c:3958
void * CustomData_get_layer(const struct CustomData *data, int type)
int CustomData_sizeof(int type)
Definition: customdata.c:4277
bool CustomData_layer_has_math(const struct CustomData *data, int layer_n)
Definition: customdata.c:3820
void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
support for deformation groups and hooks.
int BKE_object_defgroup_name_index(const struct Object *ob, const char *name)
float BKE_defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
Definition: deform.c:632
struct Mesh * BKE_mesh_new_nomain_from_template(const struct Mesh *me_src, int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
@ eModifierTypeFlag_AcceptsCVs
Definition: BKE_modifier.h:81
@ eModifierTypeFlag_SupportsMapping
Definition: BKE_modifier.h:82
@ eModifierTypeFlag_EnableInEditmode
Definition: BKE_modifier.h:92
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:83
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:80
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, const int flag)
@ eModifierTypeType_Constructive
Definition: BKE_modifier.h:61
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:36
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:63
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
@ BVH_OVERLAP_RETURN_PAIRS
Definition: BLI_kdopbvh.h:94
BVHTreeOverlap * BLI_bvhtree_overlap_ex(const BVHTree *tree1, const BVHTree *tree2, uint *r_overlap_tot, BVHTree_OverlapCallback callback, void *userdata, const uint max_interactions, const int flag)
Definition: BLI_kdopbvh.c:1301
A kd-tree for nearest neighbor search.
MINLINE float square_f(float a)
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
void range_vn_u(unsigned int *array_tar, const int size, const unsigned int start)
Definition: math_vector.c:1182
unsigned int uint
Definition: BLI_sys_types.h:83
#define CLAMP_MAX(a, c)
#define SWAP(type, a, b)
#define UNUSED(x)
#define ELEM(...)
#define MIN2(a, b)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define POINTER_OFFSET(v, ofs)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define CLAMP_MIN(a, b)
#define IFACE_(msgid)
#define CD_MASK_NORMAL
#define CD_MASK_MDEFORMVERT
@ CD_MDEFORMVERT
@ CD_MVERT
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:44
@ ME_LOOSEEDGE
struct WeldModifierData WeldModifierData
@ MOD_WELD_INVERT_VGROUP
@ eModifierType_Weld
@ MOD_WELD_MODE_CONNECTED
@ MOD_WELD_MODE_ALL
Object is a sort of wrapper for general info.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const char *vgroup_prop, const char *invert_vgroup_prop, const char *text)
struct WeldEdge WeldEdge
struct WeldLoopOfPolyIter WeldLoopOfPolyIter
static void weld_vert_ctx_alloc_and_setup(const uint mvert_len, uint *r_vert_dest_map, WeldVert **r_wvert, uint *r_wvert_len)
Definition: MOD_weld.c:373
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
Definition: MOD_weld.c:1988
static void weld_edge_ctx_setup(const uint mvert_len, const uint wedge_len, struct WeldGroup *r_vlinks, uint *r_edge_dest_map, WeldEdge *r_wedge, uint *r_edge_kiil_len)
Definition: MOD_weld.c:467
static void weld_edge_ctx_alloc(const MEdge *medge, const uint medge_len, const uint *vert_dest_map, uint *r_edge_dest_map, uint **r_edge_ctx_map, WeldEdge **r_wedge, uint *r_wedge_len)
Definition: MOD_weld.c:590
static void weld_poly_loop_ctx_setup(const MLoop *mloop, const uint mvert_len, const uint *vert_dest_map, const uint remain_edge_ctx_len, struct WeldGroup *r_vlinks, WeldMesh *r_weld_mesh)
Definition: MOD_weld.c:1071
ModifierTypeInfo modifierType_Weld
Definition: MOD_weld.c:2036
struct WeldPoly WeldPoly
static void weld_mesh_context_create(const Mesh *mesh, uint *vert_dest_map, const uint vert_kill_len, WeldMesh *r_weld_mesh)
Definition: MOD_weld.c:1321
struct WeldMesh WeldMesh
struct WeldLoop WeldLoop
static void weld_edge_groups_setup(const uint medge_len, const uint edge_kill_len, const uint wedge_len, WeldEdge *wedge, const uint *wedge_map, uint *r_edge_groups_map, uint **r_edge_groups_buffer, struct WeldGroupEdge **r_edge_groups)
Definition: MOD_weld.c:634
struct WeldVert WeldVert
#define ELEM_COLLAPSED
Definition: MOD_weld.c:75
#define OUT_OF_CONTEXT
Definition: MOD_weld.c:73
static void weld_mesh_context_free(WeldMesh *weld_mesh)
Definition: MOD_weld.c:1390
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
Definition: MOD_weld.c:2015
static void initData(ModifierData *md)
Definition: MOD_weld.c:1994
#define ELEM_MERGED
Definition: MOD_weld.c:77
static void panelRegister(ARegionType *region_type)
Definition: MOD_weld.c:2031
static void customdata_weld(const CustomData *source, CustomData *dest, const uint *src_indices, int count, int dest_index)
Definition: MOD_weld.c:1411
static bool weld_iter_loop_of_poly_next(WeldLoopOfPolyIter *iter)
Definition: MOD_weld.c:773
static void weld_poly_split_recursive(const uint *vert_dest_map, uint ctx_verts_len, WeldPoly *r_wp, WeldMesh *r_weld_mesh, uint *r_poly_kill, uint *r_loop_kill)
Definition: MOD_weld.c:931
static void weld_vert_groups_setup(const uint mvert_len, const uint wvert_len, const WeldVert *wvert, const uint *vert_dest_map, uint *r_vert_groups_map, uint **r_vert_groups_buffer, struct WeldGroup **r_vert_groups)
Definition: MOD_weld.c:399
static bool weld_iter_loop_of_poly_begin(WeldLoopOfPolyIter *iter, const WeldPoly *wp, const WeldLoop *wloop, const MLoop *mloop, const uint *loop_map, uint *group_buffer)
Definition: MOD_weld.c:721
static Mesh * weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContext *ctx, Mesh *mesh)
Definition: MOD_weld.c:1576
static void weld_poly_loop_ctx_alloc(const MPoly *mpoly, const uint mpoly_len, const MLoop *mloop, const uint mloop_len, const uint *vert_dest_map, const uint *edge_dest_map, WeldMesh *r_weld_mesh)
Definition: MOD_weld.c:826
static void requiredDataMask(Object *UNUSED(ob), ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
Definition: MOD_weld.c:2003
StructRNA RNA_WeldModifier
#define C
Definition: RandGen.cpp:39
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void * tree
static float verts[][3]
int count
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
CustomDataLayer * layers
unsigned int v1
unsigned int v2
unsigned int e
unsigned int v
float co[3]
short no[3]
struct MEdge * medge
struct CustomData pdata ldata
struct MVert * mvert
int totedge
int totvert
struct MLoop * mloop
int totpoly
int totloop
struct MPoly * mpoly
struct Object * object
Definition: BKE_modifier.h:154
struct uiLayout * layout
uint vert_a
Definition: MOD_weld.c:105
uint edge_orig
Definition: MOD_weld.c:104
uint edge_dest
Definition: MOD_weld.c:103
uint vert_b
Definition: MOD_weld.c:106
uint flag
Definition: MOD_weld.c:100
struct WeldGroup group
Definition: MOD_weld.c:87
uint ofs
Definition: MOD_weld.c:82
uint len
Definition: MOD_weld.c:81
const uint * loop_map
Definition: MOD_weld.c:180
const WeldLoop * wloop
Definition: MOD_weld.c:178
const MLoop * mloop
Definition: MOD_weld.c:179
uint flag
Definition: MOD_weld.c:113
uint vert
Definition: MOD_weld.c:116
uint loop_orig
Definition: MOD_weld.c:118
uint loop_skip_to
Definition: MOD_weld.c:119
uint edge
Definition: MOD_weld.c:117
uint max_poly_len
Definition: MOD_weld.c:172
uint edge_kill_len
Definition: MOD_weld.c:167
uint * vert_groups_buffer
Definition: MOD_weld.c:144
uint * edge_groups_map
Definition: MOD_weld.c:151
struct WeldGroup * vert_groups
Definition: MOD_weld.c:143
uint * loop_map
Definition: MOD_weld.c:163
uint wpoly_new_len
Definition: MOD_weld.c:159
uint wloop_len
Definition: MOD_weld.c:157
WeldPoly * wpoly
Definition: MOD_weld.c:155
uint wpoly_len
Definition: MOD_weld.c:158
struct WeldGroupEdge * edge_groups
Definition: MOD_weld.c:147
uint * poly_map
Definition: MOD_weld.c:164
WeldLoop * wloop
Definition: MOD_weld.c:154
uint * edge_groups_buffer
Definition: MOD_weld.c:148
uint poly_kill_len
Definition: MOD_weld.c:169
uint loop_kill_len
Definition: MOD_weld.c:168
uint vert_kill_len
Definition: MOD_weld.c:166
WeldPoly * wpoly_new
Definition: MOD_weld.c:156
uint flag
Definition: MOD_weld.c:126
uint loop_start
Definition: MOD_weld.c:131
uint poly_orig
Definition: MOD_weld.c:130
uint len
Definition: MOD_weld.c:134
uint poly_dst
Definition: MOD_weld.c:129
struct WeldGroup loops
Definition: MOD_weld.c:136
uint loop_end
Definition: MOD_weld.c:132
uint vert_orig
Definition: MOD_weld.c:95
uint vert_dest
Definition: MOD_weld.c:94
uint len
PointerRNA * ptr
Definition: wm_files.c:3157