Blender  V3.3
bmesh_path_uv.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include "MEM_guardedalloc.h"
10 
11 #include "BLI_heap_simple.h"
12 #include "BLI_linklist.h"
13 #include "BLI_math.h"
14 
15 #include "DNA_meshdata_types.h"
16 
17 #include "bmesh.h"
18 #include "bmesh_path_uv.h" /* own include */
19 #include "intern/bmesh_query.h"
20 #include "intern/bmesh_query_uv.h"
21 
22 #define COST_INIT_MAX FLT_MAX
23 
24 /* -------------------------------------------------------------------- */
33 static float step_cost_3_v2_ex(
34  const float v1[2], const float v2[2], const float v3[2], bool skip_12, bool skip_23)
35 {
36  float d1[2], d2[2];
37 
38  /* The cost is based on the simple sum of the length of the two edges. */
39  sub_v2_v2v2(d1, v2, v1);
40  sub_v2_v2v2(d2, v3, v2);
41  const float cost_12 = normalize_v2(d1);
42  const float cost_23 = normalize_v2(d2);
43  const float cost = ((skip_12 ? 0.0f : cost_12) + (skip_23 ? 0.0f : cost_23));
44 
45  /* But is biased to give higher values to sharp turns, so that it will take paths with
46  * fewer "turns" when selecting between equal-weighted paths between the two edges. */
47  return cost * (1.0f + 0.5f * (2.0f - sqrtf(fabsf(dot_v2v2(d1, d2)))));
48 }
49 
50 static float step_cost_3_v2(const float v1[2], const float v2[2], const float v3[2])
51 {
52  return step_cost_3_v2_ex(v1, v2, v3, false, false);
53 }
54 
57 /* -------------------------------------------------------------------- */
62  BMLoop *l_a,
63  BMLoop **loops_prev,
64  float *cost,
65  const struct BMCalcPathUVParams *params)
66 {
67  BLI_assert(params->aspect_y != 0.0f);
68  const uint cd_loop_uv_offset = params->cd_loop_uv_offset;
69  const int l_a_index = BM_elem_index_get(l_a);
70  const MLoopUV *luv_a = BM_ELEM_CD_GET_VOID_P(l_a, cd_loop_uv_offset);
71  const float uv_a[2] = {luv_a->uv[0], luv_a->uv[1] / params->aspect_y};
72 
73  {
74  BMIter liter;
75  BMLoop *l;
76  /* Loop over faces of face, but do so by first looping over loops. */
77  BM_ITER_ELEM (l, &liter, l_a->v, BM_LOOPS_OF_VERT) {
78  const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
79  if (equals_v2v2(luv_a->uv, luv->uv)) {
80  /* 'l_a' is already tagged, tag all adjacent. */
82  BMLoop *l_b = l->next;
83  do {
85  const MLoopUV *luv_b = BM_ELEM_CD_GET_VOID_P(l_b, cd_loop_uv_offset);
86  const float uv_b[2] = {luv_b->uv[0], luv_b->uv[1] / params->aspect_y};
87  /* We know 'l_b' is not visited, check it out! */
88  const int l_b_index = BM_elem_index_get(l_b);
89  const float cost_cut = params->use_topology_distance ? 1.0f : len_v2v2(uv_a, uv_b);
90  const float cost_new = cost[l_a_index] + cost_cut;
91 
92  if (cost[l_b_index] > cost_new) {
93  cost[l_b_index] = cost_new;
94  loops_prev[l_b_index] = l_a;
95  BLI_heapsimple_insert(heap, cost_new, l_b);
96  }
97  }
98  /* This means we only step onto `l->prev` & `l->next`. */
99  if (params->use_step_face == false) {
100  if (l_b == l->next) {
101  l_b = l->prev->prev;
102  }
103  }
104  } while ((l_b = l_b->next) != l);
105  }
106  }
107  }
108 }
109 
111  BMLoop *l_src,
112  BMLoop *l_dst,
113  const struct BMCalcPathUVParams *params,
114  bool (*filter_fn)(BMLoop *, void *),
115  void *user_data)
116 {
117  LinkNode *path = NULL;
118  /* BM_ELEM_TAG flag is used to store visited edges */
119  BMIter viter;
120  HeapSimple *heap;
121  float *cost;
122  BMLoop **loops_prev;
123  int i = 0, totloop;
124  BMFace *f;
125 
126  /* NOTE: would pass BM_EDGE except we are looping over all faces anyway. */
127  // BM_mesh_elem_index_ensure(bm, BM_LOOP); // NOT NEEDED FOR FACETAG
128 
129  BM_ITER_MESH (f, &viter, bm, BM_FACES_OF_MESH) {
130  BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
131  BMLoop *l_iter = l_first;
132  do {
133  BM_elem_flag_set(l_iter, BM_ELEM_TAG, !filter_fn(l_iter, user_data));
134  BM_elem_index_set(l_iter, i); /* set_inline */
135  i += 1;
136  } while ((l_iter = l_iter->next) != l_first);
137  }
139 
140  /* Allocate. */
141  totloop = bm->totloop;
142  loops_prev = MEM_callocN(sizeof(*loops_prev) * totloop, __func__);
143  cost = MEM_mallocN(sizeof(*cost) * totloop, __func__);
144 
145  copy_vn_fl(cost, totloop, COST_INIT_MAX);
146 
147  /* Regular dijkstra shortest path, but over UV loops instead of vertices. */
148  heap = BLI_heapsimple_new();
149  BLI_heapsimple_insert(heap, 0.0f, l_src);
150  cost[BM_elem_index_get(l_src)] = 0.0f;
151 
152  BMLoop *l = NULL;
153  while (!BLI_heapsimple_is_empty(heap)) {
154  l = BLI_heapsimple_pop_min(heap);
155 
156  if ((l->v == l_dst->v) && BM_loop_uv_share_vert_check(l, l_dst, params->cd_loop_uv_offset)) {
157  break;
158  }
159 
161  /* Adjacent loops are tagged while stepping to avoid 2x loops. */
163  verttag_add_adjacent_uv(heap, l, loops_prev, cost, params);
164  }
165  }
166 
167  if ((l->v == l_dst->v) && BM_loop_uv_share_vert_check(l, l_dst, params->cd_loop_uv_offset)) {
168  do {
169  BLI_linklist_prepend(&path, l);
170  } while ((l = loops_prev[BM_elem_index_get(l)]));
171  }
172 
173  MEM_freeN(loops_prev);
174  MEM_freeN(cost);
175  BLI_heapsimple_free(heap, NULL);
176 
177  return path;
178 }
179 
182 /* -------------------------------------------------------------------- */
187  BMLoop *l_e_a, BMLoop *l_e_b, BMLoop *l_v, const float aspect_y, const int cd_loop_uv_offset)
188 {
189  BMLoop *l_v1 = (l_v->v == l_e_a->v) ? l_e_a->next : l_e_a;
190  BMLoop *l_v2 = (l_v->v == l_e_b->v) ? l_e_b->next : l_e_b;
191 
192  MLoopUV *luv_v1 = BM_ELEM_CD_GET_VOID_P(l_v1, cd_loop_uv_offset);
193  MLoopUV *luv_v2 = BM_ELEM_CD_GET_VOID_P(l_v2, cd_loop_uv_offset);
194  MLoopUV *luv_v = BM_ELEM_CD_GET_VOID_P(l_v, cd_loop_uv_offset);
195 
196  float uv_v1[2] = {luv_v1->uv[0], luv_v1->uv[1] / aspect_y};
197  float uv_v2[2] = {luv_v2->uv[0], luv_v2->uv[1] / aspect_y};
198  float uv_v[2] = {luv_v->uv[0], luv_v->uv[1] / aspect_y};
199 
200  return step_cost_3_v2(uv_v1, uv_v, uv_v2);
201 }
202 
204  BMLoop *l_e_a, BMLoop *l_e_b, BMFace *f, const float aspect_v2[2], const int cd_loop_uv_offset)
205 {
206  float l_e_a_cent[2], l_e_b_cent[2], f_cent[2];
207  MLoopUV *luv_e_a = BM_ELEM_CD_GET_VOID_P(l_e_a, cd_loop_uv_offset);
208  MLoopUV *luv_e_b = BM_ELEM_CD_GET_VOID_P(l_e_b, cd_loop_uv_offset);
209 
210  mid_v2_v2v2(l_e_a_cent, luv_e_a->uv, luv_e_a->uv);
211  mid_v2_v2v2(l_e_b_cent, luv_e_b->uv, luv_e_b->uv);
212 
213  mul_v2_v2(l_e_a_cent, aspect_v2);
214  mul_v2_v2(l_e_b_cent, aspect_v2);
215 
216  BM_face_uv_calc_center_median_weighted(f, aspect_v2, cd_loop_uv_offset, f_cent);
217 
218  return step_cost_3_v2(l_e_a_cent, l_e_b_cent, f_cent);
219 }
220 
222  BMLoop *l_a,
223  BMLoop **loops_prev,
224  float *cost,
225  const struct BMCalcPathUVParams *params)
226 {
227  BLI_assert(params->aspect_y != 0.0f);
228  const uint cd_loop_uv_offset = params->cd_loop_uv_offset;
229  BMLoop *l_a_verts[2] = {l_a, l_a->next};
230  const int l_a_index = BM_elem_index_get(l_a);
231 
232  if (params->use_step_face == false) {
233  for (int i = 0; i < ARRAY_SIZE(l_a_verts); i++) {
234 
235  /* Skip current UV vert if it is part of the previous UV edge in the path. */
236  if (loops_prev[l_a_index]) {
237  BMLoop *l_prev = loops_prev[l_a_index];
238  if (l_a_verts[i]->v != l_prev->v) {
239  l_prev = (l_a_verts[i]->v == l_prev->next->v) ? l_prev->next : NULL;
240  }
241  if (l_prev && BM_loop_uv_share_vert_check(l_a_verts[i], l_prev, cd_loop_uv_offset)) {
242  continue;
243  }
244  }
245 
246  BMEdge *e_b;
247  BMIter eiter;
248  BM_ITER_ELEM (e_b, &eiter, l_a_verts[i]->v, BM_EDGES_OF_VERT) {
249  BMLoop *l_first, *l_b;
250  l_first = l_b = e_b->l;
251  do {
253  BMLoop *l_b_vert = (l_a_verts[i]->v == l_b->v) ? l_b : l_b->next;
254  if (BM_loop_uv_share_vert_check(l_a_verts[i], l_b_vert, cd_loop_uv_offset)) {
255  /* We know 'l_b' is not visited, check it out! */
256  const int l_b_index = BM_elem_index_get(l_b);
257  const float cost_cut = params->use_topology_distance ?
258  1.0f :
260  l_b,
261  l_a_verts[i],
262  params->aspect_y,
263  cd_loop_uv_offset);
264  const float cost_new = cost[l_a_index] + cost_cut;
265 
266  if (cost[l_b_index] > cost_new) {
267  cost[l_b_index] = cost_new;
268  loops_prev[l_b_index] = l_a;
269  BLI_heapsimple_insert(heap, cost_new, l_b);
270  }
271  }
272  }
273  } while ((l_b = l_b->radial_next) != l_first);
274  }
275  }
276  }
277  else {
278  const float aspect_v2[2] = {1.0f, 1.0f / params->aspect_y};
279  BMLoop *l_first, *l_iter;
280  l_iter = l_first = l_a;
281  do {
282  /* Ensures connected UVs and that they lie on the same island. */
283  if (!BM_loop_uv_share_edge_check(l_a, l_iter, cd_loop_uv_offset)) {
284  continue;
285  }
286 
287  BMLoop *l_cycle_iter, *l_cycle_end;
288  l_cycle_iter = l_iter->next;
289  l_cycle_end = l_iter;
290  do {
291  BMLoop *l_b = l_cycle_iter;
293  /* We know 'l_b' is not visited, check it out! */
294  const int l_b_index = BM_elem_index_get(l_b);
295  const float cost_cut = params->use_topology_distance ?
296  1.0f :
298  l_b,
299  l_iter->f,
300  aspect_v2,
301  params->cd_loop_uv_offset);
302  const float cost_new = cost[l_a_index] + cost_cut;
303 
304  if (cost[l_b_index] > cost_new) {
305  cost[l_b_index] = cost_new;
306  loops_prev[l_b_index] = l_a;
307  BLI_heapsimple_insert(heap, cost_new, l_b);
308  }
309  }
310  } while ((l_cycle_iter = l_cycle_iter->next) != l_cycle_end);
311  } while ((l_iter = l_iter->radial_next) != l_first);
312  }
313 }
314 
316  BMLoop *l_src,
317  BMLoop *l_dst,
318  const struct BMCalcPathUVParams *params,
319  bool (*filter_fn)(BMLoop *, void *),
320  void *user_data)
321 {
322  LinkNode *path = NULL;
323 
324  BMFace *f;
325  BMIter iter;
326  HeapSimple *heap;
327  float *cost;
328  BMLoop **loops_prev;
329  int i = 0, totloop;
330 
331  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
332  BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
333  BMLoop *l_iter = l_first;
334  do {
335  BM_elem_flag_set(l_iter, BM_ELEM_TAG, !filter_fn(l_iter, user_data));
336  BM_elem_index_set(l_iter, i);
337  i += 1;
338  } while ((l_iter = l_iter->next) != l_first);
339  }
341 
342  totloop = bm->totloop;
343  loops_prev = MEM_callocN(sizeof(*loops_prev) * totloop, __func__);
344  cost = MEM_mallocN(sizeof(*cost) * totloop, __func__);
345 
346  copy_vn_fl(cost, totloop, COST_INIT_MAX);
347 
348  /* Regular dijkstra shortest path, but over UV loops/edges instead of vertices. */
349  heap = BLI_heapsimple_new();
350  BLI_heapsimple_insert(heap, 0.0f, l_src);
351  cost[BM_elem_index_get(l_src)] = 0.0f;
352 
353  BMLoop *l = NULL;
354  while (!BLI_heapsimple_is_empty(heap)) {
355  l = BLI_heapsimple_pop_min(heap);
356 
357  if ((l->e == l_dst->e) && (BM_loop_uv_share_edge_check(l, l_dst, params->cd_loop_uv_offset))) {
358  break;
359  }
360 
363  edgetag_add_adjacent_uv(heap, l, loops_prev, cost, params);
364  }
365  }
366 
367  if ((l->e == l_dst->e) && (BM_loop_uv_share_edge_check(l, l_dst, params->cd_loop_uv_offset))) {
368  do {
369  BLI_linklist_prepend(&path, l);
370  } while ((l = loops_prev[BM_elem_index_get(l)]));
371  }
372 
373  MEM_freeN(loops_prev);
374  MEM_freeN(cost);
375  BLI_heapsimple_free(heap, NULL);
376 
377  return path;
378 }
379 
382 /* -------------------------------------------------------------------- */
387  BMFace *f_b,
388  BMLoop *l_edge,
389  const void *const f_endpoints[2],
390  const float aspect_v2[2],
391  const int cd_loop_uv_offset)
392 {
393  float f_a_cent[2];
394  float f_b_cent[2];
395  float e_cent[2];
396 
397  BM_face_uv_calc_center_median_weighted(f_a, aspect_v2, cd_loop_uv_offset, f_a_cent);
398  BM_face_uv_calc_center_median_weighted(f_b, aspect_v2, cd_loop_uv_offset, f_b_cent);
399 
400  const float *co_v1 = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_edge, cd_loop_uv_offset))->uv;
401  const float *co_v2 =
402  ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_edge->next, cd_loop_uv_offset))->uv;
403 
404 #if 0
405  mid_v2_v2v2(e_cent, co_v1, co_v2);
406 #else
407  /* For triangle fans it gives better results to pick a point on the edge. */
408  {
409  float ix_e[2];
410  isect_line_line_v2_point(co_v1, co_v2, f_a_cent, f_b_cent, ix_e);
411  const float factor = line_point_factor_v2(ix_e, co_v1, co_v2);
412  if (factor < 0.0f) {
413  copy_v2_v2(e_cent, co_v1);
414  }
415  else if (factor > 1.0f) {
416  copy_v2_v2(e_cent, co_v2);
417  }
418  else {
419  copy_v2_v2(e_cent, ix_e);
420  }
421  }
422 #endif
423 
424  /* Apply aspect before calculating cost. */
425  mul_v2_v2(f_a_cent, aspect_v2);
426  mul_v2_v2(f_b_cent, aspect_v2);
427  mul_v2_v2(e_cent, aspect_v2);
428 
429  return step_cost_3_v2_ex(
430  f_a_cent, e_cent, f_b_cent, (f_a == f_endpoints[0]), (f_b == f_endpoints[1]));
431 }
432 
434  BMFace *f_b,
435  BMLoop *l_vert,
436  const void *const f_endpoints[2],
437  const float aspect_v2[2],
438  const int cd_loop_uv_offset)
439 {
440  float f_a_cent[2];
441  float f_b_cent[2];
442  float v_cent[2];
443 
444  BM_face_uv_calc_center_median_weighted(f_a, aspect_v2, cd_loop_uv_offset, f_a_cent);
445  BM_face_uv_calc_center_median_weighted(f_b, aspect_v2, cd_loop_uv_offset, f_b_cent);
446 
447  copy_v2_v2(v_cent, ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_vert, cd_loop_uv_offset))->uv);
448 
449  mul_v2_v2(f_a_cent, aspect_v2);
450  mul_v2_v2(f_b_cent, aspect_v2);
451  mul_v2_v2(v_cent, aspect_v2);
452 
453  return step_cost_3_v2_ex(
454  f_a_cent, v_cent, f_b_cent, (f_a == f_endpoints[0]), (f_b == f_endpoints[1]));
455 }
456 
458  BMFace *f_a,
459  BMFace **faces_prev,
460  float *cost,
461  const void *const f_endpoints[2],
462  const float aspect_v2[2],
463  const struct BMCalcPathUVParams *params)
464 {
465  const uint cd_loop_uv_offset = params->cd_loop_uv_offset;
466  const int f_a_index = BM_elem_index_get(f_a);
467 
468  /* Loop over faces of face, but do so by first looping over loops. */
469  {
470  BMIter liter;
471  BMLoop *l_a;
472 
473  BM_ITER_ELEM (l_a, &liter, f_a, BM_LOOPS_OF_FACE) {
474  BMLoop *l_first, *l_iter;
475 
476  /* Check there is an adjacent face to loop over. */
477  if (l_a != l_a->radial_next) {
478  l_iter = l_first = l_a->radial_next;
479  do {
480  BMFace *f_b = l_iter->f;
481  if (!BM_elem_flag_test(f_b, BM_ELEM_TAG)) {
482  if (BM_loop_uv_share_edge_check(l_a, l_iter, cd_loop_uv_offset)) {
483  /* We know 'f_b' is not visited, check it out! */
484  const int f_b_index = BM_elem_index_get(f_b);
485  const float cost_cut =
486  params->use_topology_distance ?
487  1.0f :
489  f_a, f_b, l_iter, f_endpoints, aspect_v2, cd_loop_uv_offset);
490  const float cost_new = cost[f_a_index] + cost_cut;
491 
492  if (cost[f_b_index] > cost_new) {
493  cost[f_b_index] = cost_new;
494  faces_prev[f_b_index] = f_a;
495  BLI_heapsimple_insert(heap, cost_new, f_b);
496  }
497  }
498  }
499  } while ((l_iter = l_iter->radial_next) != l_first);
500  }
501  }
502  }
503 
504  if (params->use_step_face) {
505  BMIter liter;
506  BMLoop *l_a;
507 
508  BM_ITER_ELEM (l_a, &liter, f_a, BM_LOOPS_OF_FACE) {
509  BMIter litersub;
510  BMLoop *l_b;
511  BM_ITER_ELEM (l_b, &litersub, l_a->v, BM_LOOPS_OF_VERT) {
512  if ((l_a != l_b) && !BM_loop_share_edge_check(l_a, l_b)) {
513  BMFace *f_b = l_b->f;
514  if (!BM_elem_flag_test(f_b, BM_ELEM_TAG)) {
515  if (BM_loop_uv_share_vert_check(l_a, l_b, cd_loop_uv_offset)) {
516  /* We know 'f_b' is not visited, check it out! */
517  const int f_b_index = BM_elem_index_get(f_b);
518  const float cost_cut =
519  params->use_topology_distance ?
520  1.0f :
522  f_a, f_b, l_a, f_endpoints, aspect_v2, cd_loop_uv_offset);
523  const float cost_new = cost[f_a_index] + cost_cut;
524 
525  if (cost[f_b_index] > cost_new) {
526  cost[f_b_index] = cost_new;
527  faces_prev[f_b_index] = f_a;
528  BLI_heapsimple_insert(heap, cost_new, f_b);
529  }
530  }
531  }
532  }
533  }
534  }
535  }
536 }
537 
539  BMFace *f_src,
540  BMFace *f_dst,
541  const struct BMCalcPathUVParams *params,
542  bool (*filter_fn)(BMFace *, void *),
543  void *user_data)
544 {
545  const float aspect_v2[2] = {1.0f, 1.0f / params->aspect_y};
546  LinkNode *path = NULL;
547  /* BM_ELEM_TAG flag is used to store visited edges */
548  BMIter fiter;
549  HeapSimple *heap;
550  float *cost;
551  BMFace **faces_prev;
552  int i = 0, totface;
553 
554  /* Start measuring face path at the face edges, ignoring their centers. */
555  const void *const f_endpoints[2] = {f_src, f_dst};
556 
557  /* NOTE: would pass BM_EDGE except we are looping over all faces anyway. */
558  // BM_mesh_elem_index_ensure(bm, BM_LOOP); // NOT NEEDED FOR FACETAG
559 
560  {
561  BMFace *f;
562  BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
563  BM_elem_flag_set(f, BM_ELEM_TAG, !filter_fn(f, user_data));
564  BM_elem_index_set(f, i); /* set_inline */
565  i += 1;
566  }
568  }
569 
570  /* Allocate. */
571  totface = bm->totface;
572  faces_prev = MEM_callocN(sizeof(*faces_prev) * totface, __func__);
573  cost = MEM_mallocN(sizeof(*cost) * totface, __func__);
574 
575  copy_vn_fl(cost, totface, COST_INIT_MAX);
576 
577  /* Regular dijkstra shortest path, but over UV faces instead of vertices. */
578  heap = BLI_heapsimple_new();
579  BLI_heapsimple_insert(heap, 0.0f, f_src);
580  cost[BM_elem_index_get(f_src)] = 0.0f;
581 
582  BMFace *f = NULL;
583  while (!BLI_heapsimple_is_empty(heap)) {
584  f = BLI_heapsimple_pop_min(heap);
585 
586  if (f == f_dst) {
587  break;
588  }
589 
590  if (!BM_elem_flag_test(f, BM_ELEM_TAG)) {
591  /* Adjacent loops are tagged while stepping to avoid 2x loops. */
593  facetag_add_adjacent_uv(heap, f, faces_prev, cost, f_endpoints, aspect_v2, params);
594  }
595  }
596 
597  if (f == f_dst) {
598  do {
599  BLI_linklist_prepend(&path, f);
600  } while ((f = faces_prev[BM_elem_index_get(f)]));
601  }
602 
603  MEM_freeN(faces_prev);
604  MEM_freeN(cost);
605  BLI_heapsimple_free(heap, NULL);
606 
607  return path;
608 }
609 
#define BLI_assert(a)
Definition: BLI_assert.h:46
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)
float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2])
Definition: math_geom.c:3274
int isect_line_line_v2_point(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float r_vi[2])
Definition: math_geom.c:1085
MINLINE void mul_v2_v2(float r[2], const float a[2])
MINLINE void copy_v2_v2(float r[2], const float a[2])
void copy_vn_fl(float *array_tar, int size, float val)
Definition: math_vector.c:1259
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
void mid_v2_v2v2(float r[2], const float a[2], const float b[2])
Definition: math_vector.c:244
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v2(float r[2])
unsigned int uint
Definition: BLI_sys_types.h:67
#define ARRAY_SIZE(arr)
_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_ELEM_TAG
Definition: bmesh_class.h:484
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#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_FACES_OF_MESH
@ BM_LOOPS_OF_VERT
@ BM_EDGES_OF_VERT
@ BM_LOOPS_OF_FACE
ATTR_WARN_UNUSED_RESULT BMesh * bm
static float edgetag_cut_cost_face_uv(BMLoop *l_e_a, BMLoop *l_e_b, BMFace *f, const float aspect_v2[2], const int cd_loop_uv_offset)
static void edgetag_add_adjacent_uv(HeapSimple *heap, BMLoop *l_a, BMLoop **loops_prev, float *cost, const struct BMCalcPathUVParams *params)
struct LinkNode * BM_mesh_calc_path_uv_vert(BMesh *bm, BMLoop *l_src, BMLoop *l_dst, const struct BMCalcPathUVParams *params, bool(*filter_fn)(BMLoop *, void *), void *user_data)
#define COST_INIT_MAX
Definition: bmesh_path_uv.c:22
static float edgetag_cut_cost_vert_uv(BMLoop *l_e_a, BMLoop *l_e_b, BMLoop *l_v, const float aspect_y, const int cd_loop_uv_offset)
static void facetag_add_adjacent_uv(HeapSimple *heap, BMFace *f_a, BMFace **faces_prev, float *cost, const void *const f_endpoints[2], const float aspect_v2[2], const struct BMCalcPathUVParams *params)
static float step_cost_3_v2(const float v1[2], const float v2[2], const float v3[2])
Definition: bmesh_path_uv.c:50
struct LinkNode * BM_mesh_calc_path_uv_face(BMesh *bm, BMFace *f_src, BMFace *f_dst, const struct BMCalcPathUVParams *params, bool(*filter_fn)(BMFace *, void *), void *user_data)
static void verttag_add_adjacent_uv(HeapSimple *heap, BMLoop *l_a, BMLoop **loops_prev, float *cost, const struct BMCalcPathUVParams *params)
Definition: bmesh_path_uv.c:61
struct LinkNode * BM_mesh_calc_path_uv_edge(BMesh *bm, BMLoop *l_src, BMLoop *l_dst, const struct BMCalcPathUVParams *params, bool(*filter_fn)(BMLoop *, void *), void *user_data)
static float step_cost_3_v2_ex(const float v1[2], const float v2[2], const float v3[2], bool skip_12, bool skip_23)
Definition: bmesh_path_uv.c:33
static float facetag_cut_cost_edge_uv(BMFace *f_a, BMFace *f_b, BMLoop *l_edge, const void *const f_endpoints[2], const float aspect_v2[2], const int cd_loop_uv_offset)
static float facetag_cut_cost_vert_uv(BMFace *f_a, BMFace *f_b, BMLoop *l_vert, const void *const f_endpoints[2], const float aspect_v2[2], const int cd_loop_uv_offset)
bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b)
Definition: bmesh_query.c:1030
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
ATTR_WARN_UNUSED_RESULT const BMVert * v
bool BM_loop_uv_share_vert_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
bool BM_loop_uv_share_edge_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
void BM_face_uv_calc_center_median_weighted(const BMFace *f, const float aspect[2], const int cd_loop_uv_offset, float r_cent[2])
void * user_data
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
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
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
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 BMLoop * prev
Definition: bmesh_class.h:233
struct BMFace * f
Definition: bmesh_class.h:171
struct BMLoop * next
Definition: bmesh_class.h:233
char elem_index_dirty
Definition: bmesh_class.h:305
int totloop
Definition: bmesh_class.h:297
int totface
Definition: bmesh_class.h:297