Blender  V2.93
bmesh_path.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 
25 #include "MEM_guardedalloc.h"
26 
27 #include "BLI_heap_simple.h"
28 #include "BLI_linklist.h"
29 #include "BLI_math.h"
30 
31 #include "bmesh.h"
32 #include "bmesh_path.h" /* own include */
33 
34 #define COST_INIT_MAX FLT_MAX
35 
36 /* -------------------------------------------------------------------- */
43 static float step_cost_3_v3_ex(
44  const float v1[3], const float v2[3], const float v3[3], bool skip_12, bool skip_23)
45 {
46  float d1[3], d2[3];
47 
48  /* The cost is based on the simple sum of the length of the two edges. */
49  sub_v3_v3v3(d1, v2, v1);
50  sub_v3_v3v3(d2, v3, v2);
51  const float cost_12 = normalize_v3(d1);
52  const float cost_23 = normalize_v3(d2);
53  const float cost = ((skip_12 ? 0.0f : cost_12) + (skip_23 ? 0.0f : cost_23));
54 
55  /* But is biased to give higher values to sharp turns, so that it will take paths with
56  * fewer "turns" when selecting between equal-weighted paths between the two edges. */
57  return cost * (1.0f + 0.5f * (2.0f - sqrtf(fabsf(dot_v3v3(d1, d2)))));
58 }
59 
60 static float step_cost_3_v3(const float v1[3], const float v2[3], const float v3[3])
61 {
62  return step_cost_3_v3_ex(v1, v2, v3, false, false);
63 }
64 
67 /* -------------------------------------------------------------------- */
71 static void verttag_add_adjacent(HeapSimple *heap,
72  BMVert *v_a,
73  BMVert **verts_prev,
74  float *cost,
75  const struct BMCalcPathParams *params)
76 {
77  const int v_a_index = BM_elem_index_get(v_a);
78 
79  {
80  BMIter eiter;
81  BMEdge *e;
82  /* Loop over faces of face, but do so by first looping over loops. */
83  BM_ITER_ELEM (e, &eiter, v_a, BM_EDGES_OF_VERT) {
84  BMVert *v_b = BM_edge_other_vert(e, v_a);
85  if (!BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
86  /* We know 'v_b' is not visited, check it out! */
87  const int v_b_index = BM_elem_index_get(v_b);
88  const float cost_cut = params->use_topology_distance ? 1.0f : len_v3v3(v_a->co, v_b->co);
89  const float cost_new = cost[v_a_index] + cost_cut;
90 
91  if (cost[v_b_index] > cost_new) {
92  cost[v_b_index] = cost_new;
93  verts_prev[v_b_index] = v_a;
94  BLI_heapsimple_insert(heap, cost_new, v_b);
95  }
96  }
97  }
98  }
99 
100  if (params->use_step_face) {
101  BMIter liter;
102  BMLoop *l;
103  /* Loop over faces of face, but do so by first looping over loops. */
104  BM_ITER_ELEM (l, &liter, v_a, BM_LOOPS_OF_VERT) {
105  if (l->f->len > 3) {
106  /* Skip loops on adjacent edges. */
107  BMLoop *l_iter = l->next->next;
108  do {
109  BMVert *v_b = l_iter->v;
110  if (!BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
111  /* We know 'v_b' is not visited, check it out! */
112  const int v_b_index = BM_elem_index_get(v_b);
113  const float cost_cut = params->use_topology_distance ? 1.0f :
114  len_v3v3(v_a->co, v_b->co);
115  const float cost_new = cost[v_a_index] + cost_cut;
116 
117  if (cost[v_b_index] > cost_new) {
118  cost[v_b_index] = cost_new;
119  verts_prev[v_b_index] = v_a;
120  BLI_heapsimple_insert(heap, cost_new, v_b);
121  }
122  }
123  } while ((l_iter = l_iter->next) != l->prev);
124  }
125  }
126  }
127 }
128 
130  BMVert *v_src,
131  BMVert *v_dst,
132  const struct BMCalcPathParams *params,
133  bool (*filter_fn)(BMVert *, void *user_data),
134  void *user_data)
135 {
136  LinkNode *path = NULL;
137  /* #BM_ELEM_TAG flag is used to store visited edges. */
138  BMVert *v;
139  BMIter viter;
140  HeapSimple *heap;
141  float *cost;
142  BMVert **verts_prev;
143  int i, totvert;
144 
145  /* Note, would pass #BM_EDGE except we are looping over all faces anyway. */
146  // BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG
147 
148  BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
149  BM_elem_flag_set(v, BM_ELEM_TAG, !filter_fn(v, user_data));
150  BM_elem_index_set(v, i); /* set_inline */
151  }
153 
154  /* Allocate. */
155  totvert = bm->totvert;
156  verts_prev = MEM_callocN(sizeof(*verts_prev) * totvert, __func__);
157  cost = MEM_mallocN(sizeof(*cost) * totvert, __func__);
158 
159  copy_vn_fl(cost, totvert, COST_INIT_MAX);
160 
161  /*
162  * Arrays are now filled as follows:
163  *
164  * As the search continues, `verts_prev[n]` will be the previous verts on the shortest
165  * path found so far to face `n`. #BM_ELEM_TAG is used to tag elements we have visited,
166  * `cost[n]` will contain the length of the shortest
167  * path to face n found so far, Finally, heap is a priority heap which is built on the
168  * the same data as the cost array, but inverted: it is a work-list of faces prioritized
169  * by the shortest path found so far to the face.
170  */
171 
172  /* Regular dijkstra shortest path, but over faces instead of vertices. */
173  heap = BLI_heapsimple_new();
174  BLI_heapsimple_insert(heap, 0.0f, v_src);
175  cost[BM_elem_index_get(v_src)] = 0.0f;
176 
177  while (!BLI_heapsimple_is_empty(heap)) {
178  v = BLI_heapsimple_pop_min(heap);
179 
180  if (v == v_dst) {
181  break;
182  }
183 
186  verttag_add_adjacent(heap, v, verts_prev, cost, params);
187  }
188  }
189 
190  if (v == v_dst) {
191  do {
192  BLI_linklist_prepend(&path, v);
193  } while ((v = verts_prev[BM_elem_index_get(v)]));
194  }
195 
196  MEM_freeN(verts_prev);
197  MEM_freeN(cost);
198  BLI_heapsimple_free(heap, NULL);
199 
200  return path;
201 }
202 
205 /* -------------------------------------------------------------------- */
209 static float edgetag_cut_cost_vert(BMEdge *e_a, BMEdge *e_b, BMVert *v)
210 {
211  BMVert *v1 = BM_edge_other_vert(e_a, v);
212  BMVert *v2 = BM_edge_other_vert(e_b, v);
213  return step_cost_3_v3(v1->co, v->co, v2->co);
214 }
215 
216 static float edgetag_cut_cost_face(BMEdge *e_a, BMEdge *e_b, BMFace *f)
217 {
218  float e_a_cent[3], e_b_cent[3], f_cent[3];
219 
220  mid_v3_v3v3(e_a_cent, e_a->v1->co, e_a->v1->co);
221  mid_v3_v3v3(e_b_cent, e_b->v1->co, e_b->v1->co);
222 
224 
225  return step_cost_3_v3(e_a_cent, e_b_cent, f_cent);
226 }
227 
229  BMEdge *e_a,
230  BMEdge **edges_prev,
231  float *cost,
232  const struct BMCalcPathParams *params)
233 {
234  const int e_a_index = BM_elem_index_get(e_a);
235 
236  /* Unlike vert/face, stepping faces disables scanning connected edges
237  * and only steps over faces (selecting a ring of edges instead of a loop). */
238  if (params->use_step_face == false || e_a->l == NULL) {
239  BMIter viter;
240  BMVert *v;
241 
242  BMIter eiter;
243  BMEdge *e_b;
244 
245  BM_ITER_ELEM (v, &viter, e_a, BM_VERTS_OF_EDGE) {
246 
247  /* Don't walk over previous vertex. */
248  if ((edges_prev[e_a_index]) && (BM_vert_in_edge(edges_prev[e_a_index], v))) {
249  continue;
250  }
251 
252  BM_ITER_ELEM (e_b, &eiter, v, BM_EDGES_OF_VERT) {
253  if (!BM_elem_flag_test(e_b, BM_ELEM_TAG)) {
254  /* We know 'e_b' is not visited, check it out! */
255  const int e_b_index = BM_elem_index_get(e_b);
256  const float cost_cut = params->use_topology_distance ?
257  1.0f :
258  edgetag_cut_cost_vert(e_a, e_b, v);
259  const float cost_new = cost[e_a_index] + cost_cut;
260 
261  if (cost[e_b_index] > cost_new) {
262  cost[e_b_index] = cost_new;
263  edges_prev[e_b_index] = e_a;
264  BLI_heapsimple_insert(heap, cost_new, e_b);
265  }
266  }
267  }
268  }
269  }
270  else {
271  BMLoop *l_first, *l_iter;
272 
273  l_iter = l_first = e_a->l;
274  do {
275  BMLoop *l_cycle_iter, *l_cycle_end;
276 
277  l_cycle_iter = l_iter->next;
278  l_cycle_end = l_iter;
279 
280  /* Good, but we need to allow this otherwise paths may fail to connect at all. */
281 #if 0
282  if (l_iter->f->len > 3) {
283  l_cycle_iter = l_cycle_iter->next;
284  l_cycle_end = l_cycle_end->prev;
285  }
286 #endif
287 
288  do {
289  BMEdge *e_b = l_cycle_iter->e;
290  if (!BM_elem_flag_test(e_b, BM_ELEM_TAG)) {
291  /* We know 'e_b' is not visited, check it out! */
292  const int e_b_index = BM_elem_index_get(e_b);
293  const float cost_cut = params->use_topology_distance ?
294  1.0f :
295  edgetag_cut_cost_face(e_a, e_b, l_iter->f);
296  const float cost_new = cost[e_a_index] + cost_cut;
297 
298  if (cost[e_b_index] > cost_new) {
299  cost[e_b_index] = cost_new;
300  edges_prev[e_b_index] = e_a;
301  BLI_heapsimple_insert(heap, cost_new, e_b);
302  }
303  }
304  } while ((l_cycle_iter = l_cycle_iter->next) != l_cycle_end);
305  } while ((l_iter = l_iter->radial_next) != l_first);
306  }
307 }
308 
310  BMEdge *e_src,
311  BMEdge *e_dst,
312  const struct BMCalcPathParams *params,
313  bool (*filter_fn)(BMEdge *, void *user_data),
314  void *user_data)
315 {
316  LinkNode *path = NULL;
317  /* #BM_ELEM_TAG flag is used to store visited edges. */
318  BMEdge *e;
319  BMIter eiter;
320  HeapSimple *heap;
321  float *cost;
322  BMEdge **edges_prev;
323  int i, totedge;
324 
325  /* Note, would pass #BM_EDGE except we are looping over all edges anyway. */
326  BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */);
327 
328  BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
329  BM_elem_flag_set(e, BM_ELEM_TAG, !filter_fn(e, user_data));
330  BM_elem_index_set(e, i); /* set_inline */
331  }
333 
334  /* Allocate. */
335  totedge = bm->totedge;
336  edges_prev = MEM_callocN(sizeof(*edges_prev) * totedge, __func__);
337  cost = MEM_mallocN(sizeof(*cost) * totedge, __func__);
338 
339  copy_vn_fl(cost, totedge, COST_INIT_MAX);
340 
341  /*
342  * Arrays are now filled as follows:
343  *
344  * As the search continues, `edges_prev[n]` will be the previous edge on the shortest
345  * path found so far to edge `n`. #BM_ELEM_TAG is used to tag elements we have visited,
346  * `cost[n]` will contain the length of the shortest
347  * path to edge n found so far, Finally, heap is a priority heap which is built on the
348  * the same data as the cost array, but inverted: it is a work-list of edges prioritized
349  * by the shortest path found so far to the edge.
350  */
351 
352  /* Regular dijkstra shortest path, but over edges instead of vertices. */
353  heap = BLI_heapsimple_new();
354  BLI_heapsimple_insert(heap, 0.0f, e_src);
355  cost[BM_elem_index_get(e_src)] = 0.0f;
356 
357  while (!BLI_heapsimple_is_empty(heap)) {
358  e = BLI_heapsimple_pop_min(heap);
359 
360  if (e == e_dst) {
361  break;
362  }
363 
366  edgetag_add_adjacent(heap, e, edges_prev, cost, params);
367  }
368  }
369 
370  if (e == e_dst) {
371  do {
372  BLI_linklist_prepend(&path, e);
373  } while ((e = edges_prev[BM_elem_index_get(e)]));
374  }
375 
376  MEM_freeN(edges_prev);
377  MEM_freeN(cost);
378  BLI_heapsimple_free(heap, NULL);
379 
380  return path;
381 }
382 
385 /* -------------------------------------------------------------------- */
389 static float facetag_cut_cost_edge(BMFace *f_a,
390  BMFace *f_b,
391  BMEdge *e,
392  const void *const f_endpoints[2])
393 {
394  float f_a_cent[3];
395  float f_b_cent[3];
396  float e_cent[3];
397 
400 #if 0
401  mid_v3_v3v3(e_cent, e->v1->co, e->v2->co);
402 #else
403  /* For triangle fans it gives better results to pick a point on the edge. */
404  {
405  float ix_e[3], ix_f[3];
406  isect_line_line_v3(e->v1->co, e->v2->co, f_a_cent, f_b_cent, ix_e, ix_f);
407  const float factor = line_point_factor_v3(ix_e, e->v1->co, e->v2->co);
408  if (factor < 0.0f) {
409  copy_v3_v3(e_cent, e->v1->co);
410  }
411  else if (factor > 1.0f) {
412  copy_v3_v3(e_cent, e->v2->co);
413  }
414  else {
415  copy_v3_v3(e_cent, ix_e);
416  }
417  }
418 #endif
419 
420  return step_cost_3_v3_ex(
421  f_a_cent, e_cent, f_b_cent, (f_a == f_endpoints[0]), (f_b == f_endpoints[1]));
422 }
423 
424 static float facetag_cut_cost_vert(BMFace *f_a,
425  BMFace *f_b,
426  BMVert *v,
427  const void *const f_endpoints[2])
428 {
429  float f_a_cent[3];
430  float f_b_cent[3];
431 
434 
435  return step_cost_3_v3_ex(
436  f_a_cent, v->co, f_b_cent, (f_a == f_endpoints[0]), (f_b == f_endpoints[1]));
437 }
438 
440  BMFace *f_a,
441  BMFace **faces_prev,
442  float *cost,
443  const void *const f_endpoints[2],
444  const struct BMCalcPathParams *params)
445 {
446  const int f_a_index = BM_elem_index_get(f_a);
447 
448  /* Loop over faces of face, but do so by first looping over loops. */
449  {
450  BMIter liter;
451  BMLoop *l_a;
452 
453  BM_ITER_ELEM (l_a, &liter, f_a, BM_LOOPS_OF_FACE) {
454  BMLoop *l_first, *l_iter;
455 
456  l_iter = l_first = l_a;
457  do {
458  BMFace *f_b = l_iter->f;
459  if (!BM_elem_flag_test(f_b, BM_ELEM_TAG)) {
460  /* We know 'f_b' is not visited, check it out! */
461  const int f_b_index = BM_elem_index_get(f_b);
462  const float cost_cut = params->use_topology_distance ?
463  1.0f :
464  facetag_cut_cost_edge(f_a, f_b, l_iter->e, f_endpoints);
465  const float cost_new = cost[f_a_index] + cost_cut;
466 
467  if (cost[f_b_index] > cost_new) {
468  cost[f_b_index] = cost_new;
469  faces_prev[f_b_index] = f_a;
470  BLI_heapsimple_insert(heap, cost_new, f_b);
471  }
472  }
473  } while ((l_iter = l_iter->radial_next) != l_first);
474  }
475  }
476 
477  if (params->use_step_face) {
478  BMIter liter;
479  BMLoop *l_a;
480 
481  BM_ITER_ELEM (l_a, &liter, f_a, BM_LOOPS_OF_FACE) {
482  BMIter litersub;
483  BMLoop *l_b;
484  BM_ITER_ELEM (l_b, &litersub, l_a->v, BM_LOOPS_OF_VERT) {
485  if ((l_a != l_b) && !BM_loop_share_edge_check(l_a, l_b)) {
486  BMFace *f_b = l_b->f;
487  if (!BM_elem_flag_test(f_b, BM_ELEM_TAG)) {
488  /* We know 'f_b' is not visited, check it out! */
489  const int f_b_index = BM_elem_index_get(f_b);
490  const float cost_cut = params->use_topology_distance ?
491  1.0f :
492  facetag_cut_cost_vert(f_a, f_b, l_a->v, f_endpoints);
493  const float cost_new = cost[f_a_index] + cost_cut;
494 
495  if (cost[f_b_index] > cost_new) {
496  cost[f_b_index] = cost_new;
497  faces_prev[f_b_index] = f_a;
498  BLI_heapsimple_insert(heap, cost_new, f_b);
499  }
500  }
501  }
502  }
503  }
504  }
505 }
506 
508  BMFace *f_src,
509  BMFace *f_dst,
510  const struct BMCalcPathParams *params,
511  bool (*filter_fn)(BMFace *, void *user_data),
512  void *user_data)
513 {
514  LinkNode *path = NULL;
515  /* #BM_ELEM_TAG flag is used to store visited edges. */
516  BMFace *f;
517  BMIter fiter;
518  HeapSimple *heap;
519  float *cost;
520  BMFace **faces_prev;
521  int i, totface;
522 
523  /* Start measuring face path at the face edges, ignoring their centers. */
524  const void *const f_endpoints[2] = {f_src, f_dst};
525 
526  /* Note, would pass #BM_EDGE except we are looping over all faces anyway. */
527  // BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG
528 
529  BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) {
530  BM_elem_flag_set(f, BM_ELEM_TAG, !filter_fn(f, user_data));
531  BM_elem_index_set(f, i); /* set_inline */
532  }
534 
535  /* Allocate. */
536  totface = bm->totface;
537  faces_prev = MEM_callocN(sizeof(*faces_prev) * totface, __func__);
538  cost = MEM_mallocN(sizeof(*cost) * totface, __func__);
539 
540  copy_vn_fl(cost, totface, COST_INIT_MAX);
541 
542  /*
543  * Arrays are now filled as follows:
544  *
545  * As the search continues, `faces_prev[n]` will be the previous face on the shortest
546  * path found so far to face `n`. #BM_ELEM_TAG is used to tag elements we have visited,
547  * `cost[n]` will contain the length of the shortest
548  * path to face n found so far, Finally, heap is a priority heap which is built on the
549  * the same data as the cost array, but inverted: it is a work-list of faces prioritized
550  * by the shortest path found so far to the face.
551  */
552 
553  /* Regular dijkstra shortest path, but over faces instead of vertices. */
554  heap = BLI_heapsimple_new();
555  BLI_heapsimple_insert(heap, 0.0f, f_src);
556  cost[BM_elem_index_get(f_src)] = 0.0f;
557 
558  while (!BLI_heapsimple_is_empty(heap)) {
559  f = BLI_heapsimple_pop_min(heap);
560 
561  if (f == f_dst) {
562  break;
563  }
564 
565  if (!BM_elem_flag_test(f, BM_ELEM_TAG)) {
567  facetag_add_adjacent(heap, f, faces_prev, cost, f_endpoints, params);
568  }
569  }
570 
571  if (f == f_dst) {
572  do {
573  BLI_linklist_prepend(&path, f);
574  } while ((f = faces_prev[BM_elem_index_get(f)]));
575  }
576 
577  MEM_freeN(faces_prev);
578  MEM_freeN(cost);
579  BLI_heapsimple_free(heap, NULL);
580 
581  return path;
582 }
A min-heap / priority queue ADT.
void BLI_heapsimple_free(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) ATTR_NONNULL(1)
HeapSimple * BLI_heapsimple_new(void) ATTR_WARN_UNUSED_RESULT
void * BLI_heapsimple_pop_min(HeapSimple *heap) ATTR_NONNULL(1)
bool BLI_heapsimple_is_empty(const HeapSimple *heap) ATTR_NONNULL(1)
void BLI_heapsimple_insert(HeapSimple *heap, float value, void *ptr) ATTR_NONNULL(1)
int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float r_i1[3], float r_i2[3])
Definition: math_geom.c:3103
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3449
void copy_vn_fl(float *array_tar, const int size, const float val)
Definition: math_vector.c:1410
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:270
_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.
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ 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:124
#define BM_elem_flag_set(ele, hflag, val)
Definition: bmesh_inline.h:30
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:125
#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_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_VERTS_OF_EDGE
@ BM_FACES_OF_MESH
@ BM_LOOPS_OF_VERT
@ BM_EDGES_OF_VERT
@ BM_LOOPS_OF_FACE
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2152
LinkNode * BM_mesh_calc_path_vert(BMesh *bm, BMVert *v_src, BMVert *v_dst, const struct BMCalcPathParams *params, bool(*filter_fn)(BMVert *, void *user_data), void *user_data)
Definition: bmesh_path.c:129
static float edgetag_cut_cost_face(BMEdge *e_a, BMEdge *e_b, BMFace *f)
Definition: bmesh_path.c:216
static float facetag_cut_cost_edge(BMFace *f_a, BMFace *f_b, BMEdge *e, const void *const f_endpoints[2])
Definition: bmesh_path.c:389
static float step_cost_3_v3_ex(const float v1[3], const float v2[3], const float v3[3], bool skip_12, bool skip_23)
Definition: bmesh_path.c:43
LinkNode * BM_mesh_calc_path_edge(BMesh *bm, BMEdge *e_src, BMEdge *e_dst, const struct BMCalcPathParams *params, bool(*filter_fn)(BMEdge *, void *user_data), void *user_data)
Definition: bmesh_path.c:309
#define COST_INIT_MAX
Definition: bmesh_path.c:34
static void edgetag_add_adjacent(HeapSimple *heap, BMEdge *e_a, BMEdge **edges_prev, float *cost, const struct BMCalcPathParams *params)
Definition: bmesh_path.c:228
static void facetag_add_adjacent(HeapSimple *heap, BMFace *f_a, BMFace **faces_prev, float *cost, const void *const f_endpoints[2], const struct BMCalcPathParams *params)
Definition: bmesh_path.c:439
static float edgetag_cut_cost_vert(BMEdge *e_a, BMEdge *e_b, BMVert *v)
Definition: bmesh_path.c:209
LinkNode * BM_mesh_calc_path_face(BMesh *bm, BMFace *f_src, BMFace *f_dst, const struct BMCalcPathParams *params, bool(*filter_fn)(BMFace *, void *user_data), void *user_data)
Definition: bmesh_path.c:507
static float step_cost_3_v3(const float v1[3], const float v2[3], const float v3[3])
Definition: bmesh_path.c:60
static float facetag_cut_cost_vert(BMFace *f_a, BMFace *f_b, BMVert *v, const void *const f_endpoints[2])
Definition: bmesh_path.c:424
static void verttag_add_adjacent(HeapSimple *heap, BMVert *v_a, BMVert **verts_prev, float *cost, const struct BMCalcPathParams *params)
Definition: bmesh_path.c:71
void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3])
bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b)
Definition: bmesh_query.c:1305
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
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 BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
ATTR_WARN_UNUSED_RESULT const BMVert * v
void * user_data
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define fabsf(x)
#define sqrtf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
BMVert * v1
Definition: bmesh_class.h:134
struct BMLoop * l
Definition: bmesh_class.h:140
int len
Definition: bmesh_class.h:279
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 BMLoop * prev
Definition: bmesh_class.h:245
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245
float co[3]
Definition: bmesh_class.h:99
int totvert
Definition: bmesh_class.h:297
char elem_index_dirty
Definition: bmesh_class.h:305
int totedge
Definition: bmesh_class.h:297
int totface
Definition: bmesh_class.h:297