Blender  V3.3
bmesh_separate.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
10 #include <limits.h>
11 
12 #include "MEM_guardedalloc.h"
13 
14 #include "BLI_buffer.h"
15 #include "BLI_utildefines.h"
16 
17 #include "bmesh.h"
18 #include "bmesh_separate.h" /* own include */
19 #include "intern/bmesh_private.h"
20 
22 {
23  BMFace **faces_array_all = MEM_mallocN(bm->totface * sizeof(BMFace *), __func__);
24  /*
25  * - Create an array of faces based on 'filter_fn'.
26  * First part of array for match, for non-match.
27  *
28  * - Enable all vertex tags, then clear all tagged vertices from 'faces_b'.
29  *
30  * - Loop over 'faces_a', checking each vertex,
31  * splitting out any which aren't tagged (and therefor shared), disabling tags as we go.
32  */
33 
34  BMFace *f;
35  BMIter iter;
36 
37  uint faces_a_len = 0;
38  uint faces_b_len = 0;
39  {
40  int i_a = 0;
41  int i_b = bm->totface;
42  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
43  faces_array_all[filter_fn(f, user_data) ? i_a++ : --i_b] = f;
44  }
45  faces_a_len = i_a;
46  faces_b_len = bm->totface - i_a;
47  }
48 
49  BMFace **faces_a = faces_array_all;
50  BMFace **faces_b = faces_array_all + faces_a_len;
51 
52  /* Enable for all. */
54 
55  /* Disable vert tag on faces_b */
56  for (uint i = 0; i < faces_b_len; i++) {
57  BMLoop *l_iter, *l_first;
58  l_iter = l_first = BM_FACE_FIRST_LOOP(faces_b[i]);
59  do {
61  } while ((l_iter = l_iter->next) != l_first);
62  }
63 
64  BLI_buffer_declare_static(BMLoop **, loop_split, 0, 128);
65 
66  /* Check shared verts ('faces_a' tag and disable) */
67  for (uint i = 0; i < faces_a_len; i++) {
68  BMLoop *l_iter, *l_first;
69  l_iter = l_first = BM_FACE_FIRST_LOOP(faces_a[i]);
70  do {
71  if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
72  BMVert *v = l_iter->v;
73  /* Enable, since we may visit this vertex again on other faces */
75 
76  /* We know the vertex is shared, collect all vertices and split them off. */
77 
78  /* Fill 'loop_split' */
79  {
80  BMEdge *e_first, *e_iter;
81  e_iter = e_first = l_iter->e;
82  do {
83  if (e_iter->l != NULL) {
84  BMLoop *l_radial_first, *l_radial_iter;
85  l_radial_first = l_radial_iter = e_iter->l;
86  do {
87  if (l_radial_iter->v == v) {
88  if (filter_fn(l_radial_iter->f, user_data)) {
89  BLI_buffer_append(&loop_split, BMLoop *, l_radial_iter);
90  }
91  }
92  } while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first);
93  }
94  } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
95  }
96 
97  /* Perform the split */
98  BM_face_loop_separate_multi(bm, loop_split.data, loop_split.count);
99 
100  BLI_buffer_clear(&loop_split);
101  }
102  } while ((l_iter = l_iter->next) != l_first);
103  }
104 
105  BLI_buffer_free(&loop_split);
106 
107  MEM_freeN(faces_array_all);
108 }
#define BLI_buffer_append(buffer_, type_, val_)
Definition: BLI_buffer.h:50
#define BLI_buffer_declare_static(type_, name_, flag_, static_count_)
Definition: BLI_buffer.h:25
#define BLI_buffer_clear(buffer_)
Definition: BLI_buffer.h:54
#define BLI_buffer_free(name_)
Definition: BLI_buffer.h:94
unsigned int uint
Definition: BLI_sys_types.h:67
Read Guarded memory(de)allocation.
bool(* BMFaceFilterFunc)(const BMFace *, void *user_data)
Definition: bmesh_class.h:505
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
#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
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_MESH
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
BMVert * BM_face_loop_separate_multi(BMesh *bm, BMLoop **larr, int larr_len)
Definition: bmesh_mods.c:906
ATTR_WARN_UNUSED_RESULT const BMVert * v
void BM_mesh_separate_faces(BMesh *bm, BMFaceFilterFunc filter_fn, void *user_data)
BLI_INLINE BMEdge * bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void * user_data
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
struct BMLoop * l
Definition: bmesh_class.h:128
struct BMVert * v
Definition: bmesh_class.h:153
struct BMEdge * e
Definition: bmesh_class.h:164
struct BMLoop * radial_next
Definition: bmesh_class.h:204
struct BMFace * f
Definition: bmesh_class.h:171
struct BMLoop * next
Definition: bmesh_class.h:233
int totface
Definition: bmesh_class.h:297