Blender  V3.3
bmo_removedoubles.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include "MEM_guardedalloc.h"
10 
11 #include "BLI_alloca.h"
12 #include "BLI_kdtree.h"
13 #include "BLI_listbase.h"
14 #include "BLI_math.h"
15 #include "BLI_stack.h"
16 #include "BLI_utildefines_stack.h"
17 
18 #include "BKE_customdata.h"
19 
20 #include "bmesh.h"
22 
23 static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot *slot_targetmap)
24 {
25  BMIter liter;
26  BMLoop *l, *l_tar, *l_double;
27  bool split = false;
28 
29  BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
30  BMVert *v_tar = BMO_slot_map_elem_get(slot_targetmap, l->v);
31  /* ok: if v_tar is NULL (e.g. not in the map) then it's
32  * a target vert, otherwise it's a double */
33  if (v_tar) {
34  l_tar = BM_face_vert_share_loop(f, v_tar);
35 
36  if (l_tar && (l_tar != l) && !BM_loop_is_adjacent(l_tar, l)) {
37  l_double = l;
38  split = true;
39  break;
40  }
41  }
42  }
43 
44  if (split) {
45  BMLoop *l_new;
46  BMFace *f_new;
47 
48  f_new = BM_face_split(bm, f, l_double, l_tar, &l_new, NULL, false);
49 
50  remdoubles_splitface(f, bm, op, slot_targetmap);
51  remdoubles_splitface(f_new, bm, op, slot_targetmap);
52  }
53 }
54 
55 #define ELE_DEL 1
56 #define EDGE_COL 2
57 #define VERT_IN_FACE 4
58 
63  BMFace *f,
64  BMOpSlot *slot_targetmap,
65  bool *r_created)
66 {
67  BMEdge *e_new;
68 
69  /* New ordered edges. */
70  BMEdge **edges = BLI_array_alloca(edges, f->len);
71  /* New ordered verts. */
73  /* Original ordered loops to copy attributes into the new face. */
74  BMLoop **loops = BLI_array_alloca(loops, f->len);
75 
76  STACK_DECLARE(edges);
77  STACK_DECLARE(loops);
79 
80  STACK_INIT(edges, f->len);
81  STACK_INIT(loops, f->len);
82  STACK_INIT(verts, f->len);
83 
84  *r_created = false;
85 
86  {
87 #define LOOP_MAP_VERT_INIT(l_init, v_map, is_del) \
88  v_map = l_init->v; \
89  is_del = BMO_vert_flag_test_bool(bm, v_map, ELE_DEL); \
90  if (is_del) { \
91  v_map = BMO_slot_map_elem_get(slot_targetmap, v_map); \
92  } \
93  ((void)0)
94 
95  BMLoop *l_first, *l_curr, *l_next;
96  BMVert *v_curr;
97  bool is_del_v_curr;
98 
99  l_curr = l_first = BM_FACE_FIRST_LOOP(f);
100  LOOP_MAP_VERT_INIT(l_curr, v_curr, is_del_v_curr);
101 
102  do {
103  BMVert *v_next;
104  bool is_del_v_next;
105 
106  l_next = l_curr->next;
107  LOOP_MAP_VERT_INIT(l_next, v_next, is_del_v_next);
108 
109  /* only search for a new edge if one of the verts is mapped */
110  if ((is_del_v_curr || is_del_v_next) == 0) {
111  e_new = l_curr->e;
112  }
113  else if (v_curr == v_next) {
114  e_new = NULL; /* skip */
115  }
116  else {
117  e_new = BM_edge_exists(v_curr, v_next);
118  BLI_assert(e_new); /* never fails */
119  }
120 
121  if (e_new) {
122  if (UNLIKELY(BMO_vert_flag_test(bm, v_curr, VERT_IN_FACE))) {
123  /* we can't make the face, bail out */
124  STACK_CLEAR(edges);
125  goto finally;
126  }
128 
129  STACK_PUSH(edges, e_new);
130  STACK_PUSH(loops, l_curr);
131  STACK_PUSH(verts, v_curr);
132  }
133 
134  v_curr = v_next;
135  is_del_v_curr = is_del_v_next;
136  } while ((l_curr = l_next) != l_first);
137 
138 #undef LOOP_MAP_VERT_INIT
139  }
140 
141 finally : {
142  uint i;
143  for (i = 0; i < STACK_SIZE(verts); i++) {
145  }
146 }
147 
148  if (STACK_SIZE(edges) >= 3) {
150  if (f_new) {
151  return f_new;
152  }
153  f_new = BM_face_create(bm, verts, edges, STACK_SIZE(edges), f, BM_CREATE_NOP);
154  BLI_assert(f_new != f);
155 
156  if (f_new) {
157  uint i = 0;
158  BMLoop *l_iter, *l_first;
159  l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
160  do {
161  BM_elem_attrs_copy(bm, bm, loops[i], l_iter);
162  } while ((void)i++, (l_iter = l_iter->next) != l_first);
163 
164  *r_created = true;
165  return f_new;
166  }
167  }
168 
169  return NULL;
170 }
171 
178 {
179  BMIter iter, liter;
180  BMVert *v;
181  BMEdge *e;
182  BMLoop *l;
183  BMFace *f;
184  BMOpSlot *slot_targetmap = BMO_slot_get(op->slots_in, "targetmap");
185 
186  /* Maintain selection history. */
187  const bool has_selected = !BLI_listbase_is_empty(&bm->selected);
188  const bool use_targetmap_all = has_selected;
189  GHash *targetmap_all = NULL;
190  if (use_targetmap_all) {
191  /* Map deleted to keep elem. */
192  targetmap_all = BLI_ghash_ptr_new(__func__);
193  }
194 
195  /* mark merge verts for deletion */
196  BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
197  BMVert *v_dst = BMO_slot_map_elem_get(slot_targetmap, v);
198  if (v_dst != NULL) {
200 
201  /* merge the vertex flags, else we get randomly selected/unselected verts */
203 
204  if (use_targetmap_all) {
205  BLI_assert(v != v_dst);
206  BLI_ghash_insert(targetmap_all, v, v_dst);
207  }
208  }
209  }
210 
211  /* check if any faces are getting their own corners merged
212  * together, split face if so */
213  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
214  remdoubles_splitface(f, bm, op, slot_targetmap);
215  }
216 
217  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
218  BMVert *v1, *v2;
219  const bool is_del_v1 = BMO_vert_flag_test_bool(bm, (v1 = e->v1), ELE_DEL);
220  const bool is_del_v2 = BMO_vert_flag_test_bool(bm, (v2 = e->v2), ELE_DEL);
221 
222  if (is_del_v1 || is_del_v2) {
223  if (is_del_v1) {
224  v1 = BMO_slot_map_elem_get(slot_targetmap, v1);
225  }
226  if (is_del_v2) {
227  v2 = BMO_slot_map_elem_get(slot_targetmap, v2);
228  }
229 
230  if (v1 == v2) {
232  }
233  else {
234  /* always merge flags, even for edges we already created */
235  BMEdge *e_new = BM_edge_exists(v1, v2);
236  if (e_new == NULL) {
237  e_new = BM_edge_create(bm, v1, v2, e, BM_CREATE_NOP);
238  }
240  if (use_targetmap_all) {
241  BLI_assert(e != e_new);
242  BLI_ghash_insert(targetmap_all, e, e_new);
243  }
244  }
245 
247  }
248  }
249 
250  /* faces get "modified" by creating new faces here, then at the
251  * end the old faces are deleted */
252  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
253  bool vert_delete = false;
254  int edge_collapse = 0;
255 
256  BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
257  if (BMO_vert_flag_test(bm, l->v, ELE_DEL)) {
258  vert_delete = true;
259  }
260  if (BMO_edge_flag_test(bm, l->e, EDGE_COL)) {
261  edge_collapse++;
262  }
263  }
264 
265  if (vert_delete) {
266  bool use_in_place = false;
267  BMFace *f_new = NULL;
269 
270  if (f->len - edge_collapse >= 3) {
271  bool created;
272  f_new = remdoubles_createface(bm, f, slot_targetmap, &created);
273  /* do this so we don't need to return a list of created faces */
274  if (f_new) {
275  if (created) {
276  bmesh_face_swap_data(f_new, f);
277 
278  if (bm->use_toolflags) {
279  SWAP(BMFlagLayer *, ((BMFace_OFlag *)f)->oflags, ((BMFace_OFlag *)f_new)->oflags);
280  }
281 
283  BM_face_kill(bm, f_new);
284  use_in_place = true;
285  }
286  else {
288  }
289  }
290  }
291 
292  if ((use_in_place == false) && (f_new != NULL)) {
293  BLI_assert(f != f_new);
294  if (use_targetmap_all) {
295  BLI_ghash_insert(targetmap_all, f, f_new);
296  }
297  if (bm->act_face && (f == bm->act_face)) {
298  bm->act_face = f_new;
299  }
300  }
301  }
302  }
303 
304  if (has_selected) {
305  BM_select_history_merge_from_targetmap(bm, targetmap_all, targetmap_all, targetmap_all, true);
306  }
307 
308  if (use_targetmap_all) {
309  BLI_ghash_free(targetmap_all, NULL, NULL);
310  }
311 
313 }
314 
315 #define VERT_KEEP 8
316 
317 #define EDGE_MARK 1
318 
320 {
321  BMOIter siter;
322  BMIter iter;
323  BMVert *v, *vert_snap;
324  BMLoop *l, *l_first = NULL;
325  float fac;
326  int i, tot;
327 
328  vert_snap = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert_snap"));
329  tot = BM_vert_face_count(vert_snap);
330 
331  if (!tot) {
332  return;
333  }
334 
335  fac = 1.0f / tot;
336  BM_ITER_ELEM (l, &iter, vert_snap, BM_LOOPS_OF_VERT) {
337  if (l_first == NULL) {
338  l_first = l;
339  }
340 
341  for (i = 0; i < bm->ldata.totlayer; i++) {
342  if (CustomData_layer_has_math(&bm->ldata, i)) {
343  const int type = bm->ldata.layers[i].type;
344  const int offset = bm->ldata.layers[i].offset;
345  void *e1, *e2;
346 
347  e1 = BM_ELEM_CD_GET_VOID_P(l_first, offset);
349 
350  CustomData_data_multiply(type, e2, fac);
351 
352  if (l != l_first) {
353  CustomData_data_add(type, e1, e2);
354  }
355  }
356  }
357  }
358 
359  BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
360  BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
361  if (l == l_first) {
362  continue;
363  }
364 
366  }
367  }
368 }
369 
371 {
372  BMOIter siter;
373  BMIter iter;
374  BMVert *v;
375  BMLoop *l;
377  int i;
378 
379  for (i = 0; i < bm->ldata.totlayer; i++) {
380  const int type = bm->ldata.layers[i].type;
381  const int offset = bm->ldata.layers[i].offset;
382 
383  if (!CustomData_layer_has_math(&bm->ldata, i)) {
384  continue;
385  }
386 
388 
389  BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
390  BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
391  void *block = BM_ELEM_CD_GET_VOID_P(l, offset);
392  CustomData_data_dominmax(type, block, &min, &max);
393  }
394  }
395 
399 
400  BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
401  BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
402  void *block = BM_ELEM_CD_GET_VOID_P(l, offset);
404  }
405  }
406  }
407 }
408 
410 {
411  BMOperator weldop;
412  BMOIter siter;
413  BMVert *v, *vert_snap = NULL;
414  float vec[3];
415  BMOpSlot *slot_targetmap;
416 
417  BMO_slot_vec_get(op->slots_in, "merge_co", vec);
418 
419  // BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges");
420  BMO_op_init(bm, &weldop, op->flag, "weld_verts");
421 
422  slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
423 
424  BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
425  if (!vert_snap) {
426  vert_snap = v;
427  copy_v3_v3(vert_snap->co, vec);
428  }
429  else {
430  BMO_slot_map_elem_insert(&weldop, slot_targetmap, v, vert_snap);
431  }
432  }
433 
434  BMO_op_exec(bm, &weldop);
435  BMO_op_finish(bm, &weldop);
436 }
437 
439 {
440  BMOperator weldop;
441  BMWalker walker;
442  BMIter iter;
443  BMEdge *e;
444  BLI_Stack *edge_stack;
445  BMOpSlot *slot_targetmap;
446 
447  if (BMO_slot_bool_get(op->slots_in, "uvs")) {
448  BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges");
449  }
450 
451  BMO_op_init(bm, &weldop, op->flag, "weld_verts");
452  slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
453 
455 
456  BMW_init(&walker,
457  bm,
459  BMW_MASK_NOP,
460  EDGE_MARK,
461  BMW_MASK_NOP,
462  BMW_FLAG_NOP, /* no need to use BMW_FLAG_TEST_HIDDEN, already marked data */
463  BMW_NIL_LAY);
464 
465  edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
466 
467  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
468  float center[3];
469  int count = 0;
470  BMVert *v_tar;
471 
472  zero_v3(center);
473 
474  if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) {
475  continue;
476  }
477 
478  BLI_assert(BLI_stack_is_empty(edge_stack));
479 
480  for (e = BMW_begin(&walker, e->v1); e; e = BMW_step(&walker)) {
481  BLI_stack_push(edge_stack, &e);
482 
483  add_v3_v3(center, e->v1->co);
484  add_v3_v3(center, e->v2->co);
485 
486  count += 2;
487 
488  /* prevent adding to slot_targetmap multiple times */
491  }
492 
493  if (!BLI_stack_is_empty(edge_stack)) {
494  mul_v3_fl(center, 1.0f / count);
495 
496  /* snap edges to a point. for initial testing purposes anyway */
497  e = *(BMEdge **)BLI_stack_peek(edge_stack);
498  v_tar = e->v1;
499 
500  while (!BLI_stack_is_empty(edge_stack)) {
501  uint j;
502  BLI_stack_pop(edge_stack, &e);
503 
504  for (j = 0; j < 2; j++) {
505  BMVert *v_src = *((&e->v1) + j);
506 
507  copy_v3_v3(v_src->co, center);
508  if ((v_src != v_tar) && !BM_elem_flag_test(v_src, BM_ELEM_TAG)) {
510  BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_src, v_tar);
511  }
512  }
513  }
514  }
515  }
516 
517  BLI_stack_free(edge_stack);
518 
519  BMO_op_exec(bm, &weldop);
520  BMO_op_finish(bm, &weldop);
521 
522  BMW_end(&walker);
523 }
524 
525 /* uv collapse function */
526 static void bmo_collapsecon_do_layer(BMesh *bm, const int layer, const short oflag)
527 {
528  const int type = bm->ldata.layers[layer].type;
529  const int offset = bm->ldata.layers[layer].offset;
530  BMIter iter, liter;
531  BMFace *f;
532  BMLoop *l, *l2;
533  BMWalker walker;
534  BLI_Stack *block_stack;
536 
537  BMW_init(&walker,
538  bm,
540  BMW_MASK_NOP,
541  oflag,
542  BMW_MASK_NOP,
543  BMW_FLAG_NOP, /* no need to use BMW_FLAG_TEST_HIDDEN, already marked data */
544  layer);
545 
546  block_stack = BLI_stack_new(sizeof(void *), __func__);
547 
548  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
549  BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
550  if (BMO_edge_flag_test(bm, l->e, oflag)) {
551  /* walk */
552  BLI_assert(BLI_stack_is_empty(block_stack));
553 
555  for (l2 = BMW_begin(&walker, l); l2; l2 = BMW_step(&walker)) {
556  void *block = BM_ELEM_CD_GET_VOID_P(l2, offset);
557  CustomData_data_dominmax(type, block, &min, &max);
558  BLI_stack_push(block_stack, &block);
559  }
560 
561  if (!BLI_stack_is_empty(block_stack)) {
565 
566  /* snap CD (uv, vcol) points to their centroid */
567  while (!BLI_stack_is_empty(block_stack)) {
568  void *block;
569  BLI_stack_pop(block_stack, &block);
571  }
572  }
573  }
574  }
575  }
576 
577  BLI_stack_free(block_stack);
578 
579  BMW_end(&walker);
580 }
581 
583 {
584  const short oflag = EDGE_MARK;
585  int i;
586 
587  /* Check flags don't change once set. */
588 #ifndef NDEBUG
589  int tot_test;
590 #endif
591 
592  if (!CustomData_has_math(&bm->ldata)) {
593  return;
594  }
595 
597 
598 #ifndef NDEBUG
599  tot_test = BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, oflag, true);
600 #endif
601 
602  for (i = 0; i < bm->ldata.totlayer; i++) {
603  if (CustomData_layer_has_math(&bm->ldata, i)) {
605  }
606  }
607 
608 #ifndef NDEBUG
610 #endif
611 }
612 
614  BMOperator *op,
615  BMOperator *optarget,
616  BMOpSlot *optarget_slot)
617 {
618  const BMOpSlot *slot_verts = BMO_slot_get(op->slots_in, "verts");
619  BMVert *const *verts = (BMVert **)slot_verts->data.buf;
620  const int verts_len = slot_verts->len;
621 
622  bool has_keep_vert = false;
623  bool found_duplicates = false;
624 
625  const float dist = BMO_slot_float_get(op->slots_in, "dist");
626 
627  /* Test whether keep_verts arg exists and is non-empty */
628  if (BMO_slot_exists(op->slots_in, "keep_verts")) {
629  BMOIter oiter;
630  has_keep_vert = BMO_iter_new(&oiter, op->slots_in, "keep_verts", BM_VERT) != NULL;
631  }
632 
633  /* Flag keep_verts */
634  if (has_keep_vert) {
636  }
637 
638  int *duplicates = MEM_mallocN(sizeof(int) * verts_len, __func__);
639  {
640  KDTree_3d *tree = BLI_kdtree_3d_new(verts_len);
641  for (int i = 0; i < verts_len; i++) {
642  BLI_kdtree_3d_insert(tree, i, verts[i]->co);
643  if (has_keep_vert && BMO_vert_flag_test(bm, verts[i], VERT_KEEP)) {
644  duplicates[i] = i;
645  }
646  else {
647  duplicates[i] = -1;
648  }
649  }
650 
651  BLI_kdtree_3d_balance(tree);
652  found_duplicates = BLI_kdtree_3d_calc_duplicates_fast(tree, dist, false, duplicates) != 0;
653  BLI_kdtree_3d_free(tree);
654  }
655 
656  if (found_duplicates) {
657  for (int i = 0; i < verts_len; i++) {
658  BMVert *v_check = verts[i];
659  if (duplicates[i] == -1) {
660  /* nop (others can use as target) */
661  }
662  else if (duplicates[i] == i) {
663  /* keep (others can use as target) */
664  }
665  else {
666  BMVert *v_other = verts[duplicates[i]];
667  BLI_assert(ELEM(duplicates[duplicates[i]], -1, duplicates[i]));
668  BMO_slot_map_elem_insert(optarget, optarget_slot, v_check, v_other);
669  }
670  }
671  }
672 
673  MEM_freeN(duplicates);
674 }
675 
677 {
678  BMOperator weldop;
679  BMOpSlot *slot_targetmap;
680 
681  BMO_op_init(bm, &weldop, op->flag, "weld_verts");
682  slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
683  bmesh_find_doubles_common(bm, op, &weldop, slot_targetmap);
684  BMO_op_exec(bm, &weldop);
685  BMO_op_finish(bm, &weldop);
686 }
687 
689 {
690  BMOpSlot *slot_targetmap_out;
691  slot_targetmap_out = BMO_slot_get(op->slots_out, "targetmap.out");
692  bmesh_find_doubles_common(bm, op, op, slot_targetmap_out);
693 }
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_has_math(const struct CustomData *data)
void CustomData_data_add(int type, void *data1, const void *data2)
Definition: customdata.cc:4011
void CustomData_data_copy_value(int type, const void *source, void *dest)
Definition: customdata.cc:3939
void CustomData_data_multiply(int type, void *data, float fac)
Definition: customdata.cc:4002
void CustomData_bmesh_copy_data(const struct CustomData *source, struct CustomData *dest, void *src_block, void **dest_block)
void CustomData_data_initminmax(int type, void *min, void *max)
Definition: customdata.cc:3984
bool CustomData_layer_has_math(const struct CustomData *data, int layer_n)
void CustomData_data_dominmax(int type, const void *data, void *min, void *max)
Definition: customdata.cc:3993
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:22
#define BLI_assert(a)
Definition: BLI_assert.h:46
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:710
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
A KD-tree for nearest neighbor search.
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL()
Definition: stack.c:135
void * BLI_stack_peek(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:166
void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL()
Definition: stack.c:129
bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: stack.c:247
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
Definition: stack.c:94
#define BLI_stack_new(esize, descr)
unsigned int uint
Definition: BLI_sys_types.h:67
#define SWAP(type, a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define STACK_CLEAR(stack)
#define STACK_PUSH(stack, val)
#define STACK_DECLARE(stack)
#define STACK_SIZE(stack)
#define STACK_INIT(stack, stack_num)
NSNotificationCenter * center
_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 BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_HIDDEN
Definition: bmesh_class.h:472
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src, void *ele_dst)
void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b)
Definition: bmesh_core.c:2651
void BM_face_kill(BMesh *bm, BMFace *f)
Definition: bmesh_core.c:828
BMFace * BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const BMFace *f_example, const eBMCreateFlag create_flag)
Definition: bmesh_core.c:395
BMEdge * BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag)
Main function for creating a new edge.
Definition: bmesh_core.c:123
@ BM_CREATE_NOP
Definition: bmesh_core.h:12
void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type)
Definition: bmesh_delete.c:86
#define BM_elem_flag_merge_ex(ele_a, ele_b, hflag_and)
Definition: bmesh_inline.h:19
#define BM_elem_flag_disable(ele, hflag)
Definition: bmesh_inline.h:15
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:14
int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value)
Mesh Iter Flag Count.
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
@ BM_LOOPS_OF_VERT
@ BM_LOOPS_OF_FACE
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_select_history_merge_from_targetmap(BMesh *bm, GHash *vert_map, GHash *edge_map, GHash *face_map, const bool use_chain)
BMFace * BM_face_split(BMesh *bm, BMFace *f, BMLoop *l_a, BMLoop *l_b, BMLoop **r_l, BMEdge *example, const bool no_double)
Face Split.
Definition: bmesh_mods.c:179
void BMO_slot_buffer_flag_enable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, short oflag)
BMO_FLAG_BUFFER.
#define BMO_vert_flag_disable(bm, e, oflag)
#define BMO_edge_flag_test(bm, e, oflag)
void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3])
#define BMO_edge_flag_enable(bm, e, oflag)
@ DEL_ONLYTAGGED
float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
void * BMO_slot_buffer_get_single(BMOpSlot *slot)
void * BMO_iter_new(BMOIter *iter, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char restrictmask)
New Iterator.
#define BMO_vert_flag_enable(bm, e, oflag)
void BMO_op_exec(BMesh *bm, BMOperator *op)
BMESH OPSTACK EXEC OP.
#define BMO_face_flag_enable(bm, e, oflag)
void BMO_op_init(BMesh *bm, BMOperator *op, int flag, const char *opname)
BMESH OPSTACK INIT OP.
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag)
#define BMO_vert_flag_test(bm, e, oflag)
void BMO_op_finish(BMesh *bm, BMOperator *op)
BMESH OPSTACK FINISH OP.
bool BMO_op_callf(BMesh *bm, int flag, const char *fmt,...)
BMOpSlot * BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
BMESH OPSTACK GET SLOT.
#define BMO_vert_flag_test_bool(bm, e, oflag)
#define BMO_face_flag_disable(bm, e, oflag)
bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
BMESH OPSTACK HAS SLOT.
bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, const void *element, void *val)
ATTR_WARN_UNUSED_RESULT const BMFlagLayer const short oflag
ATTR_WARN_UNUSED_RESULT const BMFlagLayer * oflags
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1553
int BM_vert_face_count(const BMVert *v)
Definition: bmesh_query.c:664
BMFace * BM_face_exists(BMVert **varr, int len)
Definition: bmesh_query.c:1612
BMLoop * BM_face_vert_share_loop(BMFace *f, BMVert *v)
Return the Loop Shared by Face and Vertex.
Definition: bmesh_query.c:1100
BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
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
void BMW_init(BMWalker *walker, BMesh *bm, int type, short mask_vert, short mask_edge, short mask_face, BMWFlag flag, int layer)
Init Walker.
Definition: bmesh_walkers.c:49
void BMW_end(BMWalker *walker)
End Walker.
void * BMW_begin(BMWalker *walker, void *start)
Definition: bmesh_walkers.c:40
void * BMW_step(BMWalker *walker)
Step Walker.
#define BMW_NIL_LAY
@ BMW_FLAG_NOP
Definition: bmesh_walkers.h:19
#define BMW_MASK_NOP
Definition: bmesh_walkers.h:54
@ BMW_VERT_SHELL
@ BMW_LOOPDATA_ISLAND
#define ELE_DEL
static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *optarget, BMOpSlot *optarget_slot)
#define VERT_KEEP
void bmo_collapse_exec(BMesh *bm, BMOperator *op)
void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op)
static BMFace * remdoubles_createface(BMesh *bm, BMFace *f, BMOpSlot *slot_targetmap, bool *r_created)
void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op)
#define LOOP_MAP_VERT_INIT(l_init, v_map, is_del)
static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot *slot_targetmap)
void bmo_pointmerge_exec(BMesh *bm, BMOperator *op)
#define EDGE_MARK
void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op)
#define EDGE_COL
void bmo_find_doubles_exec(BMesh *bm, BMOperator *op)
static void bmo_collapsecon_do_layer(BMesh *bm, const int layer, const short oflag)
#define VERT_IN_FACE
void bmo_collapse_uvs_exec(BMesh *bm, BMOperator *op)
void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
void * tree
static float verts[][3]
int count
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
void split(const std::string &s, const char delim, std::vector< std::string > &tokens)
Definition: abc_util.cc:92
#define min(a, b)
Definition: sort.c:35
int len
Definition: bmesh_class.h:267
void * data
Definition: bmesh_class.h:51
BMHeader head
Definition: bmesh_class.h:145
struct BMVert * v
Definition: bmesh_class.h:153
struct BMEdge * e
Definition: bmesh_class.h:164
struct BMLoop * next
Definition: bmesh_class.h:233
union BMOpSlot::@145 data
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]
float co[3]
Definition: bmesh_class.h:87
ListBase selected
Definition: bmesh_class.h:356
uint use_toolflags
Definition: bmesh_class.h:333
BMFace * act_face
Definition: bmesh_class.h:366
CustomData ldata
Definition: bmesh_class.h:337
CustomDataLayer * layers
float max