Blender  V3.3
bmesh_query.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
14 #include "MEM_guardedalloc.h"
15 
16 #include "BLI_alloca.h"
17 #include "BLI_linklist.h"
18 #include "BLI_math.h"
19 #include "BLI_utildefines_stack.h"
20 
21 #include "BKE_customdata.h"
22 
23 #include "bmesh.h"
24 #include "intern/bmesh_private.h"
25 
27 {
29  BLI_assert(l != NULL);
30  return BM_loop_other_edge_loop(l, v);
31 }
32 
34 {
36  return l->v == v ? l->prev : l->next;
37 }
38 
40 {
41  BMLoop *l_iter = BM_face_vert_share_loop(f, v);
42 
43  BLI_assert(BM_edge_exists(v_prev, v) != NULL);
44 
45  if (l_iter) {
46  if (l_iter->prev->v == v_prev) {
47  return l_iter->next;
48  }
49  if (l_iter->next->v == v_prev) {
50  return l_iter->prev;
51  }
52  /* invalid args */
53  BLI_assert(0);
54  return NULL;
55  }
56  /* invalid args */
57  BLI_assert(0);
58  return NULL;
59 }
60 
62 {
63 #if 0 /* works but slow */
65 #else
66  BMEdge *e = l->e;
67  BMVert *v_prev = BM_edge_other_vert(e, v);
68  if (l->v == v) {
69  if (l->prev->v == v_prev) {
70  return l->next;
71  }
72  BLI_assert(l->next->v == v_prev);
73 
74  return l->prev;
75  }
76  BLI_assert(l->v == v_prev);
77 
78  if (l->prev->v == v) {
79  return l->prev->prev;
80  }
81  BLI_assert(l->next->v == v);
82  return l->next->next;
83 #endif
84 }
85 
87 {
89  if (l->e == e) {
90  return l->next;
91  }
92  if (l->prev->e == e) {
93  return l->prev;
94  }
95 
96  BLI_assert(0);
97  return NULL;
98 }
99 
101 {
102  if (v_a->e && v_b->e) {
103  BMIter iter;
104  BMFace *f;
105 
106  BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) {
107  if (BM_vert_in_face(v_b, f)) {
108  return true;
109  }
110  }
111  }
112 
113  return false;
114 }
115 
117  BMVert *v_b,
118  bool (*test_fn)(BMFace *, void *user_data),
119  void *user_data)
120 {
121  if (v_a->e && v_b->e) {
122  BMIter iter;
123  BMFace *f;
124 
125  BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) {
126  if (test_fn(f, user_data)) {
127  if (BM_vert_in_face(v_b, f)) {
128  return true;
129  }
130  }
131  }
132  }
133 
134  return false;
135 }
136 
138  BMVert *v_b,
139  const bool allow_adjacent,
140  bool (*callback)(BMFace *, BMLoop *, BMLoop *, void *userdata),
141  void *user_data,
142  BMLoop **r_l_a,
143  BMLoop **r_l_b)
144 {
145  if (v_a->e && v_b->e) {
146  BMIter iter;
147  BMLoop *l_a, *l_b;
148 
149  BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) {
150  BMFace *f = l_a->f;
151  l_b = BM_face_vert_share_loop(f, v_b);
152  if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b)) &&
153  callback(f, l_a, l_b, user_data)) {
154  *r_l_a = l_a;
155  *r_l_b = l_b;
156 
157  return f;
158  }
159  }
160  }
161 
162  return NULL;
163 }
164 
166  BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
167 {
168  BMLoop *l_cur_a = NULL, *l_cur_b = NULL;
169  BMFace *f_cur = NULL;
170 
171  if (v_a->e && v_b->e) {
172  BMIter iter;
173  BMLoop *l_a, *l_b;
174 
175  BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) {
176  if ((f_cur == NULL) || (l_a->f->len < f_cur->len)) {
177  l_b = BM_face_vert_share_loop(l_a->f, v_b);
178  if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) {
179  f_cur = l_a->f;
180  l_cur_a = l_a;
181  l_cur_b = l_b;
182  }
183  }
184  }
185  }
186 
187  *r_l_a = l_cur_a;
188  *r_l_b = l_cur_b;
189 
190  return f_cur;
191 }
192 
194  BMEdge *e_a, BMEdge *e_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
195 {
196  BMLoop *l_cur_a = NULL, *l_cur_b = NULL;
197  BMFace *f_cur = NULL;
198 
199  if (e_a->l && e_b->l) {
200  BMIter iter;
201  BMLoop *l_a, *l_b;
202 
203  BM_ITER_ELEM (l_a, &iter, e_a, BM_LOOPS_OF_EDGE) {
204  if ((f_cur == NULL) || (l_a->f->len < f_cur->len)) {
205  l_b = BM_face_edge_share_loop(l_a->f, e_b);
206  if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) {
207  f_cur = l_a->f;
208  l_cur_a = l_a;
209  l_cur_b = l_b;
210  }
211  }
212  }
213  }
214 
215  *r_l_a = l_cur_a;
216  *r_l_b = l_cur_b;
217 
218  return f_cur;
219 }
220 
222 {
223  float no[2][3];
224 
225  if ((BM_face_calc_normal_subset(l_a, l_b, no[0]) != 0.0f) &&
226  (BM_face_calc_normal_subset(l_b, l_a, no[1]) != 0.0f)) {
227  return dot_v3v3(no[0], no[1]);
228  }
229  return -1.0f;
230 }
231 
232 float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3])
233 {
234  const float *axis = l->f->no;
235  return dist_signed_squared_to_corner_v3v3v3(co, l->prev->v->co, l->v->co, l->next->v->co, axis);
236 }
237 
238 float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3])
239 {
240  const float *axis = l->f->no;
241  float dir[3];
242  float plane[4];
243 
244  sub_v3_v3v3(dir, l->next->v->co, l->v->co);
245  cross_v3_v3v3(plane, axis, dir);
246 
247  plane[3] = -dot_v3v3(plane, l->v->co);
248  return dist_signed_squared_to_plane_v3(co, plane);
249 }
250 
252  BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
253 {
254  BMLoop *l_cur_a = NULL, *l_cur_b = NULL;
255  BMFace *f_cur = NULL;
256 
257  if (v_a->e && v_b->e) {
258  BMIter iter;
259  BMLoop *l_a, *l_b;
260  float dot_best = -1.0f;
261 
262  BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) {
263  l_b = BM_face_vert_share_loop(l_a->f, v_b);
264  if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) {
265 
266  if (f_cur == NULL) {
267  f_cur = l_a->f;
268  l_cur_a = l_a;
269  l_cur_b = l_b;
270  }
271  else {
272  /* avoid expensive calculations if we only ever find one face */
273  float dot;
274  if (dot_best == -1.0f) {
275  dot_best = bm_face_calc_split_dot(l_cur_a, l_cur_b);
276  }
277 
279  if (dot > dot_best) {
280  dot_best = dot;
281 
282  f_cur = l_a->f;
283  l_cur_a = l_a;
284  l_cur_b = l_b;
285  }
286  }
287  }
288  }
289  }
290 
291  *r_l_a = l_cur_a;
292  *r_l_b = l_cur_b;
293 
294  return f_cur;
295 }
296 
298 {
299  return v->e ? bmesh_disk_faceloop_find_first(v->e, v) : NULL;
300 }
302 {
304 }
305 
307 {
308  BMLoop *l_iter, *l_first;
309 
310 #ifdef USE_BMESH_HOLES
311  BMLoopList *lst;
312  for (lst = f->loops.first; lst; lst = lst->next)
313 #endif
314  {
315 #ifdef USE_BMESH_HOLES
316  l_iter = l_first = lst->first;
317 #else
318  l_iter = l_first = f->l_first;
319 #endif
320  do {
321  if (l_iter->v == v) {
322  return true;
323  }
324  } while ((l_iter = l_iter->next) != l_first);
325  }
326 
327  return false;
328 }
329 
331 {
332  BMLoop *l_iter, *l_first;
333 
334 #ifdef USE_BMESH_HOLES
335  BMLoopList *lst;
336 #endif
337 
338  int i, count = 0;
339 
340  for (i = 0; i < len; i++) {
342  }
343 
344 #ifdef USE_BMESH_HOLES
345  for (lst = f->loops.first; lst; lst = lst->next)
346 #endif
347  {
348 
349 #ifdef USE_BMESH_HOLES
350  l_iter = l_first = lst->first;
351 #else
352  l_iter = l_first = f->l_first;
353 #endif
354 
355  do {
356  if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) {
357  count++;
358  }
359 
360  } while ((l_iter = l_iter->next) != l_first);
361  }
362 
363  for (i = 0; i < len; i++) {
365  }
366 
367  return count;
368 }
369 
370 bool BM_verts_in_face(BMVert **varr, int len, BMFace *f)
371 {
372  BMLoop *l_iter, *l_first;
373 
374 #ifdef USE_BMESH_HOLES
375  BMLoopList *lst;
376 #endif
377 
378  int i;
379  bool ok = true;
380 
381  /* simple check, we know can't succeed */
382  if (f->len < len) {
383  return false;
384  }
385 
386  for (i = 0; i < len; i++) {
388  }
389 
390 #ifdef USE_BMESH_HOLES
391  for (lst = f->loops.first; lst; lst = lst->next)
392 #endif
393  {
394 
395 #ifdef USE_BMESH_HOLES
396  l_iter = l_first = lst->first;
397 #else
398  l_iter = l_first = f->l_first;
399 #endif
400 
401  do {
402  if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) {
403  /* pass */
404  }
405  else {
406  ok = false;
407  break;
408  }
409 
410  } while ((l_iter = l_iter->next) != l_first);
411  }
412 
413  for (i = 0; i < len; i++) {
415  }
416 
417  return ok;
418 }
419 
420 bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
421 {
422  if (e->l) {
423  const BMLoop *l_iter, *l_first;
424 
425  l_iter = l_first = e->l;
426  do {
427  if (l_iter->f == f) {
428  return true;
429  }
430  } while ((l_iter = l_iter->radial_next) != l_first);
431  }
432 
433  return false;
434 }
435 
437 {
438  BMLoop *l_other;
439 
440  // BLI_assert(BM_edge_is_manifold(e)); // TOO strict, just check if we have another radial face
441  BLI_assert(e->l && e->l->radial_next != e->l);
443 
444  l_other = (l->e == e) ? l : l->prev;
445  l_other = l_other->radial_next;
446  BLI_assert(l_other->e == e);
447 
448  if (l_other->v == l->v) {
449  /* pass */
450  }
451  else if (l_other->next->v == l->v) {
452  l_other = l_other->next;
453  }
454  else {
455  BLI_assert(0);
456  }
457 
458  return l_other;
459 }
460 
462 {
463  BMEdge *e_prev = *e_step;
464  BMEdge *e_next;
465  if (l->e == e_prev) {
466  e_next = l->prev->e;
467  }
468  else if (l->prev->e == e_prev) {
469  e_next = l->e;
470  }
471  else {
472  BLI_assert(0);
473  return NULL;
474  }
475 
476  if (BM_edge_is_manifold(e_next)) {
477  return BM_edge_other_loop((*e_step = e_next), l);
478  }
479  return NULL;
480 }
481 
483 {
484  BMLoop *l_a;
485  int tot = 0;
486  int i;
487 
488  BLI_assert(BM_vert_in_edge(e_first, v));
489 
490  l_a = e_first->l;
491  do {
492  l_a = BM_loop_other_vert_loop(l_a, v);
493  l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev;
494  if (BM_edge_is_manifold(l_a->e)) {
495  l_a = l_a->radial_next;
496  }
497  else {
498  return NULL;
499  }
500 
501  tot++;
502  } while (l_a != e_first->l);
503 
504  /* we know the total, now loop half way */
505  tot /= 2;
506  i = 0;
507 
508  l_a = e_first->l;
509  do {
510  if (i == tot) {
511  l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev;
512  return l_a->e;
513  }
514 
515  l_a = BM_loop_other_vert_loop(l_a, v);
516  l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev;
517  if (BM_edge_is_manifold(l_a->e)) {
518  l_a = l_a->radial_next;
519  }
520  /* this won't have changed from the previous loop */
521 
522  i++;
523  } while (l_a != e_first->l);
524 
525  return NULL;
526 }
527 
529 {
530  return len_v3v3(e->v1->co, e->v2->co);
531 }
532 
534 {
535  return len_squared_v3v3(e->v1->co, e->v2->co);
536 }
537 
538 bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
539 {
540  BMLoop *la, *lb;
541 
542  if ((la = e->l) && (lb = la->radial_next) && (la != lb) && (lb->radial_next == la)) {
543  *r_fa = la->f;
544  *r_fb = lb->f;
545  return true;
546  }
547 
548  *r_fa = NULL;
549  *r_fb = NULL;
550  return false;
551 }
552 
553 bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
554 {
555  BMLoop *la, *lb;
556 
557  if ((la = e->l) && (lb = la->radial_next) && (la != lb) && (lb->radial_next == la)) {
558  *r_la = la;
559  *r_lb = lb;
560  return true;
561  }
562 
563  *r_la = NULL;
564  *r_lb = NULL;
565  return false;
566 }
567 
569 {
570  const BMEdge *e = v->e;
571  if (e) {
572  BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v);
573  return ((e_other != e) && (BM_DISK_EDGE_NEXT(e_other, v) == e));
574  }
575  return false;
576 }
577 
579 {
580  const BMEdge *e = v->e;
581  if (e) {
582  BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v);
583  if (((e_other != e) && (BM_DISK_EDGE_NEXT(e_other, v) == e))) {
584  return BM_edge_is_manifold(e) && BM_edge_is_manifold(e_other);
585  }
586  }
587  return false;
588 }
589 
590 bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b)
591 {
592  BMEdge *e_a = v->e;
593  if (e_a) {
594  BMEdge *e_b = BM_DISK_EDGE_NEXT(e_a, v);
595  if ((e_b != e_a) && (BM_DISK_EDGE_NEXT(e_b, v) == e_a)) {
596  *r_e_a = e_a;
597  *r_e_b = e_b;
598  return true;
599  }
600  }
601 
602  *r_e_a = NULL;
603  *r_e_b = NULL;
604  return false;
605 }
606 
608 {
609  return bmesh_disk_count(v);
610 }
611 
612 int BM_vert_edge_count_at_most(const BMVert *v, const int count_max)
613 {
614  return bmesh_disk_count_at_most(v, count_max);
615 }
616 
618 {
619  int count = 0;
620  BMIter eiter;
621  BMEdge *edge;
622  BM_ITER_ELEM (edge, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) {
623  if (edge->l) {
624  count++;
625  }
626  }
627  return count;
628 }
630 {
631  int count = 0;
632 
633  if (e->l) {
634  BMLoop *l_iter, *l_first;
635 
636  l_iter = l_first = e->l;
637  do {
638  count++;
639  } while ((l_iter = l_iter->radial_next) != l_first);
640  }
641 
642  return count;
643 }
644 
645 int BM_edge_face_count_at_most(const BMEdge *e, const int count_max)
646 {
647  int count = 0;
648 
649  if (e->l) {
650  BMLoop *l_iter, *l_first;
651 
652  l_iter = l_first = e->l;
653  do {
654  count++;
655  if (count == count_max) {
656  break;
657  }
658  } while ((l_iter = l_iter->radial_next) != l_first);
659  }
660 
661  return count;
662 }
663 
665 {
667 }
668 
669 int BM_vert_face_count_at_most(const BMVert *v, int count_max)
670 {
671  return bmesh_disk_facevert_count_at_most(v, count_max);
672 }
673 
675 {
676  if (v->e != NULL) {
677  const BMEdge *e_iter, *e_first;
678  e_first = e_iter = v->e;
679  do {
680  if (e_iter->l != NULL) {
681  return true;
682  }
683  } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
684  }
685  return false;
686 }
687 
689 {
690  if (v->e) {
691  BMEdge *e_first, *e_iter;
692 
693  e_first = e_iter = v->e;
694  do {
695  if (e_iter->l) {
696  return false;
697  }
698  } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
699 
700  return true;
701  }
702  return false;
703 }
704 
706 {
707  BMEdge *e_iter, *e_first, *e_prev;
708  BMLoop *l_iter, *l_first;
709  int loop_num = 0, loop_num_region = 0, boundary_num = 0;
710 
711  if (v->e == NULL) {
712  /* loose vert */
713  return false;
714  }
715 
716  /* count edges while looking for non-manifold edges */
717  e_first = e_iter = v->e;
718  /* may be null */
719  l_first = e_iter->l;
720  do {
721  /* loose edge or edge shared by more than two faces,
722  * edges with 1 face user are OK, otherwise we could
723  * use BM_edge_is_manifold() here */
724  if (e_iter->l == NULL || (e_iter->l != e_iter->l->radial_next->radial_next)) {
725  return false;
726  }
727 
728  /* count radial loops */
729  if (e_iter->l->v == v) {
730  loop_num += 1;
731  }
732 
733  if (!BM_edge_is_boundary(e_iter)) {
734  /* non boundary check opposite loop */
735  if (e_iter->l->radial_next->v == v) {
736  loop_num += 1;
737  }
738  }
739  else {
740  /* start at the boundary */
741  l_first = e_iter->l;
742  boundary_num += 1;
743  /* >2 boundaries can't be manifold */
744  if (boundary_num == 3) {
745  return false;
746  }
747  }
748  } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
749 
750  e_first = l_first->e;
751  l_first = (l_first->v == v) ? l_first : l_first->next;
752  BLI_assert(l_first->v == v);
753 
754  l_iter = l_first;
755  e_prev = e_first;
756 
757  do {
758  loop_num_region += 1;
759  } while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL));
760 
761  return (loop_num == loop_num_region);
762 }
763 
764 #define LOOP_VISIT _FLAG_WALK
765 #define EDGE_VISIT _FLAG_WALK
766 
768 {
769  BMLoop *l_iter, *l_first;
770  int count = 0;
771 
774 
775  l_iter = l_first = e->l;
776  do {
777  if (l_iter->v == v) {
778  BMEdge *e_other = l_iter->prev->e;
779  if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
781  count += 1;
782  }
783  if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) {
785  }
786  }
787  else if (l_iter->next->v == v) {
788  BMEdge *e_other = l_iter->next->e;
789  if (!BM_ELEM_API_FLAG_TEST(l_iter->next, LOOP_VISIT)) {
791  count += 1;
792  }
793  if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) {
795  }
796  }
797  else {
798  BLI_assert(0);
799  }
800  } while ((l_iter = l_iter->radial_next) != l_first);
801 
802  return count;
803 }
804 
806 {
807  int count = 0;
808  BMEdge *e_iter, *e_first;
809 
810  /* clear flags */
811  e_iter = e_first = l->e;
812  do {
814  if (e_iter->l) {
815  BMLoop *l_iter, *l_first;
816  l_iter = l_first = e_iter->l;
817  do {
818  if (l_iter->v == l->v) {
820  count += 1;
821  }
822  } while ((l_iter = l_iter->radial_next) != l_first);
823  }
824  } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, l->v)) != e_first);
825 
826  return count;
827 }
828 
830 {
831  const int count = bm_loop_region_count__recursive(l->e, l->v);
832  const int count_total = bm_loop_region_count__clear(l);
833  if (r_loop_total) {
834  *r_loop_total = count_total;
835  }
836  return count;
837 }
838 
839 #undef LOOP_VISIT
840 #undef EDGE_VISIT
841 
843 {
845 }
846 
848 {
849  BMLoop *l_first = BM_vert_find_first_loop((BMVert *)v);
850  if (l_first) {
851  int count, count_total;
852  count = BM_loop_region_loops_count_at_most(l_first, &count_total);
853  return (count == count_total);
854  }
855  return true;
856 }
857 
859 {
860  if (BM_edge_is_manifold(e)) {
861  BMLoop *l1 = e->l;
862  BMLoop *l2 = e->l->radial_next;
863  if (!equals_v3v3(l1->f->no, l2->f->no)) {
864  float cross[3];
865  float l_dir[3];
866  cross_v3_v3v3(cross, l1->f->no, l2->f->no);
867  /* we assume contiguous normals, otherwise the result isn't meaningful */
868  sub_v3_v3v3(l_dir, l1->next->v->co, l1->v->co);
869  return (dot_v3v3(l_dir, cross) > 0.0f);
870  }
871  }
872  return true;
873 }
874 
876  const int cd_loop_type,
877  const int cd_loop_offset)
878 {
879  BLI_assert(cd_loop_offset != -1);
880 
881  if (e->l && e->l->radial_next != e->l) {
882  const BMLoop *l_base_v1 = e->l;
883  const BMLoop *l_base_v2 = e->l->next;
884  const void *l_base_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_base_v1, cd_loop_offset);
885  const void *l_base_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_base_v2, cd_loop_offset);
886  const BMLoop *l_iter = e->l->radial_next;
887  do {
888  const BMLoop *l_iter_v1;
889  const BMLoop *l_iter_v2;
890  const void *l_iter_cd_v1;
891  const void *l_iter_cd_v2;
892 
893  if (l_iter->v == l_base_v1->v) {
894  l_iter_v1 = l_iter;
895  l_iter_v2 = l_iter->next;
896  }
897  else {
898  l_iter_v1 = l_iter->next;
899  l_iter_v2 = l_iter;
900  }
901  BLI_assert((l_iter_v1->v == l_base_v1->v) && (l_iter_v2->v == l_base_v2->v));
902 
903  l_iter_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_iter_v1, cd_loop_offset);
904  l_iter_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_iter_v2, cd_loop_offset);
905 
906  if ((CustomData_data_equals(cd_loop_type, l_base_cd_v1, l_iter_cd_v1) == 0) ||
907  (CustomData_data_equals(cd_loop_type, l_base_cd_v2, l_iter_cd_v2) == 0)) {
908  return false;
909  }
910 
911  } while ((l_iter = l_iter->radial_next) != e->l);
912  }
913  return true;
914 }
915 
917 {
918  if (v->e) {
919  BMEdge *e_first, *e_iter;
920 
921  e_first = e_iter = v->e;
922  do {
923  if (BM_edge_is_boundary(e_iter)) {
924  return true;
925  }
926  } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
927 
928  return false;
929  }
930  return false;
931 }
932 
934 {
935  BMIter iter1, iter2;
936  BMEdge *e;
937  BMFace *f;
938  int count = 0;
939 
940  BM_ITER_ELEM (e, &iter1, f_a, BM_EDGES_OF_FACE) {
941  BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) {
942  if (f != f_a && f != f_b && BM_face_share_edge_check(f, f_b)) {
943  count++;
944  }
945  }
946  }
947 
948  return count;
949 }
950 
952 {
953  BMIter iter1, iter2;
954  BMEdge *e;
955  BMFace *f;
956 
957  BM_ITER_ELEM (e, &iter1, f_a, BM_EDGES_OF_FACE) {
958  BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) {
959  if (f != f_a && f != f_b && BM_face_share_edge_check(f, f_b)) {
960  return true;
961  }
962  }
963  }
964 
965  return false;
966 }
967 
969 {
970  BMLoop *l_iter;
971  BMLoop *l_first;
972  int count = 0;
973 
974  l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
975  do {
976  if (BM_edge_in_face(l_iter->e, f_b)) {
977  count++;
978  }
979  } while ((l_iter = l_iter->next) != l_first);
980 
981  return count;
982 }
983 
985 {
986  BMLoop *l_iter;
987  BMLoop *l_first;
988 
989  l_iter = l_first = BM_FACE_FIRST_LOOP(f1);
990  do {
991  if (BM_edge_in_face(l_iter->e, f2)) {
992  return true;
993  }
994  } while ((l_iter = l_iter->next) != l_first);
995 
996  return false;
997 }
998 
1000 {
1001  BMLoop *l_iter;
1002  BMLoop *l_first;
1003  int count = 0;
1004 
1005  l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
1006  do {
1007  if (BM_vert_in_face(l_iter->v, f_b)) {
1008  count++;
1009  }
1010  } while ((l_iter = l_iter->next) != l_first);
1011 
1012  return count;
1013 }
1014 
1016 {
1017  BMLoop *l_iter;
1018  BMLoop *l_first;
1019 
1020  l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
1021  do {
1022  if (BM_vert_in_face(l_iter->v, f_b)) {
1023  return true;
1024  }
1025  } while ((l_iter = l_iter->next) != l_first);
1026 
1027  return false;
1028 }
1029 
1031 {
1032  BLI_assert(l_a->v == l_b->v);
1033  return (ELEM(l_a->e, l_b->e, l_b->prev->e) || ELEM(l_b->e, l_a->e, l_a->prev->e));
1034 }
1035 
1037 {
1038  BMLoop *l;
1039  BMFace *f;
1040 
1041  if (e1->l && e2->l) {
1042  l = e1->l;
1043  do {
1044  f = l->f;
1045  if (BM_edge_in_face(e2, f)) {
1046  return true;
1047  }
1048  l = l->radial_next;
1049  } while (l != e1->l);
1050  }
1051  return false;
1052 }
1053 
1055 {
1056  BMLoop *l;
1057  BMFace *f;
1058 
1059  if (e1->l && e2->l) {
1060  l = e1->l;
1061  do {
1062  f = l->f;
1063  if (f->len == 4) {
1064  if (BM_edge_in_face(e2, f)) {
1065  return true;
1066  }
1067  }
1068  l = l->radial_next;
1069  } while (l != e1->l);
1070  }
1071  return false;
1072 }
1073 
1075 {
1076  return (e1->v1 == e2->v1 || e1->v1 == e2->v2 || e1->v2 == e2->v1 || e1->v2 == e2->v2);
1077 }
1078 
1080 {
1081  BLI_assert(e1 != e2);
1082  if (BM_vert_in_edge(e2, e1->v1)) {
1083  return e1->v1;
1084  }
1085  if (BM_vert_in_edge(e2, e1->v2)) {
1086  return e1->v2;
1087  }
1088  return NULL;
1089 }
1090 
1092 {
1094  if (l->v == v) {
1095  return l;
1096  }
1097  return l->next;
1098 }
1099 
1101 {
1102  BMLoop *l_first;
1103  BMLoop *l_iter;
1104 
1105  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1106  do {
1107  if (l_iter->v == v) {
1108  return l_iter;
1109  }
1110  } while ((l_iter = l_iter->next) != l_first);
1111 
1112  return NULL;
1113 }
1114 
1116 {
1117  BMLoop *l_first;
1118  BMLoop *l_iter;
1119 
1120  l_iter = l_first = e->l;
1121  do {
1122  if (l_iter->f == f) {
1123  return l_iter;
1124  }
1125  } while ((l_iter = l_iter->radial_next) != l_first);
1126 
1127  return NULL;
1128 }
1129 
1131  BMVert **r_v1,
1132  BMVert **r_v2,
1133  const BMLoop *edge_loop)
1134 {
1135  BLI_assert(edge_loop->e == edge);
1136  (void)edge; /* quiet warning in release build */
1137  *r_v1 = edge_loop->v;
1138  *r_v2 = edge_loop->next->v;
1139 }
1140 
1141 void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
1142 {
1143  BM_edge_ordered_verts_ex(edge, r_v1, r_v2, edge->l);
1144 }
1145 
1146 BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq)
1147 {
1148  BMLoop *l_step = l->prev;
1149 
1150  BLI_assert(!ELEM(l_stop, NULL, l));
1151 
1152  while (UNLIKELY(len_squared_v3v3(l->v->co, l_step->v->co) < eps_sq)) {
1153  l_step = l_step->prev;
1154  BLI_assert(l_step != l);
1155  if (UNLIKELY(l_step == l_stop)) {
1156  return NULL;
1157  }
1158  }
1159 
1160  return l_step;
1161 }
1162 
1163 BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq)
1164 {
1165  BMLoop *l_step = l->next;
1166 
1167  BLI_assert(!ELEM(l_stop, NULL, l));
1168 
1169  while (UNLIKELY(len_squared_v3v3(l->v->co, l_step->v->co) < eps_sq)) {
1170  l_step = l_step->next;
1171  BLI_assert(l_step != l);
1172  if (UNLIKELY(l_step == l_stop)) {
1173  return NULL;
1174  }
1175  }
1176 
1177  return l_step;
1178 }
1179 
1181 {
1182  float e_dir_prev[3];
1183  float e_dir_next[3];
1184  float l_no[3];
1185 
1186  sub_v3_v3v3(e_dir_prev, l->prev->v->co, l->v->co);
1187  sub_v3_v3v3(e_dir_next, l->next->v->co, l->v->co);
1188  cross_v3_v3v3(l_no, e_dir_next, e_dir_prev);
1189  return dot_v3v3(l_no, l->f->no) > 0.0f;
1190 }
1191 
1193 {
1194  return angle_v3v3v3(l->prev->v->co, l->v->co, l->next->v->co);
1195 }
1196 
1197 float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3])
1198 {
1199  /* NOTE: we cannot use result of normal_tri_v3 here to detect colinear vectors
1200  * (vertex on a straight line) from zero value,
1201  * because it does not normalize both vectors before making cross-product.
1202  * Instead of adding two costly normalize computations,
1203  * just check ourselves for colinear case. */
1204  /* NOTE: FEPSILON might need some finer tweaking at some point?
1205  * Seems to be working OK for now though. */
1206  float v1[3], v2[3], v_tmp[3];
1207  sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
1208  sub_v3_v3v3(v2, l->next->v->co, l->v->co);
1209 
1210  const float fac = ((v2[0] == 0.0f) ?
1211  ((v2[1] == 0.0f) ? ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) :
1212  v1[1] / v2[1]) :
1213  v1[0] / v2[0]);
1214 
1215  mul_v3_v3fl(v_tmp, v2, fac);
1216  sub_v3_v3(v_tmp, v1);
1217  if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) {
1218  /* Not co-linear, we can compute cross-product and normalize it into normal. */
1219  cross_v3_v3v3(r_normal, v1, v2);
1220  return normalize_v3(r_normal);
1221  }
1222  copy_v3_v3(r_normal, l->f->no);
1223  return 0.0f;
1224 }
1225 
1227  const float normal_fallback[3],
1228  float const (*vertexCos)[3],
1229  const float epsilon_sq,
1230  float r_normal[3])
1231 {
1232  const int i_prev = BM_elem_index_get(l->prev->v);
1233  const int i_next = BM_elem_index_get(l->next->v);
1234  const int i = BM_elem_index_get(l->v);
1235 
1236  float v1[3], v2[3], v_tmp[3];
1237  sub_v3_v3v3(v1, vertexCos[i_prev], vertexCos[i]);
1238  sub_v3_v3v3(v2, vertexCos[i_next], vertexCos[i]);
1239 
1240  const float fac = ((v2[0] == 0.0f) ?
1241  ((v2[1] == 0.0f) ? ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) :
1242  v1[1] / v2[1]) :
1243  v1[0] / v2[0]);
1244 
1245  mul_v3_v3fl(v_tmp, v2, fac);
1246  sub_v3_v3(v_tmp, v1);
1247  if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) {
1248  /* Not co-linear, we can compute cross-product and normalize it into normal. */
1249  cross_v3_v3v3(r_normal, v1, v2);
1250  return normalize_v3(r_normal);
1251  }
1252  copy_v3_v3(r_normal, normal_fallback);
1253  return 0.0f;
1254 }
1255 
1256 float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3])
1257 {
1258  return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal);
1259 }
1260 
1262  const float normal_fallback[3],
1263  float const (*vertexCos)[3],
1264  float r_normal[3])
1265 
1266 {
1267  return BM_loop_calc_face_normal_safe_vcos_ex(l, normal_fallback, vertexCos, 1e-5f, r_normal);
1268 }
1269 
1270 float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
1271 {
1272  float v1[3], v2[3];
1273  sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
1274  sub_v3_v3v3(v2, l->next->v->co, l->v->co);
1275 
1276  cross_v3_v3v3(r_normal, v1, v2);
1277  const float len = normalize_v3(r_normal);
1278  if (UNLIKELY(len == 0.0f)) {
1279  copy_v3_v3(r_normal, l->f->no);
1280  }
1281  return len;
1282 }
1283 
1284 void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3])
1285 {
1286  float v_prev[3];
1287  float v_next[3];
1288 
1289  sub_v3_v3v3(v_prev, l->v->co, l->prev->v->co);
1290  sub_v3_v3v3(v_next, l->next->v->co, l->v->co);
1291 
1292  normalize_v3(v_prev);
1293  normalize_v3(v_next);
1294 
1295  add_v3_v3v3(r_dir, v_prev, v_next);
1296  normalize_v3(r_dir);
1297 }
1298 
1299 void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3])
1300 {
1301  float v_prev[3];
1302  float v_next[3];
1303  float dir[3];
1304 
1305  sub_v3_v3v3(v_prev, l->prev->v->co, l->v->co);
1306  sub_v3_v3v3(v_next, l->v->co, l->next->v->co);
1307 
1308  normalize_v3(v_prev);
1309  normalize_v3(v_next);
1310  add_v3_v3v3(dir, v_prev, v_next);
1311 
1312  if (compare_v3v3(v_prev, v_next, FLT_EPSILON * 10.0f) == false) {
1313  float nor[3]; /* for this purpose doesn't need to be normalized */
1314  cross_v3_v3v3(nor, v_prev, v_next);
1315  /* concave face check */
1316  if (UNLIKELY(dot_v3v3(nor, l->f->no) < 0.0f)) {
1317  negate_v3(nor);
1318  }
1319  cross_v3_v3v3(r_tangent, dir, nor);
1320  }
1321  else {
1322  /* prev/next are the same - compare with face normal since we don't have one */
1323  cross_v3_v3v3(r_tangent, dir, l->f->no);
1324  }
1325 
1326  normalize_v3(r_tangent);
1327 }
1328 
1329 float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback)
1330 {
1331  if (BM_edge_is_manifold(e)) {
1332  const BMLoop *l1 = e->l;
1333  const BMLoop *l2 = e->l->radial_next;
1334  return angle_normalized_v3v3(l1->f->no, l2->f->no);
1335  }
1336  return fallback;
1337 }
1339 {
1340  return BM_edge_calc_face_angle_ex(e, DEG2RADF(90.0f));
1341 }
1342 
1344  const float imat3[3][3],
1345  const float fallback)
1346 {
1347  if (BM_edge_is_manifold(e)) {
1348  const BMLoop *l1 = e->l;
1349  const BMLoop *l2 = e->l->radial_next;
1350  float no1[3], no2[3];
1351  copy_v3_v3(no1, l1->f->no);
1352  copy_v3_v3(no2, l2->f->no);
1353 
1354  mul_transposed_m3_v3(imat3, no1);
1355  mul_transposed_m3_v3(imat3, no2);
1356 
1357  normalize_v3(no1);
1358  normalize_v3(no2);
1359 
1360  return angle_normalized_v3v3(no1, no2);
1361  }
1362  return fallback;
1363 }
1364 float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, const float imat3[3][3])
1365 {
1366  return BM_edge_calc_face_angle_with_imat3_ex(e, imat3, DEG2RADF(90.0f));
1367 }
1368 
1369 float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback)
1370 {
1371  if (BM_edge_is_manifold(e)) {
1372  BMLoop *l1 = e->l;
1373  BMLoop *l2 = e->l->radial_next;
1374  const float angle = angle_normalized_v3v3(l1->f->no, l2->f->no);
1375  return BM_edge_is_convex(e) ? angle : -angle;
1376  }
1377  return fallback;
1378 }
1380 {
1382 }
1383 
1384 void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3])
1385 {
1386  float tvec[3];
1387  BMVert *v1, *v2;
1388  BM_edge_ordered_verts_ex(e, &v1, &v2, e_loop);
1389 
1390  sub_v3_v3v3(tvec, v1->co, v2->co); /* use for temp storage */
1391  /* NOTE: we could average the tangents of both loops,
1392  * for non flat ngons it will give a better direction */
1393  cross_v3_v3v3(r_tangent, tvec, e_loop->f->no);
1394  normalize_v3(r_tangent);
1395 }
1396 
1397 float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback)
1398 {
1399  BMEdge *e1, *e2;
1400 
1401  /* Saves `BM_vert_edge_count(v)` and edge iterator,
1402  * get the edges and count them both at once. */
1403 
1404  if ((e1 = v->e) && (e2 = bmesh_disk_edge_next(e1, v)) && (e1 != e2) &&
1405  /* make sure we come full circle and only have 2 connected edges */
1406  (e1 == bmesh_disk_edge_next(e2, v))) {
1407  BMVert *v1 = BM_edge_other_vert(e1, v);
1408  BMVert *v2 = BM_edge_other_vert(e2, v);
1409 
1410  return (float)M_PI - angle_v3v3v3(v1->co, v->co, v2->co);
1411  }
1412  return fallback;
1413 }
1414 
1416 {
1417  return BM_vert_calc_edge_angle_ex(v, DEG2RADF(90.0f));
1418 }
1419 
1421 {
1422  BMIter iter;
1423  BMLoop *l;
1424  float accum_shell = 0.0f;
1425  float accum_angle = 0.0f;
1426 
1427  BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) {
1428  const float face_angle = BM_loop_calc_face_angle(l);
1429  accum_shell += shell_v3v3_normalized_to_dist(v->no, l->f->no) * face_angle;
1430  accum_angle += face_angle;
1431  }
1432 
1433  if (accum_angle != 0.0f) {
1434  return accum_shell / accum_angle;
1435  }
1436  return 1.0f;
1437 }
1438 float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag)
1439 {
1440  BMIter iter;
1441  const BMLoop *l;
1442  float accum_shell = 0.0f;
1443  float accum_angle = 0.0f;
1444  int tot_sel = 0, tot = 0;
1445 
1446  BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) {
1447  if (BM_elem_flag_test(l->f, hflag)) { /* <-- main difference to BM_vert_calc_shell_factor! */
1448  const float face_angle = BM_loop_calc_face_angle(l);
1449  accum_shell += shell_v3v3_normalized_to_dist(no, l->f->no) * face_angle;
1450  accum_angle += face_angle;
1451  tot_sel++;
1452  }
1453  tot++;
1454  }
1455 
1456  if (accum_angle != 0.0f) {
1457  return accum_shell / accum_angle;
1458  }
1459  /* other main difference from BM_vert_calc_shell_factor! */
1460  if (tot != 0 && tot_sel == 0) {
1461  /* none selected, so use all */
1462  return BM_vert_calc_shell_factor(v);
1463  }
1464  return 1.0f;
1465 }
1466 
1468 {
1469  BMIter iter;
1470  BMEdge *e;
1471  int tot;
1472  float length = 0.0f;
1473 
1474  BM_ITER_ELEM_INDEX (e, &iter, (BMVert *)v, BM_EDGES_OF_VERT, tot) {
1475  const BMVert *v_other = BM_edge_other_vert(e, v);
1476  if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
1478  }
1479  }
1480 
1481  if (tot) {
1482  return length / (float)tot;
1483  }
1484  return 0.0f;
1485 }
1486 
1488 {
1489  BMLoop *shortest_loop = NULL;
1490  float shortest_len = FLT_MAX;
1491 
1492  BMLoop *l_iter;
1493  BMLoop *l_first;
1494 
1495  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1496 
1497  do {
1498  const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co);
1499  if (len_sq <= shortest_len) {
1500  shortest_loop = l_iter;
1501  shortest_len = len_sq;
1502  }
1503  } while ((l_iter = l_iter->next) != l_first);
1504 
1505  return shortest_loop;
1506 }
1507 
1509 {
1510  BMLoop *longest_loop = NULL;
1511  float len_max_sq = 0.0f;
1512 
1513  BMLoop *l_iter;
1514  BMLoop *l_first;
1515 
1516  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1517 
1518  do {
1519  const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co);
1520  if (len_sq >= len_max_sq) {
1521  longest_loop = l_iter;
1522  len_max_sq = len_sq;
1523  }
1524  } while ((l_iter = l_iter->next) != l_first);
1525 
1526  return longest_loop;
1527 }
1528 
1535 #if 0
1536 BMEdge *BM_edge_exists(BMVert *v_a, BMVert *v_b)
1537 {
1538  BMIter iter;
1539  BMEdge *e;
1540 
1541  BLI_assert(v_a != v_b);
1542  BLI_assert(v_a->head.htype == BM_VERT && v_b->head.htype == BM_VERT);
1543 
1544  BM_ITER_ELEM (e, &iter, v_a, BM_EDGES_OF_VERT) {
1545  if (e->v1 == v_b || e->v2 == v_b) {
1546  return e;
1547  }
1548  }
1549 
1550  return NULL;
1551 }
1552 #else
1554 {
1555  /* speedup by looping over both edges verts
1556  * where one vert may connect to many edges but not the other. */
1557 
1558  BMEdge *e_a, *e_b;
1559 
1560  BLI_assert(v_a != v_b);
1561  BLI_assert(v_a->head.htype == BM_VERT && v_b->head.htype == BM_VERT);
1562 
1563  if ((e_a = v_a->e) && (e_b = v_b->e)) {
1564  BMEdge *e_a_iter = e_a, *e_b_iter = e_b;
1565 
1566  do {
1567  if (BM_vert_in_edge(e_a_iter, v_b)) {
1568  return e_a_iter;
1569  }
1570  if (BM_vert_in_edge(e_b_iter, v_a)) {
1571  return e_b_iter;
1572  }
1573  } while (((e_a_iter = bmesh_disk_edge_next(e_a_iter, v_a)) != e_a) &&
1574  ((e_b_iter = bmesh_disk_edge_next(e_b_iter, v_b)) != e_b));
1575  }
1576 
1577  return NULL;
1578 }
1579 #endif
1580 
1582 {
1583  BMVert *v = e->v1;
1584  BMVert *v_other = e->v2;
1585 
1586  BMEdge *e_iter;
1587 
1588  e_iter = e;
1589  while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e) {
1590  if (UNLIKELY(BM_vert_in_edge(e_iter, v_other))) {
1591  return e_iter;
1592  }
1593  }
1594 
1595  return NULL;
1596 }
1597 
1599 {
1600  if (e->l != NULL) {
1601  BMLoop *l_iter, *l_first;
1602  l_iter = l_first = e->l;
1603  do {
1604  if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
1605  return l_iter;
1606  }
1607  } while ((l_iter = l_iter->radial_next) != l_first);
1608  }
1609  return NULL;
1610 }
1611 
1613 {
1614  if (varr[0]->e) {
1615  BMEdge *e_iter, *e_first;
1616  e_iter = e_first = varr[0]->e;
1617 
1618  /* would normally use BM_LOOPS_OF_VERT, but this runs so often,
1619  * its faster to iterate on the data directly */
1620  do {
1621  if (e_iter->l) {
1622  BMLoop *l_iter_radial, *l_first_radial;
1623  l_iter_radial = l_first_radial = e_iter->l;
1624 
1625  do {
1626  if ((l_iter_radial->v == varr[0]) && (l_iter_radial->f->len == len)) {
1627  /* the fist 2 verts match, now check the remaining (len - 2) faces do too
1628  * winding isn't known, so check in both directions */
1629  int i_walk = 2;
1630 
1631  if (l_iter_radial->next->v == varr[1]) {
1632  BMLoop *l_walk = l_iter_radial->next->next;
1633  do {
1634  if (l_walk->v != varr[i_walk]) {
1635  break;
1636  }
1637  } while ((void)(l_walk = l_walk->next), ++i_walk != len);
1638  }
1639  else if (l_iter_radial->prev->v == varr[1]) {
1640  BMLoop *l_walk = l_iter_radial->prev->prev;
1641  do {
1642  if (l_walk->v != varr[i_walk]) {
1643  break;
1644  }
1645  } while ((void)(l_walk = l_walk->prev), ++i_walk != len);
1646  }
1647 
1648  if (i_walk == len) {
1649  return l_iter_radial->f;
1650  }
1651  }
1652  } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial);
1653  }
1654  } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, varr[0])) != e_first);
1655  }
1656 
1657  return NULL;
1658 }
1659 
1661 {
1662  BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
1663  for (BMLoop *l_iter = l_first->radial_next; l_first != l_iter; l_iter = l_iter->radial_next) {
1664  if (l_iter->f->len == l_first->f->len) {
1665  if (l_iter->v == l_first->v) {
1666  BMLoop *l_a = l_first, *l_b = l_iter, *l_b_init = l_iter;
1667  do {
1668  if (l_a->e != l_b->e) {
1669  break;
1670  }
1671  } while (((void)(l_a = l_a->next), (l_b = l_b->next)) != l_b_init);
1672  if (l_b == l_b_init) {
1673  return l_iter->f;
1674  }
1675  }
1676  else {
1677  BMLoop *l_a = l_first, *l_b = l_iter, *l_b_init = l_iter;
1678  do {
1679  if (l_a->e != l_b->e) {
1680  break;
1681  }
1682  } while (((void)(l_a = l_a->prev), (l_b = l_b->next)) != l_b_init);
1683  if (l_b == l_b_init) {
1684  return l_iter->f;
1685  }
1686  }
1687  }
1688  }
1689  return NULL;
1690 }
1691 
1692 bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
1693 {
1694  BMFace *f;
1695  BMEdge *e;
1696  BMVert *v;
1697  bool ok;
1698  int tot_tag;
1699 
1700  BMIter fiter;
1701  BMIter viter;
1702 
1703  int i;
1704 
1705  for (i = 0; i < len; i++) {
1706  /* save some time by looping over edge faces rather than vert faces
1707  * will still loop over some faces twice but not as many */
1708  BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) {
1710  BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
1712  }
1713  }
1714 
1715  /* clear all edge tags */
1716  BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) {
1718  }
1719  }
1720 
1721  /* now tag all verts and edges in the boundary array as true so
1722  * we can know if a face-vert is from our array */
1723  for (i = 0; i < len; i++) {
1726  }
1727 
1728  /* so! boundary is tagged, everything else cleared */
1729 
1730  /* 1) tag all faces connected to edges - if all their verts are boundary */
1731  tot_tag = 0;
1732  for (i = 0; i < len; i++) {
1733  BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) {
1735  ok = true;
1736  BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
1738  ok = false;
1739  break;
1740  }
1741  }
1742 
1743  if (ok) {
1744  /* we only use boundary verts */
1746  tot_tag++;
1747  }
1748  }
1749  else {
1750  /* we already found! */
1751  }
1752  }
1753  }
1754 
1755  if (tot_tag == 0) {
1756  /* no faces use only boundary verts, quit early */
1757  ok = false;
1758  goto finally;
1759  }
1760 
1761  /* 2) loop over non-boundary edges that use boundary verts,
1762  * check each have 2 tagged faces connected (faces that only use 'varr' verts) */
1763  ok = true;
1764  for (i = 0; i < len; i++) {
1765  BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) {
1766 
1767  if (/* non-boundary edge */
1769  /* ...using boundary verts */
1772  int tot_face_tag = 0;
1773  BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
1775  tot_face_tag++;
1776  }
1777  }
1778 
1779  if (tot_face_tag != 2) {
1780  ok = false;
1781  break;
1782  }
1783  }
1784  }
1785 
1786  if (ok == false) {
1787  break;
1788  }
1789  }
1790 
1791 finally:
1792  /* Cleanup */
1793  for (i = 0; i < len; i++) {
1796  }
1797  return ok;
1798 }
1799 
1801 {
1802  BMVert **varr = BLI_array_alloca(varr, len);
1803 
1804  /* first check if verts have edges, if not we can bail out early */
1805  if (!BM_verts_from_edges(varr, earr, len)) {
1806  BMESH_ASSERT(0);
1807  return false;
1808  }
1809 
1810  return BM_face_exists_multi(varr, earr, len);
1811 }
1812 
1814 {
1815  BMIter viter;
1816  BMFace *f;
1817  int i;
1818  BMFace *f_overlap = NULL;
1819  LinkNode *f_lnk = NULL;
1820 
1821 #ifdef DEBUG
1822  /* check flag isn't already set */
1823  for (i = 0; i < len; i++) {
1824  BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
1826  }
1827  }
1828 #endif
1829 
1830  for (i = 0; i < len; i++) {
1831  BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
1832  if (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0) {
1833  if (len <= BM_verts_in_face_count(varr, len, f)) {
1834  f_overlap = f;
1835  break;
1836  }
1837 
1839  BLI_linklist_prepend_alloca(&f_lnk, f);
1840  }
1841  }
1842  }
1843 
1844  for (; f_lnk; f_lnk = f_lnk->next) {
1846  }
1847 
1848  return f_overlap;
1849 }
1850 
1852 {
1853  BMIter viter;
1854  BMFace *f;
1855  bool is_init = false;
1856  bool is_overlap = false;
1857  LinkNode *f_lnk = NULL;
1858 
1859 #ifdef DEBUG
1860  /* check flag isn't already set */
1861  for (int i = 0; i < len; i++) {
1863  BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
1865  }
1866  }
1867 #endif
1868 
1869  for (int i = 0; i < len; i++) {
1870  BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
1871  if ((f->len <= len) && (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0)) {
1872  /* Check if all verts in this face are flagged. */
1873  BMLoop *l_iter, *l_first;
1874 
1875  if (is_init == false) {
1876  is_init = true;
1877  for (int j = 0; j < len; j++) {
1879  }
1880  }
1881 
1882  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1883  is_overlap = true;
1884  do {
1885  if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP) == 0) {
1886  is_overlap = false;
1887  break;
1888  }
1889  } while ((l_iter = l_iter->next) != l_first);
1890 
1891  if (is_overlap) {
1892  break;
1893  }
1894 
1896  BLI_linklist_prepend_alloca(&f_lnk, f);
1897  }
1898  }
1899  }
1900 
1901  if (is_init == true) {
1902  for (int i = 0; i < len; i++) {
1904  }
1905  }
1906 
1907  for (; f_lnk; f_lnk = f_lnk->next) {
1909  }
1910 
1911  return is_overlap;
1912 }
1913 
1914 bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide)
1915 {
1916  if (v->e) {
1917  BMEdge *e_other;
1918  BMIter eiter;
1919 
1920  BM_ITER_ELEM (e_other, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) {
1921  if (!respect_hide || !BM_elem_flag_test(e_other, BM_ELEM_HIDDEN)) {
1922  if (!BM_elem_flag_test(e_other, hflag)) {
1923  return false;
1924  }
1925  }
1926  }
1927  }
1928 
1929  return true;
1930 }
1931 
1932 bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide)
1933 {
1934  if (v->e) {
1935  BMEdge *f_other;
1936  BMIter fiter;
1937 
1938  BM_ITER_ELEM (f_other, &fiter, (BMVert *)v, BM_FACES_OF_VERT) {
1939  if (!respect_hide || !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN)) {
1940  if (!BM_elem_flag_test(f_other, hflag)) {
1941  return false;
1942  }
1943  }
1944  }
1945  }
1946 
1947  return true;
1948 }
1949 
1950 bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide)
1951 {
1952  if (e->l) {
1953  BMLoop *l_iter, *l_first;
1954 
1955  l_iter = l_first = e->l;
1956  do {
1957  if (!respect_hide || !BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
1958  if (!BM_elem_flag_test(l_iter->f, hflag)) {
1959  return false;
1960  }
1961  }
1962  } while ((l_iter = l_iter->radial_next) != l_first);
1963  }
1964 
1965  return true;
1966 }
1967 
1968 bool BM_edge_is_any_face_flag_test(const BMEdge *e, const char hflag)
1969 {
1970  if (e->l) {
1971  BMLoop *l_iter, *l_first;
1972 
1973  l_iter = l_first = e->l;
1974  do {
1975  if (BM_elem_flag_test(l_iter->f, hflag)) {
1976  return true;
1977  }
1978  } while ((l_iter = l_iter->radial_next) != l_first);
1979  }
1980 
1981  return false;
1982 }
1983 
1984 bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag)
1985 {
1986  return (BM_elem_flag_test(e->v1, hflag) || BM_elem_flag_test(e->v2, hflag));
1987 }
1988 
1989 bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag)
1990 {
1991  BMLoop *l_iter;
1992  BMLoop *l_first;
1993 
1994  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1995  do {
1996  if (BM_elem_flag_test(l_iter->v, hflag)) {
1997  return true;
1998  }
1999  } while ((l_iter = l_iter->next) != l_first);
2000  return false;
2001 }
2002 
2003 bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag)
2004 {
2005  BMLoop *l_iter;
2006  BMLoop *l_first;
2007 
2008  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
2009  do {
2010  if (BM_elem_flag_test(l_iter->e, hflag)) {
2011  return true;
2012  }
2013  } while ((l_iter = l_iter->next) != l_first);
2014  return false;
2015 }
2016 
2017 bool BM_edge_is_any_face_len_test(const BMEdge *e, const int len)
2018 {
2019  if (e->l) {
2020  BMLoop *l_iter, *l_first;
2021 
2022  l_iter = l_first = e->l;
2023  do {
2024  if (l_iter->f->len == len) {
2025  return true;
2026  }
2027  } while ((l_iter = l_iter->radial_next) != l_first);
2028  }
2029 
2030  return false;
2031 }
2032 
2034 {
2035  const float eps = 0.0001f;
2036  float no[3];
2037 
2038  BM_face_calc_normal(f, no);
2039  return len_squared_v3v3(no, f->no) < (eps * eps);
2040 }
2041 
2047 static double bm_mesh_calc_volume_face(const BMFace *f)
2048 {
2049  const int tottri = f->len - 2;
2050  BMLoop **loops = BLI_array_alloca(loops, f->len);
2051  uint(*index)[3] = BLI_array_alloca(index, tottri);
2052  double vol = 0.0;
2053 
2054  BM_face_calc_tessellation(f, false, loops, index);
2055 
2056  for (int j = 0; j < tottri; j++) {
2057  const float *p1 = loops[index[j][0]]->v->co;
2058  const float *p2 = loops[index[j][1]]->v->co;
2059  const float *p3 = loops[index[j][2]]->v->co;
2060 
2061  double p1_db[3];
2062  double p2_db[3];
2063  double p3_db[3];
2064 
2065  copy_v3db_v3fl(p1_db, p1);
2066  copy_v3db_v3fl(p2_db, p2);
2067  copy_v3db_v3fl(p3_db, p3);
2068 
2069  /* co1.dot(co2.cross(co3)) / 6.0 */
2070  double cross[3];
2071  cross_v3_v3v3_db(cross, p2_db, p3_db);
2072  vol += dot_v3v3_db(p1_db, cross);
2073  }
2074  return (1.0 / 6.0) * vol;
2075 }
2076 double BM_mesh_calc_volume(BMesh *bm, bool is_signed)
2077 {
2078  /* warning, calls own tessellation function, may be slow */
2079  double vol = 0.0;
2080  BMFace *f;
2081  BMIter fiter;
2082 
2083  BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
2084  vol += bm_mesh_calc_volume_face(f);
2085  }
2086 
2087  if (is_signed == false) {
2088  vol = fabs(vol);
2089  }
2090 
2091  return vol;
2092 }
2093 
2095  int *r_groups_array,
2096  int (**r_group_index)[2],
2097  BMLoopFilterFunc filter_fn,
2098  BMLoopPairFilterFunc filter_pair_fn,
2099  void *user_data,
2100  const char hflag_test,
2101  const char htype_step)
2102 {
2103  /* NOTE: almost duplicate of #BM_mesh_calc_edge_groups, keep in sync. */
2104 
2105 #ifdef DEBUG
2106  int group_index_len = 1;
2107 #else
2108  int group_index_len = 32;
2109 #endif
2110 
2111  int(*group_index)[2] = MEM_mallocN(sizeof(*group_index) * group_index_len, __func__);
2112 
2113  int *group_array = r_groups_array;
2114  STACK_DECLARE(group_array);
2115 
2116  int group_curr = 0;
2117 
2118  uint tot_faces = 0;
2119  uint tot_touch = 0;
2120 
2121  BMFace **stack;
2122  STACK_DECLARE(stack);
2123 
2124  BMIter iter;
2125  BMFace *f, *f_next;
2126  int i;
2127 
2128  STACK_INIT(group_array, bm->totface);
2129 
2130  BLI_assert(((htype_step & ~(BM_VERT | BM_EDGE)) == 0) && (htype_step != 0));
2131 
2132  /* init the array */
2133  BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
2134  if ((hflag_test == 0) || BM_elem_flag_test(f, hflag_test)) {
2135  tot_faces++;
2137  }
2138  else {
2139  /* never walk over tagged */
2141  }
2142 
2143  BM_elem_index_set(f, i); /* set_inline */
2144  }
2146 
2147  /* detect groups */
2148  stack = MEM_mallocN(sizeof(*stack) * tot_faces, __func__);
2149 
2150  f_next = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL);
2151 
2152  while (tot_touch != tot_faces) {
2153  int *group_item;
2154  bool ok = false;
2155 
2156  BLI_assert(tot_touch < tot_faces);
2157 
2158  STACK_INIT(stack, tot_faces);
2159 
2160  for (; f_next; f_next = BM_iter_step(&iter)) {
2161  if (BM_elem_flag_test(f_next, BM_ELEM_TAG) == false) {
2163  STACK_PUSH(stack, f_next);
2164  ok = true;
2165  break;
2166  }
2167  }
2168 
2169  BLI_assert(ok == true);
2170  UNUSED_VARS_NDEBUG(ok);
2171 
2172  /* manage arrays */
2173  if (group_index_len == group_curr) {
2174  group_index_len *= 2;
2175  group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_index_len);
2176  }
2177 
2178  group_item = group_index[group_curr];
2179  group_item[0] = STACK_SIZE(group_array);
2180  group_item[1] = 0;
2181 
2182  while ((f = STACK_POP(stack))) {
2183  BMLoop *l_iter, *l_first;
2184 
2185  /* add face */
2186  STACK_PUSH(group_array, BM_elem_index_get(f));
2187  tot_touch++;
2188  group_item[1]++;
2189  /* done */
2190 
2191  if (htype_step & BM_EDGE) {
2192  /* search for other faces */
2193  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
2194  do {
2195  BMLoop *l_radial_iter = l_iter->radial_next;
2196  if ((l_radial_iter != l_iter) && ((filter_fn == NULL) || filter_fn(l_iter, user_data))) {
2197  do {
2198  if ((filter_pair_fn == NULL) || filter_pair_fn(l_iter, l_radial_iter, user_data)) {
2199  BMFace *f_other = l_radial_iter->f;
2200  if (BM_elem_flag_test(f_other, BM_ELEM_TAG) == false) {
2201  BM_elem_flag_enable(f_other, BM_ELEM_TAG);
2202  STACK_PUSH(stack, f_other);
2203  }
2204  }
2205  } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
2206  }
2207  } while ((l_iter = l_iter->next) != l_first);
2208  }
2209 
2210  if (htype_step & BM_VERT) {
2211  BMIter liter;
2212  /* search for other faces */
2213  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
2214  do {
2215  if ((filter_fn == NULL) || filter_fn(l_iter, user_data)) {
2216  BMLoop *l_other;
2217  BM_ITER_ELEM (l_other, &liter, l_iter, BM_LOOPS_OF_LOOP) {
2218  if ((filter_pair_fn == NULL) || filter_pair_fn(l_iter, l_other, user_data)) {
2219  BMFace *f_other = l_other->f;
2220  if (BM_elem_flag_test(f_other, BM_ELEM_TAG) == false) {
2221  BM_elem_flag_enable(f_other, BM_ELEM_TAG);
2222  STACK_PUSH(stack, f_other);
2223  }
2224  }
2225  }
2226  }
2227  } while ((l_iter = l_iter->next) != l_first);
2228  }
2229  }
2230 
2231  group_curr++;
2232  }
2233 
2234  MEM_freeN(stack);
2235 
2236  /* reduce alloc to required size */
2237  if (group_index_len != group_curr) {
2238  group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_curr);
2239  }
2240  *r_group_index = group_index;
2241 
2242  return group_curr;
2243 }
2244 
2246  int *r_groups_array,
2247  int (**r_group_index)[2],
2248  BMVertFilterFunc filter_fn,
2249  void *user_data,
2250  const char hflag_test)
2251 {
2252  /* NOTE: almost duplicate of #BM_mesh_calc_face_groups, keep in sync. */
2253 
2254 #ifdef DEBUG
2255  int group_index_len = 1;
2256 #else
2257  int group_index_len = 32;
2258 #endif
2259 
2260  int(*group_index)[2] = MEM_mallocN(sizeof(*group_index) * group_index_len, __func__);
2261 
2262  int *group_array = r_groups_array;
2263  STACK_DECLARE(group_array);
2264 
2265  int group_curr = 0;
2266 
2267  uint tot_edges = 0;
2268  uint tot_touch = 0;
2269 
2270  BMEdge **stack;
2271  STACK_DECLARE(stack);
2272 
2273  BMIter iter;
2274  BMEdge *e, *e_next;
2275  int i;
2276  STACK_INIT(group_array, bm->totedge);
2277 
2278  /* init the array */
2279  BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
2280  if ((hflag_test == 0) || BM_elem_flag_test(e, hflag_test)) {
2281  tot_edges++;
2283  }
2284  else {
2285  /* never walk over tagged */
2287  }
2288 
2289  BM_elem_index_set(e, i); /* set_inline */
2290  }
2292 
2293  /* detect groups */
2294  stack = MEM_mallocN(sizeof(*stack) * tot_edges, __func__);
2295 
2296  e_next = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL);
2297 
2298  while (tot_touch != tot_edges) {
2299  int *group_item;
2300  bool ok = false;
2301 
2302  BLI_assert(tot_touch < tot_edges);
2303 
2304  STACK_INIT(stack, tot_edges);
2305 
2306  for (; e_next; e_next = BM_iter_step(&iter)) {
2307  if (BM_elem_flag_test(e_next, BM_ELEM_TAG) == false) {
2309  STACK_PUSH(stack, e_next);
2310  ok = true;
2311  break;
2312  }
2313  }
2314 
2315  BLI_assert(ok == true);
2316  UNUSED_VARS_NDEBUG(ok);
2317 
2318  /* manage arrays */
2319  if (group_index_len == group_curr) {
2320  group_index_len *= 2;
2321  group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_index_len);
2322  }
2323 
2324  group_item = group_index[group_curr];
2325  group_item[0] = STACK_SIZE(group_array);
2326  group_item[1] = 0;
2327 
2328  while ((e = STACK_POP(stack))) {
2329  BMIter viter;
2330  BMIter eiter;
2331  BMVert *v;
2332 
2333  /* add edge */
2334  STACK_PUSH(group_array, BM_elem_index_get(e));
2335  tot_touch++;
2336  group_item[1]++;
2337  /* done */
2338 
2339  /* search for other edges */
2340  BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
2341  if ((filter_fn == NULL) || filter_fn(v, user_data)) {
2342  BMEdge *e_other;
2343  BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) {
2344  if (BM_elem_flag_test(e_other, BM_ELEM_TAG) == false) {
2345  BM_elem_flag_enable(e_other, BM_ELEM_TAG);
2346  STACK_PUSH(stack, e_other);
2347  }
2348  }
2349  }
2350  }
2351  }
2352 
2353  group_curr++;
2354  }
2355 
2356  MEM_freeN(stack);
2357 
2358  /* reduce alloc to required size */
2359  if (group_index_len != group_curr) {
2360  group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_curr);
2361  }
2362  *r_group_index = group_index;
2363 
2364  return group_curr;
2365 }
2366 
2368  BMesh *bm, BMVert **verts, BMEdge **edges, BMFace **faces, int (**r_groups)[3])
2369 {
2370  int(*groups)[3] = MEM_mallocN(sizeof(*groups) * bm->totvert, __func__);
2371  STACK_DECLARE(groups);
2372  STACK_INIT(groups, bm->totvert);
2373 
2374  /* Clear all selected vertices */
2376 
2377  BMVert **stack = MEM_mallocN(sizeof(*stack) * bm->totvert, __func__);
2378  STACK_DECLARE(stack);
2379  STACK_INIT(stack, bm->totvert);
2380 
2383 
2384  STACK_DECLARE(edges);
2385  STACK_INIT(edges, bm->totedge);
2386 
2389 
2390  BMIter iter;
2391  BMVert *v_stack_init;
2392  BM_ITER_MESH (v_stack_init, &iter, bm, BM_VERTS_OF_MESH) {
2393  if (BM_elem_flag_test(v_stack_init, BM_ELEM_TAG)) {
2394  continue;
2395  }
2396 
2397  const uint verts_init = STACK_SIZE(verts);
2398  const uint edges_init = STACK_SIZE(edges);
2399  const uint faces_init = STACK_SIZE(faces);
2400 
2401  /* Initialize stack. */
2402  BM_elem_flag_enable(v_stack_init, BM_ELEM_TAG);
2403  STACK_PUSH(verts, v_stack_init);
2404 
2405  if (v_stack_init->e != NULL) {
2406  BMVert *v_iter = v_stack_init;
2407  do {
2408  BMEdge *e_iter, *e_first;
2409  e_iter = e_first = v_iter->e;
2410  do {
2411  if (!BM_elem_flag_test(e_iter, BM_ELEM_TAG)) {
2413  STACK_PUSH(edges, e_iter);
2414 
2415  if (e_iter->l != NULL) {
2416  BMLoop *l_iter, *l_first;
2417  l_iter = l_first = e_iter->l;
2418  do {
2419  if (!BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) {
2420  BM_elem_flag_enable(l_iter->f, BM_ELEM_TAG);
2421  STACK_PUSH(faces, l_iter->f);
2422  }
2423  } while ((l_iter = l_iter->radial_next) != l_first);
2424  }
2425 
2426  BMVert *v_other = BM_edge_other_vert(e_iter, v_iter);
2427  if (!BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
2428  BM_elem_flag_enable(v_other, BM_ELEM_TAG);
2429  STACK_PUSH(verts, v_other);
2430 
2431  STACK_PUSH(stack, v_other);
2432  }
2433  }
2434  } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_iter)) != e_first);
2435  } while ((v_iter = STACK_POP(stack)));
2436  }
2437 
2438  int *g = STACK_PUSH_RET(groups);
2439  g[0] = STACK_SIZE(verts) - verts_init;
2440  g[1] = STACK_SIZE(edges) - edges_init;
2441  g[2] = STACK_SIZE(faces) - faces_init;
2442  }
2443 
2444  MEM_freeN(stack);
2445 
2446  /* Reduce alloc to required size. */
2447  groups = MEM_reallocN(groups, sizeof(*groups) * STACK_SIZE(groups));
2448  *r_groups = groups;
2449  return STACK_SIZE(groups);
2450 }
2451 
2452 float bmesh_subd_falloff_calc(const int falloff, float val)
2453 {
2454  switch (falloff) {
2455  case SUBD_FALLOFF_SMOOTH:
2456  val = 3.0f * val * val - 2.0f * val * val * val;
2457  break;
2458  case SUBD_FALLOFF_SPHERE:
2459  val = sqrtf(2.0f * val - val * val);
2460  break;
2461  case SUBD_FALLOFF_ROOT:
2462  val = sqrtf(val);
2463  break;
2464  case SUBD_FALLOFF_SHARP:
2465  val = val * val;
2466  break;
2467  case SUBD_FALLOFF_LIN:
2468  break;
2470  val = val * (2.0f - val);
2471  break;
2472  default:
2473  BLI_assert(0);
2474  break;
2475  }
2476 
2477  return val;
2478 }
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_data_equals(int type, const void *data1, const void *data2)
Definition: customdata.cc:3973
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:22
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define M_PI
Definition: BLI_math_base.h:20
MINLINE float shell_v3v3_normalized_to_dist(const float a[3], const float b[3])
float dist_signed_squared_to_plane_v3(const float p[3], const float plane[4])
Definition: math_geom.c:429
float dist_signed_squared_to_corner_v3v3v3(const float p[3], const float v1[3], const float v2[3], const float v3[3], const float axis_ref[3])
Definition: math_geom.c:512
void mul_transposed_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:936
#define DEG2RADF(_deg)
MINLINE bool compare_v3v3(const float a[3], const float b[3], float limit) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
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_v3(float r[3], const float a[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
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 double dot_v3v3_db(const double a[3], const double b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE void copy_v3db_v3fl(double r[3], const float a[3])
MINLINE void cross_v3_v3v3_db(double r[3], const double a[3], const double b[3])
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:361
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:445
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED_VARS_NDEBUG(...)
#define UNLIKELY(x)
#define ELEM(...)
#define STACK_POP(stack)
#define STACK_PUSH(stack, val)
#define STACK_DECLARE(stack)
#define STACK_SIZE(stack)
#define STACK_INIT(stack, stack_num)
#define STACK_PUSH_RET(stack)
_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 MEM_reallocN(vmemh, len)
bool(* BMVertFilterFunc)(const BMVert *, void *user_data)
Definition: bmesh_class.h:503
#define BM_DISK_EDGE_NEXT(e, v)
Definition: bmesh_class.h:625
bool(* BMLoopFilterFunc)(const BMLoop *, void *user_data)
Definition: bmesh_class.h:506
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
bool(* BMLoopPairFilterFunc)(const BMLoop *, const BMLoop *, void *user_data)
Definition: bmesh_class.h:507
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_HIDDEN
Definition: bmesh_class.h:472
@ BM_ELEM_INTERNAL_TAG
Definition: bmesh_class.h:496
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len)
#define BMESH_ASSERT(a)
Definition: bmesh_error.h:80
#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_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)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_LOOPS_OF_LOOP
@ BM_FACES_OF_EDGE
@ BM_FACES_OF_VERT
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_VERTS_OF_EDGE
@ BM_VERTS_OF_FACE
@ BM_FACES_OF_MESH
@ BM_LOOPS_OF_VERT
@ BM_LOOPS_OF_EDGE
@ BM_EDGES_OF_VERT
@ BM_EDGES_OF_FACE
#define BM_ITER_ELEM_INDEX(ele, iter, data, itype, indexvar)
#define BM_iter_new(iter, bm, itype, data)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
@ SUBD_FALLOFF_SHARP
@ SUBD_FALLOFF_SMOOTH
@ SUBD_FALLOFF_INVSQUARE
@ SUBD_FALLOFF_SPHERE
@ SUBD_FALLOFF_LIN
@ SUBD_FALLOFF_ROOT
float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3])
float BM_face_calc_normal(const BMFace *f, float r_no[3])
BMESH UPDATE FACE NORMAL.
void BM_face_calc_tessellation(const BMFace *f, const bool use_fixed_quad, BMLoop **r_loops, uint(*r_index)[3])
@ _FLAG_OVERLAP
Definition: bmesh_private.h:59
#define BM_ELEM_API_FLAG_DISABLE(element, f)
Definition: bmesh_private.h:71
#define BM_ELEM_API_FLAG_TEST(element, f)
Definition: bmesh_private.h:76
int bmesh_disk_count_at_most(const BMVert *v, int count_max)
#define BM_ELEM_API_FLAG_ENABLE(element, f)
Definition: bmesh_private.h:66
int bmesh_disk_count(const BMVert *v)
BMLoop * BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v)
Other Loop in Face Sharing an Edge.
Definition: bmesh_query.c:26
bool BM_face_share_face_check(BMFace *f_a, BMFace *f_b)
Definition: bmesh_query.c:951
float BM_vert_calc_edge_angle(const BMVert *v)
Definition: bmesh_query.c:1415
int BM_mesh_calc_edge_groups_as_arrays(BMesh *bm, BMVert **verts, BMEdge **edges, BMFace **faces, int(**r_groups)[3])
Definition: bmesh_query.c:2367
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1553
float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3])
Definition: bmesh_query.c:1256
int BM_edge_face_count_at_most(const BMEdge *e, const int count_max)
Definition: bmesh_query.c:645
float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3])
Definition: bmesh_query.c:232
void BM_edge_ordered_verts_ex(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2, const BMLoop *edge_loop)
Definition: bmesh_query.c:1130
BMLoop * BM_vert_find_first_loop_visible(BMVert *v)
Definition: bmesh_query.c:301
bool BM_vert_is_wire(const BMVert *v)
Definition: bmesh_query.c:688
bool BM_edge_is_contiguous_loop_cd(const BMEdge *e, const int cd_loop_type, const int cd_loop_offset)
Definition: bmesh_query.c:875
bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide)
Definition: bmesh_query.c:1950
BMLoop * BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq)
Definition: bmesh_query.c:1163
void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
Definition: bmesh_query.c:1141
bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
Definition: bmesh_query.c:1054
int BM_vert_edge_count_at_most(const BMVert *v, const int count_max)
Definition: bmesh_query.c:612
BMFace * BM_edge_pair_share_face_by_len(BMEdge *e_a, BMEdge *e_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
Definition: bmesh_query.c:193
BMLoop * BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v)
Other Loop in Face Sharing a Vertex.
Definition: bmesh_query.c:39
BMEdge * BM_edge_find_double(BMEdge *e)
Definition: bmesh_query.c:1581
float BM_edge_calc_face_angle(const BMEdge *e)
Definition: bmesh_query.c:1338
bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
Definition: bmesh_query.c:1692
bool BM_vert_pair_share_face_check(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:100
int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int(**r_group_index)[2], BMLoopFilterFunc filter_fn, BMLoopPairFilterFunc filter_pair_fn, void *user_data, const char hflag_test, const char htype_step)
Definition: bmesh_query.c:2094
float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag)
Definition: bmesh_query.c:1438
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
Definition: bmesh_query.c:420
BMEdge * BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first)
Definition: bmesh_query.c:482
bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag)
Definition: bmesh_query.c:2003
float BM_loop_calc_face_normal_safe_vcos(const BMLoop *l, const float normal_fallback[3], float const (*vertexCos)[3], float r_normal[3])
Definition: bmesh_query.c:1261
BMLoop * BM_vert_find_first_loop(BMVert *v)
Definition: bmesh_query.c:297
bool BM_edge_is_any_face_len_test(const BMEdge *e, const int len)
Definition: bmesh_query.c:2017
bool BM_face_exists_multi_edge(BMEdge **earr, int len)
Definition: bmesh_query.c:1800
bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b)
Definition: bmesh_query.c:1030
bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag)
Definition: bmesh_query.c:1989
float BM_vert_calc_median_tagged_edge_length(const BMVert *v)
Definition: bmesh_query.c:1467
bool BM_face_share_edge_check(BMFace *f1, BMFace *f2)
Definition: bmesh_query.c:984
static int bm_loop_region_count__recursive(BMEdge *e, BMVert *v)
Definition: bmesh_query.c:767
bool BM_vert_is_manifold_region(const BMVert *v)
Definition: bmesh_query.c:847
void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3])
BM_loop_calc_face_tangent.
Definition: bmesh_query.c:1299
#define LOOP_VISIT
Definition: bmesh_query.c:764
BMFace * BM_face_find_double(BMFace *f)
Definition: bmesh_query.c:1660
bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
Definition: bmesh_query.c:553
bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide)
Definition: bmesh_query.c:1914
bool BM_vert_is_manifold(const BMVert *v)
Definition: bmesh_query.c:705
float BM_loop_calc_face_normal_safe_vcos_ex(const BMLoop *l, const float normal_fallback[3], float const (*vertexCos)[3], const float epsilon_sq, float r_normal[3])
Definition: bmesh_query.c:1226
int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b)
Definition: bmesh_query.c:999
int BM_face_share_edge_count(BMFace *f_a, BMFace *f_b)
Definition: bmesh_query.c:968
bool BM_face_share_vert_check(BMFace *f_a, BMFace *f_b)
Definition: bmesh_query.c:1015
float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e, const float imat3[3][3], const float fallback)
BMESH EDGE/FACE ANGLE.
Definition: bmesh_query.c:1343
float BM_edge_calc_length_squared(const BMEdge *e)
Definition: bmesh_query.c:533
bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
Definition: bmesh_query.c:538
float BM_edge_calc_face_angle_signed(const BMEdge *e)
Definition: bmesh_query.c:1379
float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3])
BM_loop_calc_face_normal.
Definition: bmesh_query.c:1197
BMLoop * BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq)
Definition: bmesh_query.c:1146
float bmesh_subd_falloff_calc(const int falloff, float val)
Definition: bmesh_query.c:2452
bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2)
Definition: bmesh_query.c:1074
float BM_vert_calc_shell_factor(const BMVert *v)
Definition: bmesh_query.c:1420
BMLoop * BM_face_edge_share_loop(BMFace *f, BMEdge *e)
Return the Loop Shared by Face and Edge.
Definition: bmesh_query.c:1115
BMFace * BM_vert_pair_shared_face_cb(BMVert *v_a, BMVert *v_b, const bool allow_adjacent, bool(*callback)(BMFace *, BMLoop *, BMLoop *, void *userdata), void *user_data, BMLoop **r_l_a, BMLoop **r_l_b)
Definition: bmesh_query.c:137
bool BM_face_is_normal_valid(const BMFace *f)
Definition: bmesh_query.c:2033
bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b)
Definition: bmesh_query.c:590
int BM_vert_face_count(const BMVert *v)
Definition: bmesh_query.c:664
int BM_edge_face_count(const BMEdge *e)
Definition: bmesh_query.c:629
float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback)
BMESH VERT/EDGE ANGLE.
Definition: bmesh_query.c:1397
bool BM_verts_in_face(BMVert **varr, int len, BMFace *f)
Definition: bmesh_query.c:370
BMVert * BM_edge_share_vert(BMEdge *e1, BMEdge *e2)
Definition: bmesh_query.c:1079
#define EDGE_VISIT
Definition: bmesh_query.c:765
static float bm_face_calc_split_dot(BMLoop *l_a, BMLoop *l_b)
Definition: bmesh_query.c:221
void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3])
BM_loop_calc_face_direction.
Definition: bmesh_query.c:1284
BMFace * BM_face_exists(BMVert **varr, int len)
Definition: bmesh_query.c:1612
bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
Definition: bmesh_query.c:1036
int BM_loop_region_loops_count(BMLoop *l)
Definition: bmesh_query.c:842
BMLoop * BM_loop_other_vert_loop(BMLoop *l, BMVert *v)
Other Loop in Face Sharing a Vert.
Definition: bmesh_query.c:61
int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int(**r_group_index)[2], BMVertFilterFunc filter_fn, void *user_data, const char hflag_test)
Definition: bmesh_query.c:2245
int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total)
Definition: bmesh_query.c:829
BMLoop * BM_edge_vert_share_loop(BMLoop *l, BMVert *v)
Return the Loop Shared by Edge and Vert.
Definition: bmesh_query.c:1091
bool BM_vert_in_face(BMVert *v, BMFace *f)
Definition: bmesh_query.c:306
bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag)
Definition: bmesh_query.c:1984
BMFace * BM_vert_pair_share_face_by_angle(BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
Definition: bmesh_query.c:251
BMLoop * BM_loop_other_vert_loop_by_edge(BMLoop *l, BMEdge *e)
Definition: bmesh_query.c:86
float BM_edge_calc_length(const BMEdge *e)
Definition: bmesh_query.c:528
BMFace * BM_face_exists_overlap(BMVert **varr, const int len)
Definition: bmesh_query.c:1813
float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback)
BMESH EDGE/FACE ANGLE.
Definition: bmesh_query.c:1329
int BM_vert_edge_count(const BMVert *v)
Definition: bmesh_query.c:607
BMLoop * BM_face_find_shortest_loop(BMFace *f)
Definition: bmesh_query.c:1487
bool BM_loop_is_convex(const BMLoop *l)
Definition: bmesh_query.c:1180
BMLoop * BM_edge_other_loop(BMEdge *e, BMLoop *l)
Definition: bmesh_query.c:436
double BM_mesh_calc_volume(BMesh *bm, bool is_signed)
Definition: bmesh_query.c:2076
BMFace * BM_vert_pair_share_face_by_len(BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
Definition: bmesh_query.c:165
static int bm_loop_region_count__clear(BMLoop *l)
Definition: bmesh_query.c:805
BMLoop * BM_edge_find_first_loop_visible(BMEdge *e)
Definition: bmesh_query.c:1598
float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, const float imat3[3][3])
Definition: bmesh_query.c:1364
float BM_loop_calc_face_angle(const BMLoop *l)
Definition: bmesh_query.c:1192
BMLoop * BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step)
Definition: bmesh_query.c:461
bool BM_vert_face_check(const BMVert *v)
Definition: bmesh_query.c:674
static double bm_mesh_calc_volume_face(const BMFace *f)
Definition: bmesh_query.c:2047
bool BM_vert_is_edge_pair(const BMVert *v)
Definition: bmesh_query.c:568
int BM_vert_face_count_at_most(const BMVert *v, int count_max)
Definition: bmesh_query.c:669
float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback)
BMESH EDGE/FACE ANGLE.
Definition: bmesh_query.c:1369
bool BM_vert_is_edge_pair_manifold(const BMVert *v)
Definition: bmesh_query.c:578
int BM_face_share_face_count(BMFace *f_a, BMFace *f_b)
Definition: bmesh_query.c:933
BMLoop * BM_loop_other_edge_loop(BMLoop *l, BMVert *v)
Definition: bmesh_query.c:33
void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3])
BMESH EDGE/FACE TANGENT.
Definition: bmesh_query.c:1384
float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
BM_loop_calc_face_normal.
Definition: bmesh_query.c:1270
bool BM_vert_is_boundary(const BMVert *v)
Definition: bmesh_query.c:916
int BM_vert_edge_count_nonwire(const BMVert *v)
Definition: bmesh_query.c:617
bool BM_edge_is_convex(const BMEdge *e)
Definition: bmesh_query.c:858
bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide)
Definition: bmesh_query.c:1932
int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f)
Definition: bmesh_query.c:330
BMLoop * BM_face_find_longest_loop(BMFace *f)
Definition: bmesh_query.c:1508
bool BM_edge_is_any_face_flag_test(const BMEdge *e, const char hflag)
Definition: bmesh_query.c:1968
BMLoop * BM_face_vert_share_loop(BMFace *f, BMVert *v)
Return the Loop Shared by Face and Vertex.
Definition: bmesh_query.c:1100
bool BM_face_exists_overlap_subset(BMVert **varr, const int len)
Definition: bmesh_query.c:1851
float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3])
Definition: bmesh_query.c:238
bool BM_vert_pair_share_face_check_cb(BMVert *v_a, BMVert *v_b, bool(*test_fn)(BMFace *, void *user_data), void *user_data)
Definition: bmesh_query.c:116
BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
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
BMLoop * bmesh_disk_faceloop_find_first_visible(const BMEdge *e, const BMVert *v)
BMLoop * bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v)
int bmesh_disk_facevert_count(const BMVert *v)
DISK COUNT FACE VERT.
int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max)
BLI_INLINE BMEdge * bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
void * user_data
DEGForeachIDComponentCallback callback
SyclQueue void void size_t num_bytes void
int len
Definition: draw_manager.c:108
static float verts[][3]
uint nor
int count
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
ccl_device_inline float2 fabs(const float2 &a)
Definition: math_float2.h:222
static char faces[256]
#define sqrtf(x)
Definition: metal/compat.h:243
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
T length(const vec_base< T, Size > &a)
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
const btScalar eps
Definition: poly34.cpp:11
BMVert * v1
Definition: bmesh_class.h:122
BMVert * v2
Definition: bmesh_class.h:122
struct BMLoop * l
Definition: bmesh_class.h:128
int len
Definition: bmesh_class.h:267
float no[3]
Definition: bmesh_class.h:271
BMLoop * l_first
Definition: bmesh_class.h:261
char htype
Definition: bmesh_class.h:64
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
float co[3]
Definition: bmesh_class.h:87
struct BMEdge * e
Definition: bmesh_class.h:97
float no[3]
Definition: bmesh_class.h:88
BMHeader head
Definition: bmesh_class.h:85
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
void * link
Definition: BLI_linklist.h:24
struct LinkNode * next
Definition: BLI_linklist.h:23