Blender  V2.93
bmesh_separate.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 
24 #include <limits.h>
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "BLI_buffer.h"
29 #include "BLI_utildefines.h"
30 
31 #include "bmesh.h"
32 #include "bmesh_separate.h" /* own include */
33 #include "intern/bmesh_private.h"
34 
40 {
41  BMFace **faces_array_all = MEM_mallocN(bm->totface * sizeof(BMFace *), __func__);
42  /*
43  * - Create an array of faces based on 'filter_fn'.
44  * First part of array for match, for non-match.
45  *
46  * - Enable all vertex tags, then clear all tagged vertices from 'faces_b'.
47  *
48  * - Loop over 'faces_a', checking each vertex,
49  * splitting out any which aren't tagged (and therefor shared), disabling tags as we go.
50  */
51 
52  BMFace *f;
53  BMIter iter;
54 
55  uint faces_a_len = 0;
56  uint faces_b_len = 0;
57  {
58  int i_a = 0;
59  int i_b = bm->totface;
60  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
61  faces_array_all[filter_fn(f, user_data) ? i_a++ : --i_b] = f;
62  }
63  faces_a_len = i_a;
64  faces_b_len = bm->totface - i_a;
65  }
66 
67  BMFace **faces_a = faces_array_all;
68  BMFace **faces_b = faces_array_all + faces_a_len;
69 
70  /* Enable for all */
72 
73  /* Disable vert tag on faces_b */
74  for (uint i = 0; i < faces_b_len; i++) {
75  BMLoop *l_iter, *l_first;
76  l_iter = l_first = BM_FACE_FIRST_LOOP(faces_b[i]);
77  do {
79  } while ((l_iter = l_iter->next) != l_first);
80  }
81 
82  BLI_buffer_declare_static(BMLoop **, loop_split, 0, 128);
83 
84  /* Check shared verts ('faces_a' tag and disable) */
85  for (uint i = 0; i < faces_a_len; i++) {
86  BMLoop *l_iter, *l_first;
87  l_iter = l_first = BM_FACE_FIRST_LOOP(faces_a[i]);
88  do {
89  if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
90  BMVert *v = l_iter->v;
91  /* Enable, since we may visit this vertex again on other faces */
93 
94  /* We know the vertex is shared, collect all vertices and split them off. */
95 
96  /* Fill 'loop_split' */
97  {
98  BMEdge *e_first, *e_iter;
99  e_iter = e_first = l_iter->e;
100  do {
101  if (e_iter->l != NULL) {
102  BMLoop *l_radial_first, *l_radial_iter;
103  l_radial_first = l_radial_iter = e_iter->l;
104  do {
105  if (l_radial_iter->v == v) {
106  if (filter_fn(l_radial_iter->f, user_data)) {
107  BLI_buffer_append(&loop_split, BMLoop *, l_radial_iter);
108  }
109  }
110  } while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first);
111  }
112  } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
113  }
114 
115  /* Perform the split */
116  BM_face_loop_separate_multi(bm, loop_split.data, loop_split.count);
117 
118  BLI_buffer_clear(&loop_split);
119  }
120  } while ((l_iter = l_iter->next) != l_first);
121  }
122 
123  BLI_buffer_free(&loop_split);
124 
125  MEM_freeN(faces_array_all);
126 }
#define BLI_buffer_append(buffer_, type_, val_)
Definition: BLI_buffer.h:64
#define BLI_buffer_declare_static(type_, name_, flag_, static_count_)
Definition: BLI_buffer.h:39
#define BLI_buffer_clear(buffer_)
Definition: BLI_buffer.h:68
#define BLI_buffer_free(name_)
Definition: BLI_buffer.h:92
unsigned int uint
Definition: BLI_sys_types.h:83
Read Guarded memory(de)allocation.
bool(* BMFaceFilterFunc)(const BMFace *, void *user_data)
Definition: bmesh_class.h:505
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:553
#define BM_elem_flag_disable(ele, hflag)
Definition: bmesh_inline.h:29
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:28
#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:1107
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:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
struct BMLoop * l
Definition: bmesh_class.h:140
struct BMVert * v
Definition: bmesh_class.h:165
struct BMEdge * e
Definition: bmesh_class.h:176
struct BMLoop * radial_next
Definition: bmesh_class.h:216
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245
int totface
Definition: bmesh_class.h:297