Blender  V3.3
bmesh_beautify.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
18 #include "BLI_heap.h"
19 #include "BLI_math.h"
21 
22 #include "MEM_guardedalloc.h"
23 
24 #include "bmesh.h"
25 #include "bmesh_beautify.h" /* own include */
26 
27 // #define DEBUG_TIME
28 
29 #ifdef DEBUG_TIME
30 # include "PIL_time.h"
31 # include "PIL_time_utildefines.h"
32 #endif
33 
34 /* -------------------------------------------------------------------- */
35 /* GSet for edge rotation */
36 
37 typedef struct EdRotState {
41  int v_pair[2];
48  int f_pair[2];
50 
51 #if 0
52 /* use BLI_ghashutil_inthash_v4 direct */
53 static uint erot_gsetutil_hash(const void *ptr)
54 {
55  const EdRotState *e_state = (const EdRotState *)ptr;
56  return BLI_ghashutil_inthash_v4(&e_state->v_pair[0]);
57 }
58 #endif
59 #if 0
60 static int erot_gsetutil_cmp(const void *a, const void *b)
61 {
62  const EdRotState *e_state_a = (const EdRotState *)a;
63  const EdRotState *e_state_b = (const EdRotState *)b;
64  if (e_state_a->v_pair[0] < e_state_b->v_pair[0]) {
65  return -1;
66  }
67  if (e_state_a->v_pair[0] > e_state_b->v_pair[0]) {
68  return 1;
69  }
70  if (e_state_a->v_pair[1] < e_state_b->v_pair[1]) {
71  return -1;
72  }
73  if (e_state_a->v_pair[1] > e_state_b->v_pair[1]) {
74  return 1;
75  }
76  if (e_state_a->f_pair[0] < e_state_b->f_pair[0]) {
77  return -1;
78  }
79  if (e_state_a->f_pair[0] > e_state_b->f_pair[0]) {
80  return 1;
81  }
82  if (e_state_a->f_pair[1] < e_state_b->f_pair[1]) {
83  return -1;
84  }
85  if (e_state_a->f_pair[1] > e_state_b->f_pair[1]) {
86  return 1;
87  }
88  return 0;
89 }
90 #endif
91 static GSet *erot_gset_new(void)
92 {
94 }
95 
96 /* ensure v0 is smaller */
97 #define EDGE_ORD(v0, v1) \
98  if (v0 > v1) { \
99  SWAP(int, v0, v1); \
100  } \
101  (void)0
102 
103 static void erot_state_ex(const BMEdge *e, int v_index[2], int f_index[2])
104 {
106  BLI_assert(BM_vert_in_edge(e, e->l->prev->v) == false);
107  BLI_assert(BM_vert_in_edge(e, e->l->radial_next->prev->v) == false);
108 
109  /* verts of the edge */
110  v_index[0] = BM_elem_index_get(e->v1);
111  v_index[1] = BM_elem_index_get(e->v2);
112  EDGE_ORD(v_index[0], v_index[1]);
113 
114  /* verts of each of the 2 faces attached to this edge
115  * (that are not a part of this edge) */
116  f_index[0] = BM_elem_index_get(e->l->prev->v);
117  f_index[1] = BM_elem_index_get(e->l->radial_next->prev->v);
118  EDGE_ORD(f_index[0], f_index[1]);
119 }
120 
121 static void erot_state_current(const BMEdge *e, EdRotState *e_state)
122 {
123  erot_state_ex(e, e_state->v_pair, e_state->f_pair);
124 }
125 
126 static void erot_state_alternate(const BMEdge *e, EdRotState *e_state)
127 {
128  erot_state_ex(e, e_state->f_pair, e_state->v_pair);
129 }
130 
131 /* -------------------------------------------------------------------- */
132 /* Calculate the improvement of rotating the edge */
133 
134 static float bm_edge_calc_rotate_beauty__area(const float v1[3],
135  const float v2[3],
136  const float v3[3],
137  const float v4[3],
138  const bool lock_degenerate)
139 {
140  /* not a loop (only to be able to break out) */
141  do {
142  float v1_xy[2], v2_xy[2], v3_xy[2], v4_xy[2];
143 
144  /* first get the 2d values */
145  {
146  const float eps = 1e-5;
147  float no_a[3], no_b[3];
148  float no[3];
149  float axis_mat[3][3];
150  float no_scale;
151  cross_tri_v3(no_a, v2, v3, v4);
152  cross_tri_v3(no_b, v2, v4, v1);
153 
154  // printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
155  BLI_assert((ELEM(v1, v2, v3, v4) == false) && (ELEM(v2, v1, v3, v4) == false) &&
156  (ELEM(v3, v1, v2, v4) == false) && (ELEM(v4, v1, v2, v3) == false));
157 
158  add_v3_v3v3(no, no_a, no_b);
159  if (UNLIKELY((no_scale = normalize_v3(no)) == 0.0f)) {
160  break;
161  }
162 
163  axis_dominant_v3_to_m3(axis_mat, no);
164  mul_v2_m3v3(v1_xy, axis_mat, v1);
165  mul_v2_m3v3(v2_xy, axis_mat, v2);
166  mul_v2_m3v3(v3_xy, axis_mat, v3);
167  mul_v2_m3v3(v4_xy, axis_mat, v4);
168 
184  if (!(signum_i_ex(cross_tri_v2(v2_xy, v3_xy, v4_xy) / no_scale, eps) +
185  signum_i_ex(cross_tri_v2(v2_xy, v4_xy, v1_xy) / no_scale, eps))) {
186  break;
187  }
188  }
189 
197  v1_xy, v2_xy, v3_xy, v4_xy, lock_degenerate, NULL);
198  } while (false);
199 
200  return FLT_MAX;
201 }
202 
203 static float bm_edge_calc_rotate_beauty__angle(const float v1[3],
204  const float v2[3],
205  const float v3[3],
206  const float v4[3])
207 {
208  /* not a loop (only to be able to break out) */
209  do {
210  float no_a[3], no_b[3];
211  float angle_24, angle_13;
212 
213  /* edge (2-4), current state */
214  normal_tri_v3(no_a, v2, v3, v4);
215  normal_tri_v3(no_b, v2, v4, v1);
216  angle_24 = angle_normalized_v3v3(no_a, no_b);
217 
218  /* edge (1-3), new state */
219  /* only check new state for degenerate outcome */
220  if ((normal_tri_v3(no_a, v1, v2, v3) == 0.0f) || (normal_tri_v3(no_b, v1, v3, v4) == 0.0f)) {
221  break;
222  }
223  angle_13 = angle_normalized_v3v3(no_a, no_b);
224 
225  return angle_13 - angle_24;
226  } while (false);
227 
228  return FLT_MAX;
229 }
230 
232  const BMVert *v2,
233  const BMVert *v3,
234  const BMVert *v4,
235  const short flag,
236  const short method)
237 {
238  /* not a loop (only to be able to break out) */
239  do {
240  if (flag & VERT_RESTRICT_TAG) {
241  const BMVert *v_a = v1, *v_b = v3;
243  break;
244  }
245  }
246 
247  if (UNLIKELY(v1 == v3)) {
248  // printf("This should never happen, but does sometimes!\n");
249  break;
250  }
251 
252  switch (method) {
253  case 0:
255  v1->co, v2->co, v3->co, v4->co, flag & EDGE_RESTRICT_DEGENERATE);
256  default:
257  return bm_edge_calc_rotate_beauty__angle(v1->co, v2->co, v3->co, v4->co);
258  }
259  } while (false);
260 
261  return FLT_MAX;
262 }
263 
264 static float bm_edge_calc_rotate_beauty(const BMEdge *e, const short flag, const short method)
265 {
266  const BMVert *v1, *v2, *v3, *v4;
267  v1 = e->l->prev->v; /* First vert co */
268  v2 = e->l->v; /* `e->v1` or `e->v2`. */
269  v3 = e->l->radial_next->prev->v; /* Second vert co */
270  v4 = e->l->next->v; /* `e->v1` or `e->v2`. */
271 
272  return BM_verts_calc_rotate_beauty(v1, v2, v3, v4, flag, method);
273 }
274 
275 /* -------------------------------------------------------------------- */
276 /* Update the edge cost of rotation in the heap */
277 
278 BLI_INLINE bool edge_in_array(const BMEdge *e, const BMEdge **edge_array, const int edge_array_len)
279 {
280  const int index = BM_elem_index_get(e);
281  return ((index >= 0) && (index < edge_array_len) && (e == edge_array[index]));
282 }
283 
284 /* recalc an edge in the heap (surrounding geometry has changed) */
286  Heap *eheap,
287  HeapNode **eheap_table,
288  GSet **edge_state_arr,
289  /* only for testing the edge is in the array */
290  const BMEdge **edge_array,
291  const int edge_array_len,
292 
293  const short flag,
294  const short method)
295 {
296  if (edge_in_array(e, edge_array, edge_array_len)) {
297  const int i = BM_elem_index_get(e);
298  GSet *e_state_set = edge_state_arr[i];
299 
300  if (eheap_table[i]) {
301  BLI_heap_remove(eheap, eheap_table[i]);
302  eheap_table[i] = NULL;
303  }
304 
305  /* check if we can add it back */
306  BLI_assert(BM_edge_is_manifold(e) == true);
307 
308  /* check we're not moving back into a state we have been in before */
309  if (e_state_set != NULL) {
310  EdRotState e_state_alt;
311  erot_state_alternate(e, &e_state_alt);
312  if (BLI_gset_haskey(e_state_set, (void *)&e_state_alt)) {
313  // printf(" skipping, we already have this state\n");
314  return;
315  }
316  }
317 
318  {
319  /* recalculate edge */
320  const float cost = bm_edge_calc_rotate_beauty(e, flag, method);
321  if (cost < 0.0f) {
322  eheap_table[i] = BLI_heap_insert(eheap, cost, e);
323  }
324  else {
325  eheap_table[i] = NULL;
326  }
327  }
328  }
329 }
330 
331 /* we have rotated an edge, tag other edges and clear this one */
333  Heap *eheap,
334  HeapNode **eheap_table,
335  GSet **edge_state_arr,
336  const BMEdge **edge_array,
337  const int edge_array_len,
338  /* only for testing the edge is in the array */
339  const short flag,
340  const short method)
341 {
342  int i;
343 
344  BMEdge *e_arr[4] = {
345  e->l->next->e,
346  e->l->prev->e,
347  e->l->radial_next->next->e,
348  e->l->radial_next->prev->e,
349  };
350 
351  BLI_assert(e->l->f->len == 3 && e->l->radial_next->f->len == 3);
352 
354 
355  for (i = 0; i < 4; i++) {
357  e_arr[i], eheap, eheap_table, edge_state_arr, edge_array, edge_array_len, flag, method);
358  }
359 }
360 
361 /* -------------------------------------------------------------------- */
362 /* Beautify Fill */
363 
365  BMEdge **edge_array,
366  const int edge_array_len,
367  const short flag,
368  const short method,
369  const short oflag_edge,
370  const short oflag_face)
371 {
372  Heap *eheap; /* edge heap */
373  HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */
374 
375  GSet **edge_state_arr = MEM_callocN((size_t)edge_array_len * sizeof(GSet *), __func__);
376  BLI_mempool *edge_state_pool = BLI_mempool_create(sizeof(EdRotState), 0, 512, BLI_MEMPOOL_NOP);
377  int i;
378 
379 #ifdef DEBUG_TIME
380  TIMEIT_START(beautify_fill);
381 #endif
382 
383  eheap = BLI_heap_new_ex((uint)edge_array_len);
384  eheap_table = MEM_mallocN(sizeof(HeapNode *) * (size_t)edge_array_len, __func__);
385 
386  /* build heap */
387  for (i = 0; i < edge_array_len; i++) {
388  BMEdge *e = edge_array[i];
389  const float cost = bm_edge_calc_rotate_beauty(e, flag, method);
390  if (cost < 0.0f) {
391  eheap_table[i] = BLI_heap_insert(eheap, cost, e);
392  }
393  else {
394  eheap_table[i] = NULL;
395  }
396 
397  BM_elem_index_set(e, i); /* set_dirty */
398  }
400 
401  while (BLI_heap_is_empty(eheap) == false) {
402  BMEdge *e = BLI_heap_pop_min(eheap);
403  i = BM_elem_index_get(e);
404  eheap_table[i] = NULL;
405 
407 
409 
411 
412  if (LIKELY(e)) {
413  GSet *e_state_set = edge_state_arr[i];
414 
415  /* add the new state into the set so we don't move into this state again
416  * NOTE: we could add the previous state too but this isn't essential)
417  * for avoiding eternal loops */
418  EdRotState *e_state = BLI_mempool_alloc(edge_state_pool);
419  erot_state_current(e, e_state);
420  if (UNLIKELY(e_state_set == NULL)) {
421  edge_state_arr[i] = e_state_set = erot_gset_new(); /* store previous state */
422  }
423  BLI_assert(BLI_gset_haskey(e_state_set, (void *)e_state) == false);
424  BLI_gset_insert(e_state_set, e_state);
425 
426  // printf(" %d -> %d, %d\n", i, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2));
427 
428  /* maintain the index array */
429  edge_array[i] = e;
430  BM_elem_index_set(e, i);
431 
432  /* recalculate faces connected on the heap */
434  eheap,
435  eheap_table,
436  edge_state_arr,
437  (const BMEdge **)edge_array,
438  edge_array_len,
439  flag,
440  method);
441 
442  /* update flags */
443  if (oflag_edge) {
444  BMO_edge_flag_enable(bm, e, oflag_edge);
445  }
446 
447  if (oflag_face) {
448  BMO_face_flag_enable(bm, e->l->f, oflag_face);
449  BMO_face_flag_enable(bm, e->l->radial_next->f, oflag_face);
450  }
451  }
452  }
453 
454  BLI_heap_free(eheap, NULL);
455  MEM_freeN(eheap_table);
456 
457  for (i = 0; i < edge_array_len; i++) {
458  if (edge_state_arr[i]) {
459  BLI_gset_free(edge_state_arr[i], NULL);
460  }
461  }
462 
463  MEM_freeN(edge_state_arr);
464  BLI_mempool_destroy(edge_state_pool);
465 
466 #ifdef DEBUG_TIME
467  TIMEIT_END(beautify_fill);
468 #endif
469 }
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_INLINE
struct GSet GSet
Definition: BLI_ghash.h:340
bool BLI_gset_haskey(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1007
#define BLI_ghashutil_inthash_v4_cmp
Definition: BLI_ghash.h:601
GSet * BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:947
#define BLI_ghashutil_inthash_v4(key)
Definition: BLI_ghash.h:590
void BLI_gset_insert(GSet *gs, void *key)
Definition: BLI_ghash.c:962
#define BLI_ghashutil_inthash_v4_p
Definition: BLI_ghash.h:592
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1037
A min-heap / priority queue ADT.
void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1)
Definition: BLI_heap.c:202
void void bool BLI_heap_is_empty(const Heap *heap) ATTR_NONNULL(1)
Definition: BLI_heap.c:279
void * BLI_heap_pop_min(Heap *heap) ATTR_NONNULL(1)
Definition: BLI_heap.c:301
Heap * BLI_heap_new_ex(unsigned int reserve_num) ATTR_WARN_UNUSED_RESULT
Definition: BLI_heap.c:182
HeapNode * BLI_heap_insert(Heap *heap, float value, void *ptr) ATTR_NONNULL(1)
Definition: BLI_heap.c:245
void void BLI_heap_remove(Heap *heap, HeapNode *node) ATTR_NONNULL(1
MINLINE int signum_i_ex(float a, float eps)
MINLINE float cross_tri_v2(const float v1[2], const float v2[2], const float v3[2])
void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:18
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
Normal to x,y matrix.
Definition: math_geom.c:3527
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:33
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
Definition: math_matrix.c:917
MINLINE float normalize_v3(float r[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:445
@ BLI_MEMPOOL_NOP
Definition: BLI_mempool.h:99
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_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
Definition: BLI_mempool.c:319
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:707
float BLI_polyfill_beautify_quad_rotate_calc_ex(const float v1[2], const float v2[2], const float v3[2], const float v4[2], bool lock_degenerate, float *r_area)
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNLIKELY(x)
#define ELEM(...)
#define LIKELY(x)
_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.
Platform independent time functions.
Utility defines for timing/benchmarks.
#define TIMEIT_START(var)
#define TIMEIT_END(var)
static void erot_state_alternate(const BMEdge *e, EdRotState *e_state)
static GSet * erot_gset_new(void)
BLI_INLINE bool edge_in_array(const BMEdge *e, const BMEdge **edge_array, const int edge_array_len)
void BM_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge_array_len, const short flag, const short method, const short oflag_edge, const short oflag_face)
float BM_verts_calc_rotate_beauty(const BMVert *v1, const BMVert *v2, const BMVert *v3, const BMVert *v4, const short flag, const short method)
static void erot_state_current(const BMEdge *e, EdRotState *e_state)
#define EDGE_ORD(v0, v1)
static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr, const BMEdge **edge_array, const int edge_array_len, const short flag, const short method)
static float bm_edge_calc_rotate_beauty__angle(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
static void erot_state_ex(const BMEdge *e, int v_index[2], int f_index[2])
struct EdRotState EdRotState
static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr, const BMEdge **edge_array, const int edge_array_len, const short flag, const short method)
static float bm_edge_calc_rotate_beauty__area(const float v1[3], const float v2[3], const float v3[3], const float v4[3], const bool lock_degenerate)
static float bm_edge_calc_rotate_beauty(const BMEdge *e, const short flag, const short method)
@ EDGE_RESTRICT_DEGENERATE
@ VERT_RESTRICT_TAG
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:111
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
ATTR_WARN_UNUSED_RESULT BMesh * bm
BMEdge * BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag)
Rotate Edge.
Definition: bmesh_mods.c:785
@ BM_EDGEROT_CHECK_EXISTS
Definition: bmesh_mods.h:248
#define BMO_edge_flag_enable(bm, e, oflag)
#define BMO_face_flag_enable(bm, e, oflag)
BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define BM_edge_face_count_is_equal(e, n)
Definition: bmesh_query.h:247
BLI_INLINE bool BM_vert_in_edge(const 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
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static unsigned a[3]
Definition: RandGen.cpp:78
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
const btScalar eps
Definition: poly34.cpp:11
float co[3]
Definition: bmesh_class.h:87
struct BMEdge * e
Definition: bmesh_class.h:97
char elem_index_dirty
Definition: bmesh_class.h:305
int v_pair[2]
int f_pair[2]
Definition: BLI_heap.c:43
PointerRNA * ptr
Definition: wm_files.c:3480