Blender  V3.3
bmesh_edgenet.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include <limits.h>
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "BLI_alloca.h"
14 #include "BLI_linklist.h"
15 #include "BLI_mempool.h"
16 #include "BLI_utildefines.h"
17 
18 #include "bmesh.h"
19 #include "bmesh_edgenet.h" /* own include */
20 
21 #include "BLI_strict_flags.h" /* keep last */
22 
23 /* Struct for storing a path of verts walked over */
24 typedef struct VertNetInfo {
25  BMVert *prev; /* previous vertex */
26  int pass; /* path scanning pass value, for internal calculation */
27  int face; /* face index connected to the edge between this and the previous vert */
28  int flag; /* flag */
30 
31 enum {
33 };
34 
38 static bool bm_edge_step_ok(BMEdge *e)
39 {
40  return BM_elem_flag_test(e, BM_ELEM_TAG) && (ELEM(e->l, NULL, e->l->radial_next));
41 }
42 
43 static int bm_edge_face(BMEdge *e)
44 {
45  return e->l ? BM_elem_index_get(e->l->f) : -1;
46 }
47 
52  LinkNode **edge_queue,
53  BLI_mempool *edge_queue_pool)
54 {
55  BMEdge *e;
56  BMIter iter;
57 
58  while (*edge_queue) {
59  e = BLI_linklist_pop_pool(edge_queue, edge_queue_pool);
60  if (bm_edge_step_ok(e)) {
61  return e;
62  }
63  }
64 
65  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
66  if (bm_edge_step_ok(e)) {
67  return e;
68  }
69  }
70 
71  return NULL;
72 }
73 
81  LinkNode **v_ls,
82  VertNetInfo *vnet_info,
83  BLI_mempool *path_pool)
84 {
85  VertNetInfo *vn = &vnet_info[BM_elem_index_get(v)];
86  const int pass = vn->pass;
87  uint v_ls_tot = 0;
88 
89  do {
90  BLI_linklist_prepend_pool(v_ls, v, path_pool);
91  v_ls_tot += 1;
92  v = vn->prev;
93  vn = &vnet_info[BM_elem_index_get(v)];
94  } while (vn->pass == pass);
95 
96  return v_ls_tot;
97 }
98 
104 {
105  /* vert order doesn't matter */
106  uint v_ls_tot = 0;
107  LinkNode *v_ls = NULL;
108  BMVert *v_pair[2] = {v1, v2};
109  uint i;
110 
111  for (i = 0; i < 2; i++) {
112  BMVert *v = v_pair[i];
113  VertNetInfo *vn = &vnet_info[BM_elem_index_get(v)];
114  const int pass = vn->pass;
115  do {
117  v_ls_tot += 1;
118  v = vn->prev;
119  vn = &vnet_info[BM_elem_index_get(v)];
120  } while (vn->pass == pass);
121  }
122 
123  if (v_ls_tot) {
124  BMVert **vert_arr = BLI_array_alloca(vert_arr, v_ls_tot);
125  LinkNode *v_lnk;
126  for (i = 0, v_lnk = v_ls; i < v_ls_tot; v_lnk = v_lnk->next, i++) {
127  vert_arr[i] = v_lnk->link;
128  }
129 
130  return BM_face_exists_overlap_subset(vert_arr, (int)v_ls_tot);
131  }
132  return false;
133 }
134 
138 static BMFace *bm_edgenet_face_from_path(BMesh *bm, LinkNode *path, const uint path_len)
139 {
140  BMFace *f;
141  LinkNode *v_lnk;
142  int i;
143  bool ok;
144 
145  BMVert **vert_arr = BLI_array_alloca(vert_arr, path_len);
146  BMEdge **edge_arr = BLI_array_alloca(edge_arr, path_len);
147 
148  for (v_lnk = path, i = 0; v_lnk; v_lnk = v_lnk->next, i++) {
149  vert_arr[i] = v_lnk->link;
150  }
151 
152  ok = BM_edges_from_verts(edge_arr, vert_arr, i);
153  BLI_assert(ok);
154  UNUSED_VARS_NDEBUG(ok);
155 
156  /* no need for this, we do overlap checks before allowing the path to be used */
157 #if 0
158  if (BM_face_exists_multi(vert_arr, edge_arr, path_len)) {
159  return NULL;
160  }
161 #endif
162 
163  f = BM_face_create(bm, vert_arr, edge_arr, (int)path_len, NULL, BM_CREATE_NOP);
164 
165  return f;
166 }
167 
174  LinkNode **v_ls,
175  VertNetInfo *vnet_info,
176  BLI_mempool *path_pool)
177 {
178  const VertNetInfo *vn_curr;
179 
180  BMEdge *e;
181  BMIter iter;
182  uint tot;
183  uint v_ls_tot;
184 
185 begin:
186  tot = 0;
187  v_ls_tot = 0;
188  vn_curr = &vnet_info[BM_elem_index_get(v_curr)];
189 
190  BM_ITER_ELEM (e, &iter, v_curr, BM_EDGES_OF_VERT) {
191  BMVert *v_next = BM_edge_other_vert(e, v_curr);
192  if (v_next != vn_curr->prev) {
193  if (bm_edge_step_ok(e)) {
194  VertNetInfo *vn_next = &vnet_info[BM_elem_index_get(v_next)];
195 
196  /* check we're not looping back on ourselves */
197  if (vn_curr->pass != vn_next->pass) {
198 
199  if (vn_curr->pass == -vn_next->pass) {
200  if ((vn_curr->flag & VNINFO_FLAG_IS_MIXFACE) ||
201  (vn_next->flag & VNINFO_FLAG_IS_MIXFACE)) {
202  /* found connecting edge */
203  if (bm_edgenet_path_check_overlap(v_curr, v_next, vnet_info) == false) {
204  return e;
205  }
206  }
207  }
208  else {
209  vn_next->face = bm_edge_face(e);
210  vn_next->pass = vn_curr->pass;
211  vn_next->prev = v_curr;
212 
213  /* flush flag down the path */
214  vn_next->flag &= ~VNINFO_FLAG_IS_MIXFACE;
215  if ((vn_curr->flag & VNINFO_FLAG_IS_MIXFACE) || (vn_next->face == -1) ||
216  (vn_next->face != vn_curr->face)) {
217  vn_next->flag |= VNINFO_FLAG_IS_MIXFACE;
218  }
219 
220  /* add to the list! */
221  BLI_linklist_prepend_pool(v_ls, v_next, path_pool);
222  v_ls_tot += 1;
223  }
224  }
225  }
226  tot += 1;
227  }
228  }
229 
230  /* trick to walk along wire-edge paths */
231  if (v_ls_tot == 1 && tot == 1) {
232  v_curr = BLI_linklist_pop_pool(v_ls, path_pool);
233  /* avoid recursion, can crash on very large nets */
234 #if 0
235  bm_edgenet_path_step(v_curr, v_ls, vnet_info, path_pool);
236 #else
237  goto begin;
238 #endif
239  }
240 
241  return NULL;
242 }
243 
250  const int pass_nr,
251  const uint path_cost_max,
252  uint *r_path_len,
253  uint *r_path_cost,
254  VertNetInfo *vnet_info,
255  BLI_mempool *path_pool)
256 {
257  VertNetInfo *vn_1, *vn_2;
258  const int f_index = bm_edge_face(e);
259  bool found;
260 
261  LinkNode *v_ls_prev = NULL;
262  LinkNode *v_ls_next = NULL;
263 
264  uint path_cost_accum = 0;
265 
267 
268  *r_path_len = 0;
269  *r_path_cost = 0;
270 
271  vn_1 = &vnet_info[BM_elem_index_get(e->v1)];
272  vn_2 = &vnet_info[BM_elem_index_get(e->v2)];
273 
274  vn_1->pass = pass_nr;
275  vn_2->pass = -pass_nr;
276 
277  vn_1->prev = e->v2;
278  vn_2->prev = e->v1;
279 
280  vn_1->face = vn_2->face = f_index;
281 
282  vn_1->flag = vn_2->flag = (f_index == -1) ? VNINFO_FLAG_IS_MIXFACE : 0;
283 
284  /* Prime the search-list. */
285  BLI_linklist_prepend_pool(&v_ls_prev, e->v1, path_pool);
286  BLI_linklist_prepend_pool(&v_ls_prev, e->v2, path_pool);
287 
288  do {
289  found = false;
290 
291  /* no point to continue, we're over budget */
292  if (path_cost_accum >= path_cost_max) {
293  BLI_linklist_free_pool(v_ls_next, NULL, path_pool);
294  BLI_linklist_free_pool(v_ls_prev, NULL, path_pool);
295  return NULL;
296  }
297 
298  while (v_ls_prev) {
299  const LinkNode *v_ls_next_old = v_ls_next;
300  BMVert *v = BLI_linklist_pop_pool(&v_ls_prev, path_pool);
301  BMEdge *e_found = bm_edgenet_path_step(v, &v_ls_next, vnet_info, path_pool);
302 
303  if (e_found) {
304  LinkNode *path = NULL;
305  uint path_len;
306  BLI_linklist_free_pool(v_ls_next, NULL, path_pool);
307  BLI_linklist_free_pool(v_ls_prev, NULL, path_pool);
308 
309  // BLI_assert(BLI_mempool_len(path_pool) == 0);
310 
311  path_len = bm_edgenet_path_from_pass(e_found->v1, &path, vnet_info, path_pool);
312  BLI_linklist_reverse(&path);
313  path_len += bm_edgenet_path_from_pass(e_found->v2, &path, vnet_info, path_pool);
314  *r_path_len = path_len;
315  *r_path_cost = path_cost_accum;
316  return path;
317  }
318 
319  /* check if a change was made */
320  if (v_ls_next_old != v_ls_next) {
321  found = true;
322  }
323  }
324  BLI_assert(v_ls_prev == NULL);
325 
326  path_cost_accum++;
327 
328  /* swap */
329  v_ls_prev = v_ls_next;
330  v_ls_next = NULL;
331 
332  } while (found);
333 
334  BLI_assert(v_ls_prev == NULL);
335  BLI_assert(v_ls_next == NULL);
336 
337  /* tag not to search again */
339 
340  return NULL;
341 }
342 
348  int *pass_nr,
349  uint path_cost_max,
350  uint *r_path_len,
351  uint *r_path_cost,
352  VertNetInfo *vnet_info,
353  BLI_mempool *path_pool)
354 {
355  LinkNode *path;
356  uint path_cost;
357 
358  path = bm_edgenet_path_calc(
359  e, *pass_nr, path_cost_max, r_path_len, &path_cost, vnet_info, path_pool);
360  (*pass_nr)++;
361 
362  if (path == NULL) {
363  return NULL;
364  }
365  if (path_cost < 1) {
366  /* any face that takes 1 iteration to find we consider valid */
367  return path;
368  }
369 
370  /* Check every edge to see if any can give a better path.
371  * This avoids very strange/long paths from being created. */
372 
373  const uint path_len = *r_path_len;
374  uint i, i_prev;
375  BMVert **vert_arr = BLI_array_alloca(vert_arr, path_len);
376  LinkNode *v_lnk;
377 
378  for (v_lnk = path, i = 0; v_lnk; v_lnk = v_lnk->next, i++) {
379  vert_arr[i] = v_lnk->link;
380  }
381 
382  i_prev = path_len - 1;
383  for (i = 0; i < path_len; i++) {
384  BMEdge *e_other = BM_edge_exists(vert_arr[i], vert_arr[i_prev]);
385  if (e_other != e) {
386  LinkNode *path_test;
387  uint path_len_test;
388  uint path_cost_test;
389 
390  path_test = bm_edgenet_path_calc(
391  e_other, *pass_nr, path_cost, &path_len_test, &path_cost_test, vnet_info, path_pool);
392  (*pass_nr)++;
393 
394  if (path_test) {
395  BLI_assert(path_cost_test < path_cost);
396 
397  BLI_linklist_free_pool(path, NULL, path_pool);
398  path = path_test;
399  *r_path_len = path_len_test;
400  *r_path_cost = path_cost_test;
401  path_cost = path_cost_test;
402  }
403  }
404 
405  i_prev = i;
406  }
407 
408  return path;
409 }
410 
411 void BM_mesh_edgenet(BMesh *bm, const bool use_edge_tag, const bool use_new_face_tag)
412 {
413  VertNetInfo *vnet_info = MEM_callocN(sizeof(*vnet_info) * (size_t)bm->totvert, __func__);
414  BLI_mempool *edge_queue_pool = BLI_mempool_create(sizeof(LinkNode), 0, 512, BLI_MEMPOOL_NOP);
415  BLI_mempool *path_pool = BLI_mempool_create(sizeof(LinkNode), 0, 512, BLI_MEMPOOL_NOP);
416  LinkNode *edge_queue = NULL;
417 
418  BMEdge *e;
419  BMIter iter;
420 
421  int pass_nr = 1;
422 
423  if (use_edge_tag == false) {
424  BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
426  }
427  }
428 
430 
431  while (true) {
432  LinkNode *path = NULL;
433  uint path_len;
434  uint path_cost;
435 
436  e = bm_edgenet_edge_get_next(bm, &edge_queue, edge_queue_pool);
437  if (e == NULL) {
438  break;
439  }
440 
441  BLI_assert(bm_edge_step_ok(e) == true);
442 
444  e, &pass_nr, UINT_MAX, &path_len, &path_cost, vnet_info, path_pool);
445 
446  if (path) {
447  BMFace *f = bm_edgenet_face_from_path(bm, path, path_len);
448  /* queue edges to operate on */
449  BMLoop *l_first, *l_iter;
450  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
451  do {
452  if (bm_edge_step_ok(l_iter->e)) {
453  BLI_linklist_prepend_pool(&edge_queue, l_iter->e, edge_queue_pool);
454  }
455  } while ((l_iter = l_iter->next) != l_first);
456 
457  if (use_new_face_tag) {
459  }
460 
461  /* the face index only needs to be unique, not kept valid */
462  BM_elem_index_set(f, bm->totface - 1); /* set_dirty */
463  }
464 
465  BLI_linklist_free_pool(path, NULL, path_pool);
466  BLI_assert(BLI_mempool_len(path_pool) == 0);
467  }
468 
470 
471  BLI_mempool_destroy(edge_queue_pool);
472  BLI_mempool_destroy(path_pool);
473  MEM_freeN(vnet_info);
474 }
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:22
#define BLI_assert(a)
Definition: BLI_assert.h:46
@ BLI_MEMPOOL_NOP
Definition: BLI_mempool.h:99
int BLI_mempool_len(const BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:434
BLI_mempool * BLI_mempool_create(unsigned int esize, unsigned int elem_num, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
Definition: BLI_mempool.c:253
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:707
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
_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 GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint vn
_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_LOOP
Definition: bmesh_class.h:385
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len)
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
@ BM_CREATE_NOP
Definition: bmesh_core.h:12
static int bm_edge_face(BMEdge *e)
Definition: bmesh_edgenet.c:43
static bool bm_edgenet_path_check_overlap(BMVert *v1, BMVert *v2, VertNetInfo *vnet_info)
void BM_mesh_edgenet(BMesh *bm, const bool use_edge_tag, const bool use_new_face_tag)
static LinkNode * bm_edgenet_path_calc_best(BMEdge *e, int *pass_nr, uint path_cost_max, uint *r_path_len, uint *r_path_cost, VertNetInfo *vnet_info, BLI_mempool *path_pool)
static bool bm_edge_step_ok(BMEdge *e)
Definition: bmesh_edgenet.c:38
struct VertNetInfo VertNetInfo
static BMEdge * bm_edgenet_path_step(BMVert *v_curr, LinkNode **v_ls, VertNetInfo *vnet_info, BLI_mempool *path_pool)
static BMFace * bm_edgenet_face_from_path(BMesh *bm, LinkNode *path, const uint path_len)
static LinkNode * bm_edgenet_path_calc(BMEdge *e, const int pass_nr, const uint path_cost_max, uint *r_path_len, uint *r_path_cost, VertNetInfo *vnet_info, BLI_mempool *path_pool)
static uint bm_edgenet_path_from_pass(BMVert *v, LinkNode **v_ls, VertNetInfo *vnet_info, BLI_mempool *path_pool)
Definition: bmesh_edgenet.c:80
static BMEdge * bm_edgenet_edge_get_next(BMesh *bm, LinkNode **edge_queue, BLI_mempool *edge_queue_pool)
Definition: bmesh_edgenet.c:51
@ VNINFO_FLAG_IS_MIXFACE
Definition: bmesh_edgenet.c:32
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#define BM_elem_flag_disable(ele, hflag)
Definition: bmesh_inline.h:15
#define BM_elem_flag_set(ele, hflag, val)
Definition: bmesh_inline.h:16
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:111
#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_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_EDGES_OF_MESH
@ BM_EDGES_OF_VERT
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.cc:446
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1553
bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
Definition: bmesh_query.c:1692
bool BM_face_exists_overlap_subset(BMVert **varr, const int len)
Definition: bmesh_query.c:1851
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define UINT_MAX
Definition: hash_md5.c:43
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
BMVert * v1
Definition: bmesh_class.h:122
BMVert * v2
Definition: bmesh_class.h:122
struct BMEdge * e
Definition: bmesh_class.h:164
struct BMLoop * next
Definition: bmesh_class.h:233
int totvert
Definition: bmesh_class.h:297
char elem_index_dirty
Definition: bmesh_class.h:305
int totface
Definition: bmesh_class.h:297
void * link
Definition: BLI_linklist.h:24
struct LinkNode * next
Definition: BLI_linklist.h:23
BMVert * prev
Definition: bmesh_edgenet.c:25