Blender  V2.93
bmesh_polygon.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
25 #include "DNA_listBase.h"
26 #include "DNA_meshdata_types.h"
27 #include "DNA_modifier_types.h"
28 
29 #include "MEM_guardedalloc.h"
30 
31 #include "BLI_alloca.h"
32 #include "BLI_heap.h"
33 #include "BLI_linklist.h"
34 #include "BLI_math.h"
35 #include "BLI_memarena.h"
36 #include "BLI_polyfill_2d.h"
38 
39 #include "bmesh.h"
40 #include "bmesh_tools.h"
41 
42 #include "BKE_customdata.h"
43 
44 #include "intern/bmesh_private.h"
45 
51 static float bm_face_calc_poly_normal(const BMFace *f, float n[3])
52 {
53  BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
54  BMLoop *l_iter = l_first;
55  const float *v_prev = l_first->prev->v->co;
56  const float *v_curr = l_first->v->co;
57 
58  zero_v3(n);
59 
60  /* Newell's Method */
61  do {
62  add_newell_cross_v3_v3v3(n, v_prev, v_curr);
63 
64  l_iter = l_iter->next;
65  v_prev = v_curr;
66  v_curr = l_iter->v->co;
67 
68  } while (l_iter != l_first);
69 
70  return normalize_v3(n);
71 }
72 
80  float r_no[3],
81  float const (*vertexCos)[3])
82 {
83  BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
84  BMLoop *l_iter = l_first;
85  const float *v_prev = vertexCos[BM_elem_index_get(l_first->prev->v)];
86  const float *v_curr = vertexCos[BM_elem_index_get(l_first->v)];
87 
88  zero_v3(r_no);
89 
90  /* Newell's Method */
91  do {
92  add_newell_cross_v3_v3v3(r_no, v_prev, v_curr);
93 
94  l_iter = l_iter->next;
95  v_prev = v_curr;
96  v_curr = vertexCos[BM_elem_index_get(l_iter->v)];
97  } while (l_iter != l_first);
98 
99  return normalize_v3(r_no);
100 }
101 
106  float r_cent[3],
107  float const (*vertexCos)[3])
108 {
109  const BMLoop *l_first, *l_iter;
110 
111  zero_v3(r_cent);
112 
113  /* Newell's Method */
114  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
115  do {
116  add_v3_v3(r_cent, vertexCos[BM_elem_index_get(l_iter->v)]);
117  } while ((l_iter = l_iter->next) != l_first);
118  mul_v3_fl(r_cent, 1.0f / f->len);
119 }
120 
131  const bool use_fixed_quad,
132  BMLoop **r_loops,
133  uint (*r_index)[3])
134 {
135  BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
136  BMLoop *l_iter;
137 
138  if (f->len == 3) {
139  *r_loops++ = (l_iter = l_first);
140  *r_loops++ = (l_iter = l_iter->next);
141  *r_loops++ = (l_iter->next);
142 
143  r_index[0][0] = 0;
144  r_index[0][1] = 1;
145  r_index[0][2] = 2;
146  }
147  else if (f->len == 4 && use_fixed_quad) {
148  *r_loops++ = (l_iter = l_first);
149  *r_loops++ = (l_iter = l_iter->next);
150  *r_loops++ = (l_iter = l_iter->next);
151  *r_loops++ = (l_iter->next);
152 
153  r_index[0][0] = 0;
154  r_index[0][1] = 1;
155  r_index[0][2] = 2;
156 
157  r_index[1][0] = 0;
158  r_index[1][1] = 2;
159  r_index[1][2] = 3;
160  }
161  else {
162  float axis_mat[3][3];
163  float(*projverts)[2] = BLI_array_alloca(projverts, f->len);
164  int j;
165 
166  axis_dominant_v3_to_m3_negate(axis_mat, f->no);
167 
168  j = 0;
169  l_iter = l_first;
170  do {
171  mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co);
172  r_loops[j] = l_iter;
173  j++;
174  } while ((l_iter = l_iter->next) != l_first);
175 
176  /* complete the loop */
177  BLI_polyfill_calc(projverts, f->len, 1, r_index);
178  }
179 }
180 
184 void BM_face_calc_point_in_face(const BMFace *f, float r_co[3])
185 {
186  const BMLoop *l_tri[3];
187 
188  if (f->len == 3) {
189  const BMLoop *l = BM_FACE_FIRST_LOOP(f);
190  ARRAY_SET_ITEMS(l_tri, l, l->next, l->prev);
191  }
192  else {
193  /* tessellation here seems overkill when in many cases this will be the center,
194  * but without this we can't be sure the point is inside a concave face. */
195  const int tottri = f->len - 2;
196  BMLoop **loops = BLI_array_alloca(loops, f->len);
197  uint(*index)[3] = BLI_array_alloca(index, tottri);
198  int j;
199  int j_best = 0; /* use as fallback when unset */
200  float area_best = -1.0f;
201 
202  BM_face_calc_tessellation(f, false, loops, index);
203 
204  for (j = 0; j < tottri; j++) {
205  const float *p1 = loops[index[j][0]]->v->co;
206  const float *p2 = loops[index[j][1]]->v->co;
207  const float *p3 = loops[index[j][2]]->v->co;
208  const float area = area_squared_tri_v3(p1, p2, p3);
209  if (area > area_best) {
210  j_best = j;
211  area_best = area;
212  }
213  }
214 
216  l_tri, loops[index[j_best][0]], loops[index[j_best][1]], loops[index[j_best][2]]);
217  }
218 
219  mid_v3_v3v3v3(r_co, l_tri[0]->v->co, l_tri[1]->v->co, l_tri[2]->v->co);
220 }
221 
225 float BM_face_calc_area(const BMFace *f)
226 {
227  /* inline 'area_poly_v3' logic, avoid creating a temp array */
228  const BMLoop *l_iter, *l_first;
229  float n[3];
230 
231  zero_v3(n);
232  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
233  do {
234  add_newell_cross_v3_v3v3(n, l_iter->v->co, l_iter->next->v->co);
235  } while ((l_iter = l_iter->next) != l_first);
236  return len_v3(n) * 0.5f;
237 }
238 
242 float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3])
243 {
244  /* inline 'area_poly_v3' logic, avoid creating a temp array */
245  const BMLoop *l_iter, *l_first;
246  float co[3];
247  float n[3];
248 
249  zero_v3(n);
250  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
251  mul_v3_m3v3(co, mat3, l_iter->v->co);
252  do {
253  float co_next[3];
254  mul_v3_m3v3(co_next, mat3, l_iter->next->v->co);
255  add_newell_cross_v3_v3v3(n, co, co_next);
256  copy_v3_v3(co, co_next);
257  } while ((l_iter = l_iter->next) != l_first);
258  return len_v3(n) * 0.5f;
259 }
260 
264 float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset)
265 {
266  /* inline 'area_poly_v2' logic, avoid creating a temp array */
267  const BMLoop *l_iter, *l_first;
268 
269  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
270  /* The Trapezium Area Rule */
271  float cross = 0.0f;
272  do {
273  const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
274  const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset);
275  cross += (luv_next->uv[0] - luv->uv[0]) * (luv_next->uv[1] + luv->uv[1]);
276  } while ((l_iter = l_iter->next) != l_first);
277  return fabsf(cross * 0.5f);
278 }
279 
284 {
285  const BMLoop *l_iter, *l_first;
286  float perimeter = 0.0f;
287 
288  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
289  do {
290  perimeter += len_v3v3(l_iter->v->co, l_iter->next->v->co);
291  } while ((l_iter = l_iter->next) != l_first);
292 
293  return perimeter;
294 }
295 
299 float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3])
300 {
301  const BMLoop *l_iter, *l_first;
302  float co[3];
303  float perimeter = 0.0f;
304 
305  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
306  mul_v3_m3v3(co, mat3, l_iter->v->co);
307  do {
308  float co_next[3];
309  mul_v3_m3v3(co_next, mat3, l_iter->next->v->co);
310  perimeter += len_v3v3(co, co_next);
311  copy_v3_v3(co, co_next);
312  } while ((l_iter = l_iter->next) != l_first);
313 
314  return perimeter;
315 }
316 
323 {
324  /* find the most 'unique' loop, (greatest difference to others) */
325 #if 1
326  /* optimized version that avoids sqrt */
327  float difs[3];
328  for (int i_prev = 1, i_curr = 2, i_next = 0; i_next < 3; i_prev = i_curr, i_curr = i_next++) {
329  const float *co = verts[i_curr]->co;
330  const float *co_other[2] = {verts[i_prev]->co, verts[i_next]->co};
331  float proj_dir[3];
332  mid_v3_v3v3(proj_dir, co_other[0], co_other[1]);
333  sub_v3_v3(proj_dir, co);
334 
335  float proj_pair[2][3];
336  project_v3_v3v3(proj_pair[0], co_other[0], proj_dir);
337  project_v3_v3v3(proj_pair[1], co_other[1], proj_dir);
338  difs[i_next] = len_squared_v3v3(proj_pair[0], proj_pair[1]);
339  }
340 #else
341  const float lens[3] = {
342  len_v3v3(verts[0]->co, verts[1]->co),
343  len_v3v3(verts[1]->co, verts[2]->co),
344  len_v3v3(verts[2]->co, verts[0]->co),
345  };
346  const float difs[3] = {
347  fabsf(lens[1] - lens[2]),
348  fabsf(lens[2] - lens[0]),
349  fabsf(lens[0] - lens[1]),
350  };
351 #endif
352 
353  int order[3] = {0, 1, 2};
354  axis_sort_v3(difs, order);
355 
356  return order[0];
357 }
358 
367 void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3])
368 {
369  const int index = bm_vert_tri_find_unique_edge(verts);
370 
371  sub_v3_v3v3(r_tangent, verts[index]->co, verts[(index + 1) % 3]->co);
372 
373  normalize_v3(r_tangent);
374 }
375 
384 void BM_vert_tri_calc_tangent_edge_pair(BMVert *verts[3], float r_tangent[3])
385 {
386  const int index = bm_vert_tri_find_unique_edge(verts);
387 
388  const float *v_a = verts[index]->co;
389  const float *v_b = verts[(index + 1) % 3]->co;
390  const float *v_other = verts[(index + 2) % 3]->co;
391 
392  mid_v3_v3v3(r_tangent, v_a, v_b);
393  sub_v3_v3v3(r_tangent, v_other, r_tangent);
394 
395  normalize_v3(r_tangent);
396 }
397 
401 void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3])
402 {
403  const BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f);
404 
405  sub_v3_v3v3(r_tangent, l_long->v->co, l_long->next->v->co);
406 
407  normalize_v3(r_tangent);
408 }
409 
415 void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3])
416 {
417  if (f->len == 3) {
418  BMVert *verts[3];
419 
421 
423  }
424  else if (f->len == 4) {
425  /* Use longest edge pair */
426  BMVert *verts[4];
427  float vec[3], vec_a[3], vec_b[3];
428 
430 
431  sub_v3_v3v3(vec_a, verts[3]->co, verts[2]->co);
432  sub_v3_v3v3(vec_b, verts[0]->co, verts[1]->co);
433  add_v3_v3v3(r_tangent, vec_a, vec_b);
434 
435  sub_v3_v3v3(vec_a, verts[0]->co, verts[3]->co);
436  sub_v3_v3v3(vec_b, verts[1]->co, verts[2]->co);
437  add_v3_v3v3(vec, vec_a, vec_b);
438  /* use the longest edge length */
439  if (len_squared_v3(r_tangent) < len_squared_v3(vec)) {
440  copy_v3_v3(r_tangent, vec);
441  }
442  }
443  else {
444  /* For ngons use two longest disconnected edges */
445  BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f);
446  BMLoop *l_long_other = NULL;
447 
448  float len_max_sq = 0.0f;
449  float vec_a[3], vec_b[3];
450 
451  BMLoop *l_iter = l_long->prev->prev;
452  BMLoop *l_last = l_long->next;
453 
454  do {
455  const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co);
456  if (len_sq >= len_max_sq) {
457  l_long_other = l_iter;
458  len_max_sq = len_sq;
459  }
460  } while ((l_iter = l_iter->prev) != l_last);
461 
462  sub_v3_v3v3(vec_a, l_long->next->v->co, l_long->v->co);
463  sub_v3_v3v3(vec_b, l_long_other->v->co, l_long_other->next->v->co);
464  add_v3_v3v3(r_tangent, vec_a, vec_b);
465 
466  /* Edges may not be opposite side of the ngon,
467  * this could cause problems for ngons with multiple-aligned edges of the same length.
468  * Fallback to longest edge. */
469  if (UNLIKELY(normalize_v3(r_tangent) == 0.0f)) {
470  normalize_v3_v3(r_tangent, vec_a);
471  }
472  }
473 }
474 
480 void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3])
481 {
482  BMLoop *l_iter, *l_first;
483 
484  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
485 
486  /* In case of degenerate faces. */
487  zero_v3(r_tangent);
488 
489  /* warning: O(n^2) loop here, take care! */
490  float dist_max_sq = 0.0f;
491  do {
492  BMLoop *l_iter_other = l_iter->next;
493  BMLoop *l_iter_last = l_iter->prev;
494  do {
495  BLI_assert(!ELEM(l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co));
496  float co_other[3], vec[3];
498  co_other, l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co);
499  sub_v3_v3v3(vec, l_iter->v->co, co_other);
500 
501  const float dist_sq = len_squared_v3(vec);
502  if (dist_sq > dist_max_sq) {
503  dist_max_sq = dist_sq;
504  copy_v3_v3(r_tangent, vec);
505  }
506  } while ((l_iter_other = l_iter_other->next) != l_iter_last);
507  } while ((l_iter = l_iter->next) != l_first);
508 
509  normalize_v3(r_tangent);
510 }
511 
517 void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3])
518 {
519  BMLoop *l_iter, *l_first;
520 
521  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
522 
523  /* In case of degenerate faces. */
524  zero_v3(r_tangent);
525 
526  /* warning: O(n^2) loop here, take care! */
527  float dist_max_sq = 0.0f;
528  do {
529  BMLoop *l_iter_other = l_iter->next;
530  do {
531  float vec[3];
532  sub_v3_v3v3(vec, l_iter->v->co, l_iter_other->v->co);
533 
534  const float dist_sq = len_squared_v3(vec);
535  if (dist_sq > dist_max_sq) {
536  dist_max_sq = dist_sq;
537  copy_v3_v3(r_tangent, vec);
538  }
539  } while ((l_iter_other = l_iter_other->next) != l_iter);
540  } while ((l_iter = l_iter->next) != l_first);
541 
542  normalize_v3(r_tangent);
543 }
544 
550 void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3])
551 {
552  if (f->len == 3) {
553  /* most 'unique' edge of a triangle */
554  BMVert *verts[3];
557  }
558  else if (f->len == 4) {
559  /* longest edge pair of a quad */
560  BM_face_calc_tangent_edge_pair((BMFace *)f, r_tangent);
561  }
562  else {
563  /* longest edge of an ngon */
564  BM_face_calc_tangent_edge((BMFace *)f, r_tangent);
565  }
566 }
567 
571 void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3])
572 {
573  const BMLoop *l_iter, *l_first;
574  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
575  do {
576  minmax_v3v3_v3(min, max, l_iter->v->co);
577  } while ((l_iter = l_iter->next) != l_first);
578 }
579 
583 void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3])
584 {
585  const BMLoop *l_iter, *l_first;
586  float min[3], max[3];
587 
588  INIT_MINMAX(min, max);
589 
590  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
591  do {
592  minmax_v3v3_v3(min, max, l_iter->v->co);
593  } while ((l_iter = l_iter->next) != l_first);
594 
595  mid_v3_v3v3(r_cent, min, max);
596 }
597 
602  const BMFace *f,
603  float r_cent[3],
604  float const (*vertexCos)[3])
605 {
606  /* must have valid index data */
608  (void)bm;
609 
610  const BMLoop *l_iter, *l_first;
611  float min[3], max[3];
612 
613  INIT_MINMAX(min, max);
614 
615  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
616  do {
617  minmax_v3v3_v3(min, max, vertexCos[BM_elem_index_get(l_iter->v)]);
618  } while ((l_iter = l_iter->next) != l_first);
619 
620  mid_v3_v3v3(r_cent, min, max);
621 }
622 
626 void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
627 {
628  const BMLoop *l_iter, *l_first;
629 
630  zero_v3(r_cent);
631 
632  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
633  do {
634  add_v3_v3(r_cent, l_iter->v->co);
635  } while ((l_iter = l_iter->next) != l_first);
636  mul_v3_fl(r_cent, 1.0f / (float)f->len);
637 }
638 
643 void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3])
644 {
645  const BMLoop *l_iter;
646  const BMLoop *l_first;
647  float totw = 0.0f;
648  float w_prev;
649 
650  zero_v3(r_cent);
651 
652  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
653  w_prev = BM_edge_calc_length(l_iter->prev->e);
654  do {
655  const float w_curr = BM_edge_calc_length(l_iter->e);
656  const float w = (w_curr + w_prev);
657  madd_v3_v3fl(r_cent, l_iter->v->co, w);
658  totw += w;
659  w_prev = w_curr;
660  } while ((l_iter = l_iter->next) != l_first);
661 
662  if (totw != 0.0f) {
663  mul_v3_fl(r_cent, 1.0f / (float)totw);
664  }
665 }
666 
673 void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nverts)
674 {
675  float mat[3][3];
676  float co[3];
677  uint i;
678 
679  co[2] = 0.0f;
680 
682  for (i = 0; i < nverts; i++) {
683  mul_v2_m3v3(co, mat, verts[i]);
684  copy_v3_v3(verts[i], co);
685  }
686 }
687 
692 {
693  BMIter iter;
694  BMFace *f;
695 
696  BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
698  }
699 
702 }
703 
704 static void bm_loop_normal_accum(const BMLoop *l, float no[3])
705 {
706  float vec1[3], vec2[3], fac;
707 
708  /* Same calculation used in BM_mesh_normals_update */
709  sub_v3_v3v3(vec1, l->v->co, l->prev->v->co);
710  sub_v3_v3v3(vec2, l->next->v->co, l->v->co);
711  normalize_v3(vec1);
712  normalize_v3(vec2);
713 
714  fac = saacos(-dot_v3v3(vec1, vec2));
715 
716  madd_v3_v3fl(no, l->f->no, fac);
717 }
718 
719 bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3])
720 {
721  int len = 0;
722 
723  zero_v3(r_no);
724 
725  if (v->e) {
726  const BMEdge *e = v->e;
727  do {
728  if (e->l) {
729  const BMLoop *l = e->l;
730  do {
731  if (l->v == v) {
732  if (BM_elem_flag_test(l->f, hflag)) {
733  bm_loop_normal_accum(l, r_no);
734  len++;
735  }
736  }
737  } while ((l = l->radial_next) != e->l);
738  }
739  } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
740  }
741 
742  if (len) {
743  normalize_v3(r_no);
744  return true;
745  }
746  return false;
747 }
748 
749 bool BM_vert_calc_normal(const BMVert *v, float r_no[3])
750 {
751  int len = 0;
752 
753  zero_v3(r_no);
754 
755  if (v->e) {
756  const BMEdge *e = v->e;
757  do {
758  if (e->l) {
759  const BMLoop *l = e->l;
760  do {
761  if (l->v == v) {
762  bm_loop_normal_accum(l, r_no);
763  len++;
764  }
765  } while ((l = l->radial_next) != e->l);
766  }
767  } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
768  }
769 
770  if (len) {
771  normalize_v3(r_no);
772  return true;
773  }
774  return false;
775 }
776 
778 {
779  int len = 0;
780 
781  zero_v3(v->no);
782 
783  if (v->e) {
784  const BMEdge *e = v->e;
785  do {
786  if (e->l) {
787  const BMLoop *l = e->l;
788  do {
789  if (l->v == v) {
792  len++;
793  }
794  } while ((l = l->radial_next) != e->l);
795  }
796  } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
797  }
798 
799  if (len) {
800  normalize_v3(v->no);
801  }
802 }
803 
808 {
810 }
811 
822 float BM_face_calc_normal(const BMFace *f, float r_no[3])
823 {
824  BMLoop *l;
825 
826  /* common cases first */
827  switch (f->len) {
828  case 4: {
829  const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co;
830  const float *co2 = (l = l->next)->v->co;
831  const float *co3 = (l = l->next)->v->co;
832  const float *co4 = (l->next)->v->co;
833 
834  return normal_quad_v3(r_no, co1, co2, co3, co4);
835  }
836  case 3: {
837  const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co;
838  const float *co2 = (l = l->next)->v->co;
839  const float *co3 = (l->next)->v->co;
840 
841  return normal_tri_v3(r_no, co1, co2, co3);
842  }
843  default: {
844  return bm_face_calc_poly_normal(f, r_no);
845  }
846  }
847 }
849 {
850  BM_face_calc_normal(f, f->no);
851 }
852 
853 /* exact same as 'BM_face_calc_normal' but accepts vertex coords */
855  const BMFace *f,
856  float r_no[3],
857  float const (*vertexCos)[3])
858 {
859  BMLoop *l;
860 
861  /* must have valid index data */
863  (void)bm;
864 
865  /* common cases first */
866  switch (f->len) {
867  case 4: {
868  const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)];
869  const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)];
870  const float *co3 = vertexCos[BM_elem_index_get((l = l->next)->v)];
871  const float *co4 = vertexCos[BM_elem_index_get((l->next)->v)];
872 
873  return normal_quad_v3(r_no, co1, co2, co3, co4);
874  }
875  case 3: {
876  const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)];
877  const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)];
878  const float *co3 = vertexCos[BM_elem_index_get((l->next)->v)];
879 
880  return normal_tri_v3(r_no, co1, co2, co3);
881  }
882  default: {
883  return bm_face_calc_poly_normal_vertex_cos(f, r_no, vertexCos);
884  }
885  }
886 }
887 
895  BMVert **varr, int varr_len, float r_normal[3], float r_center[3], int *r_index_tangent)
896 {
897  const float varr_len_inv = 1.0f / (float)varr_len;
898 
899  /* Get the center point and collect vector array since we loop over these a lot. */
900  float center[3] = {0.0f, 0.0f, 0.0f};
901  for (int i = 0; i < varr_len; i++) {
902  madd_v3_v3fl(center, varr[i]->co, varr_len_inv);
903  }
904 
905  /* Find the 'co_a' point from center. */
906  int co_a_index = 0;
907  const float *co_a = NULL;
908  {
909  float dist_sq_max = -1.0f;
910  for (int i = 0; i < varr_len; i++) {
911  const float dist_sq_test = len_squared_v3v3(varr[i]->co, center);
912  if (!(dist_sq_test <= dist_sq_max)) {
913  co_a = varr[i]->co;
914  co_a_index = i;
915  dist_sq_max = dist_sq_test;
916  }
917  }
918  }
919 
920  float dir_a[3];
921  sub_v3_v3v3(dir_a, co_a, center);
922  normalize_v3(dir_a);
923 
924  const float *co_b = NULL;
925  float dir_b[3] = {0.0f, 0.0f, 0.0f};
926  {
927  float dist_sq_max = -1.0f;
928  for (int i = 0; i < varr_len; i++) {
929  if (varr[i]->co == co_a) {
930  continue;
931  }
932  float dir_test[3];
933  sub_v3_v3v3(dir_test, varr[i]->co, center);
934  project_plane_normalized_v3_v3v3(dir_test, dir_test, dir_a);
935  const float dist_sq_test = len_squared_v3(dir_test);
936  if (!(dist_sq_test <= dist_sq_max)) {
937  co_b = varr[i]->co;
938  dist_sq_max = dist_sq_test;
939  copy_v3_v3(dir_b, dir_test);
940  }
941  }
942  }
943 
944  if (varr_len <= 3) {
945  normal_tri_v3(r_normal, center, co_a, co_b);
946  goto finally;
947  }
948 
949  normalize_v3(dir_b);
950 
951  const float *co_a_opposite = NULL;
952  const float *co_b_opposite = NULL;
953 
954  {
955  float dot_a_min = FLT_MAX;
956  float dot_b_min = FLT_MAX;
957  for (int i = 0; i < varr_len; i++) {
958  const float *co_test = varr[i]->co;
959  float dot_test;
960 
961  if (co_test != co_a) {
962  dot_test = dot_v3v3(dir_a, co_test);
963  if (dot_test < dot_a_min) {
964  dot_a_min = dot_test;
965  co_a_opposite = co_test;
966  }
967  }
968 
969  if (co_test != co_b) {
970  dot_test = dot_v3v3(dir_b, co_test);
971  if (dot_test < dot_b_min) {
972  dot_b_min = dot_test;
973  co_b_opposite = co_test;
974  }
975  }
976  }
977  }
978 
979  normal_quad_v3(r_normal, co_a, co_b, co_a_opposite, co_b_opposite);
980 
981 finally:
982  if (r_center != NULL) {
983  copy_v3_v3(r_center, center);
984  }
985  if (r_index_tangent != NULL) {
986  *r_index_tangent = co_a_index;
987  }
988 }
989 
990 void BM_verts_calc_normal_from_cloud(BMVert **varr, int varr_len, float r_normal[3])
991 {
992  BM_verts_calc_normal_from_cloud_ex(varr, varr_len, r_normal, NULL, NULL);
993 }
994 
998 float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3])
999 {
1000  const float *v_prev, *v_curr;
1001 
1002  /* Newell's Method */
1003  const BMLoop *l_iter = l_first;
1004  const BMLoop *l_term = l_last->next;
1005 
1006  zero_v3(r_no);
1007 
1008  v_prev = l_last->v->co;
1009  do {
1010  v_curr = l_iter->v->co;
1011  add_newell_cross_v3_v3v3(r_no, v_prev, v_curr);
1012  v_prev = v_curr;
1013  } while ((l_iter = l_iter->next) != l_term);
1014 
1015  return normalize_v3(r_no);
1016 }
1017 
1018 /* exact same as 'BM_face_calc_normal' but accepts vertex coords */
1020  const BMFace *f,
1021  float r_cent[3],
1022  float const (*vertexCos)[3])
1023 {
1024  /* must have valid index data */
1026  (void)bm;
1027 
1028  bm_face_calc_poly_center_median_vertex_cos(f, r_cent, vertexCos);
1029 }
1030 
1038  BMFace *f,
1039  const int cd_loop_mdisp_offset,
1040  const bool use_loop_mdisp_flip)
1041 {
1042  bmesh_kernel_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip);
1043  negate_v3(f->no);
1044 }
1045 
1047 {
1048  const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
1049  BM_face_normal_flip_ex(bm, f, cd_loop_mdisp_offset, true);
1050 }
1051 
1062 bool BM_face_point_inside_test(const BMFace *f, const float co[3])
1063 {
1064  float axis_mat[3][3];
1065  float(*projverts)[2] = BLI_array_alloca(projverts, f->len);
1066 
1067  float co_2d[2];
1068  BMLoop *l_iter;
1069  int i;
1070 
1072 
1073  axis_dominant_v3_to_m3(axis_mat, f->no);
1074 
1075  mul_v2_m3v3(co_2d, axis_mat, co);
1076 
1077  for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) {
1078  mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co);
1079  }
1080 
1081  return isect_point_poly_v2(co_2d, projverts, f->len, false);
1082 }
1083 
1108  BMFace *f,
1109  BMFace **r_faces_new,
1110  int *r_faces_new_tot,
1111  BMEdge **r_edges_new,
1112  int *r_edges_new_tot,
1113  LinkNode **r_faces_double,
1114  const int quad_method,
1115  const int ngon_method,
1116  const bool use_tag,
1117  /* use for ngons only! */
1118  MemArena *pf_arena,
1119 
1120  /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
1121  struct Heap *pf_heap)
1122 {
1123  const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
1124  const bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY);
1125  BMLoop *l_first, *l_new;
1126  BMFace *f_new;
1127  int nf_i = 0;
1128  int ne_i = 0;
1129 
1131 
1132  /* ensure both are valid or NULL */
1133  BLI_assert((r_faces_new == NULL) == (r_faces_new_tot == NULL));
1134 
1135  BLI_assert(f->len > 3);
1136 
1137  {
1138  BMLoop **loops = BLI_array_alloca(loops, f->len);
1139  uint(*tris)[3] = BLI_array_alloca(tris, f->len);
1140  const int totfilltri = f->len - 2;
1141  const int last_tri = f->len - 3;
1142  int i;
1143  /* for mdisps */
1144  float f_center[3];
1145 
1146  if (f->len == 4) {
1147  /* even though we're not using BLI_polyfill, fill in 'tris' and 'loops'
1148  * so we can share code to handle face creation afterwards. */
1149  BMLoop *l_v1, *l_v2;
1150 
1151  l_first = BM_FACE_FIRST_LOOP(f);
1152 
1153  switch (quad_method) {
1155  l_v1 = l_first;
1156  l_v2 = l_first->next->next;
1157  break;
1158  }
1160  l_v1 = l_first->next;
1161  l_v2 = l_first->prev;
1162  break;
1163  }
1166  default: {
1167  BMLoop *l_v3, *l_v4;
1168  bool split_24;
1169 
1170  l_v1 = l_first->next;
1171  l_v2 = l_first->next->next;
1172  l_v3 = l_first->prev;
1173  l_v4 = l_first;
1174 
1175  if (quad_method == MOD_TRIANGULATE_QUAD_SHORTEDGE) {
1176  float d1, d2;
1177  d1 = len_squared_v3v3(l_v4->v->co, l_v2->v->co);
1178  d2 = len_squared_v3v3(l_v1->v->co, l_v3->v->co);
1179  split_24 = ((d2 - d1) > 0.0f);
1180  }
1181  else {
1182  /* first check if the quad is concave on either diagonal */
1183  const int flip_flag = is_quad_flip_v3(
1184  l_v1->v->co, l_v2->v->co, l_v3->v->co, l_v4->v->co);
1185  if (UNLIKELY(flip_flag & (1 << 0))) {
1186  split_24 = true;
1187  }
1188  else if (UNLIKELY(flip_flag & (1 << 1))) {
1189  split_24 = false;
1190  }
1191  else {
1192  split_24 = (BM_verts_calc_rotate_beauty(l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) >
1193  0.0f);
1194  }
1195  }
1196 
1197  /* named confusingly, l_v1 is in fact the second vertex */
1198  if (split_24) {
1199  l_v1 = l_v4;
1200  // l_v2 = l_v2;
1201  }
1202  else {
1203  // l_v1 = l_v1;
1204  l_v2 = l_v3;
1205  }
1206  break;
1207  }
1208  }
1209 
1210  loops[0] = l_v1;
1211  loops[1] = l_v1->next;
1212  loops[2] = l_v2;
1213  loops[3] = l_v2->next;
1214 
1215  ARRAY_SET_ITEMS(tris[0], 0, 1, 2);
1216  ARRAY_SET_ITEMS(tris[1], 0, 2, 3);
1217  }
1218  else {
1219  BMLoop *l_iter;
1220  float axis_mat[3][3];
1221  float(*projverts)[2] = BLI_array_alloca(projverts, f->len);
1222 
1223  axis_dominant_v3_to_m3_negate(axis_mat, f->no);
1224 
1225  for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) {
1226  loops[i] = l_iter;
1227  mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co);
1228  }
1229 
1230  BLI_polyfill_calc_arena(projverts, f->len, 1, tris, pf_arena);
1231 
1232  if (use_beauty) {
1233  BLI_polyfill_beautify(projverts, f->len, tris, pf_arena, pf_heap);
1234  }
1235 
1236  BLI_memarena_clear(pf_arena);
1237  }
1238 
1239  if (cd_loop_mdisp_offset != -1) {
1240  BM_face_calc_center_median(f, f_center);
1241  }
1242 
1243  /* loop over calculated triangles and create new geometry */
1244  for (i = 0; i < totfilltri; i++) {
1245  BMLoop *l_tri[3] = {loops[tris[i][0]], loops[tris[i][1]], loops[tris[i][2]]};
1246 
1247  BMVert *v_tri[3] = {l_tri[0]->v, l_tri[1]->v, l_tri[2]->v};
1248 
1249  f_new = BM_face_create_verts(bm, v_tri, 3, f, BM_CREATE_NOP, true);
1250  l_new = BM_FACE_FIRST_LOOP(f_new);
1251 
1252  BLI_assert(v_tri[0] == l_new->v);
1253 
1254  /* check for duplicate */
1255  if (l_new->radial_next != l_new) {
1256  BMLoop *l_iter = l_new->radial_next;
1257  do {
1258  if (UNLIKELY((l_iter->f->len == 3) && (l_new->prev->v == l_iter->prev->v))) {
1259  /* Check the last tri because we swap last f_new with f at the end... */
1260  BLI_linklist_prepend(r_faces_double, (i != last_tri) ? f_new : f);
1261  break;
1262  }
1263  } while ((l_iter = l_iter->radial_next) != l_new);
1264  }
1265 
1266  /* copy CD data */
1267  BM_elem_attrs_copy(bm, bm, l_tri[0], l_new);
1268  BM_elem_attrs_copy(bm, bm, l_tri[1], l_new->next);
1269  BM_elem_attrs_copy(bm, bm, l_tri[2], l_new->prev);
1270 
1271  /* add all but the last face which is swapped and removed (below) */
1272  if (i != last_tri) {
1273  if (use_tag) {
1275  }
1276  if (r_faces_new) {
1277  r_faces_new[nf_i++] = f_new;
1278  }
1279  }
1280 
1281  if (use_tag || r_edges_new) {
1282  /* new faces loops */
1283  BMLoop *l_iter;
1284 
1285  l_iter = l_first = l_new;
1286  do {
1287  BMEdge *e = l_iter->e;
1288  /* Confusing! if its not a boundary now, we know it will be later since this will be an
1289  * edge of one of the new faces which we're in the middle of creating. */
1290  bool is_new_edge = (l_iter == l_iter->radial_next);
1291 
1292  if (is_new_edge) {
1293  if (use_tag) {
1295  }
1296  if (r_edges_new) {
1297  r_edges_new[ne_i++] = e;
1298  }
1299  }
1300  /* note, never disable tag's */
1301  } while ((l_iter = l_iter->next) != l_first);
1302  }
1303 
1304  if (cd_loop_mdisp_offset != -1) {
1305  float f_new_center[3];
1306  BM_face_calc_center_median(f_new, f_new_center);
1307  BM_face_interp_multires_ex(bm, f_new, f, f_new_center, f_center, cd_loop_mdisp_offset);
1308  }
1309  }
1310 
1311  {
1312  /* we can't delete the real face, because some of the callers expect it to remain valid.
1313  * so swap data and delete the last created tri */
1314  bmesh_face_swap_data(f, f_new);
1315  BM_face_kill(bm, f_new);
1316  }
1317  }
1319 
1320  if (r_faces_new_tot) {
1321  *r_faces_new_tot = nf_i;
1322  }
1323 
1324  if (r_edges_new_tot) {
1325  *r_edges_new_tot = ne_i;
1326  }
1327 }
1328 
1337 void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
1338 {
1339  float out[2] = {-FLT_MAX, -FLT_MAX};
1340  float center[2] = {0.0f, 0.0f};
1341  float axis_mat[3][3];
1342  float(*projverts)[2] = BLI_array_alloca(projverts, f->len);
1343  const float *(*edgeverts)[2] = BLI_array_alloca(edgeverts, len);
1344  BMLoop *l;
1345  int i, i_prev, j;
1346 
1348 
1349  axis_dominant_v3_to_m3(axis_mat, f->no);
1350 
1351  for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) {
1352  mul_v2_m3v3(projverts[i], axis_mat, l->v->co);
1353  add_v2_v2(center, projverts[i]);
1354  }
1355 
1356  /* first test for completely convex face */
1357  if (is_poly_convex_v2(projverts, f->len)) {
1358  return;
1359  }
1360 
1361  mul_v2_fl(center, 1.0f / f->len);
1362 
1363  for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) {
1364  BM_elem_index_set(l, i); /* set_dirty */
1365 
1366  /* center the projection for maximum accuracy */
1367  sub_v2_v2(projverts[i], center);
1368 
1369  out[0] = max_ff(out[0], projverts[i][0]);
1370  out[1] = max_ff(out[1], projverts[i][1]);
1371  }
1373 
1374  /* ensure we are well outside the face bounds (value is arbitrary) */
1375  add_v2_fl(out, 1.0f);
1376 
1377  for (i = 0; i < len; i++) {
1378  edgeverts[i][0] = projverts[BM_elem_index_get(loops[i][0])];
1379  edgeverts[i][1] = projverts[BM_elem_index_get(loops[i][1])];
1380  }
1381 
1382  /* do convexity test */
1383  for (i = 0; i < len; i++) {
1384  float mid[2];
1385  mid_v2_v2v2(mid, edgeverts[i][0], edgeverts[i][1]);
1386 
1387  int isect = 0;
1388  int j_prev;
1389  for (j = 0, j_prev = f->len - 1; j < f->len; j_prev = j++) {
1390  const float *f_edge[2] = {projverts[j_prev], projverts[j]};
1391  if (isect_seg_seg_v2(UNPACK2(f_edge), mid, out) == ISECT_LINE_LINE_CROSS) {
1392  isect++;
1393  }
1394  }
1395 
1396  if (isect % 2 == 0) {
1397  loops[i][0] = NULL;
1398  }
1399  }
1400 
1401 #define EDGE_SHARE_VERT(e1, e2) \
1402  ((ELEM((e1)[0], (e2)[0], (e2)[1])) || (ELEM((e1)[1], (e2)[0], (e2)[1])))
1403 
1404  /* do line crossing tests */
1405  for (i = 0, i_prev = f->len - 1; i < f->len; i_prev = i++) {
1406  const float *f_edge[2] = {projverts[i_prev], projverts[i]};
1407  for (j = 0; j < len; j++) {
1408  if ((loops[j][0] != NULL) && !EDGE_SHARE_VERT(f_edge, edgeverts[j])) {
1409  if (isect_seg_seg_v2(UNPACK2(f_edge), UNPACK2(edgeverts[j])) == ISECT_LINE_LINE_CROSS) {
1410  loops[j][0] = NULL;
1411  }
1412  }
1413  }
1414  }
1415 
1416  /* self intersect tests */
1417  for (i = 0; i < len; i++) {
1418  if (loops[i][0]) {
1419  for (j = i + 1; j < len; j++) {
1420  if ((loops[j][0] != NULL) && !EDGE_SHARE_VERT(edgeverts[i], edgeverts[j])) {
1421  if (isect_seg_seg_v2(UNPACK2(edgeverts[i]), UNPACK2(edgeverts[j])) ==
1423  loops[i][0] = NULL;
1424  break;
1425  }
1426  }
1427  }
1428  }
1429  }
1430 
1431 #undef EDGE_SHARE_VERT
1432 }
1433 
1438 void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len)
1439 {
1440  int i;
1441 
1442  for (i = 0; i < len; i++) {
1443  BMLoop *l_a_dummy, *l_b_dummy;
1445  loops[i][0]->v, loops[i][1]->v, &l_a_dummy, &l_b_dummy, false)) {
1446  loops[i][0] = NULL;
1447  }
1448  }
1449 }
1450 
1458 {
1459  BMLoop *l = BM_FACE_FIRST_LOOP(f);
1460 
1461  BLI_assert(f->len == 3);
1462 
1463  r_verts[0] = l->v;
1464  l = l->next;
1465  r_verts[1] = l->v;
1466  l = l->next;
1467  r_verts[2] = l->v;
1468 }
1469 
1475 {
1476  BMLoop *l = BM_FACE_FIRST_LOOP(f);
1477 
1478  BLI_assert(f->len == 4);
1479 
1480  r_verts[0] = l->v;
1481  l = l->next;
1482  r_verts[1] = l->v;
1483  l = l->next;
1484  r_verts[2] = l->v;
1485  l = l->next;
1486  r_verts[3] = l->v;
1487 }
1488 
1496 {
1497  BMLoop *l = BM_FACE_FIRST_LOOP(f);
1498 
1499  BLI_assert(f->len == 3);
1500 
1501  r_loops[0] = l;
1502  l = l->next;
1503  r_loops[1] = l;
1504  l = l->next;
1505  r_loops[2] = l;
1506 }
1507 
1513 {
1514  BMLoop *l = BM_FACE_FIRST_LOOP(f);
1515 
1516  BLI_assert(f->len == 4);
1517 
1518  r_loops[0] = l;
1519  l = l->next;
1520  r_loops[1] = l;
1521  l = l->next;
1522  r_loops[2] = l;
1523  l = l->next;
1524  r_loops[3] = l;
1525 }
1526 
1533 void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot)
1534 {
1535  /* use this to avoid locking pthread for _every_ polygon
1536  * and calling the fill function */
1537 #define USE_TESSFACE_SPEEDUP
1538 
1539  /* this assumes all faces can be scan-filled, which isn't always true,
1540  * worst case we over alloc a little which is acceptable */
1541 #ifndef NDEBUG
1542  const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
1543 #endif
1544 
1545  BMIter iter;
1546  BMFace *efa;
1547  int i = 0;
1548 
1549  MemArena *arena = NULL;
1550 
1551  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1552  /* don't consider two-edged faces */
1553  if (UNLIKELY(efa->len < 3)) {
1554  /* do nothing */
1555  }
1556 
1557 #ifdef USE_TESSFACE_SPEEDUP
1558 
1559  /* no need to ensure the loop order, we know its ok */
1560 
1561  else if (efa->len == 3) {
1562 # if 0
1563  int j;
1564  BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, j) {
1565  looptris[i][j] = l;
1566  }
1567  i += 1;
1568 # else
1569  /* more cryptic but faster */
1570  BMLoop *l;
1571  BMLoop **l_ptr = looptris[i++];
1572  l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
1573  l_ptr[1] = l = l->next;
1574  l_ptr[2] = l->next;
1575 # endif
1576  }
1577  else if (efa->len == 4) {
1578 # if 0
1579  BMLoop *ltmp[4];
1580  int j;
1581  BLI_array_grow_items(looptris, 2);
1582  BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, j) {
1583  ltmp[j] = l;
1584  }
1585 
1586  looptris[i][0] = ltmp[0];
1587  looptris[i][1] = ltmp[1];
1588  looptris[i][2] = ltmp[2];
1589  i += 1;
1590 
1591  looptris[i][0] = ltmp[0];
1592  looptris[i][1] = ltmp[2];
1593  looptris[i][2] = ltmp[3];
1594  i += 1;
1595 # else
1596  /* more cryptic but faster */
1597  BMLoop *l;
1598  BMLoop **l_ptr_a = looptris[i++];
1599  BMLoop **l_ptr_b = looptris[i++];
1600  (l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa));
1601  (l_ptr_a[1] = l = l->next);
1602  (l_ptr_a[2] = l_ptr_b[1] = l = l->next);
1603  (l_ptr_b[2] = l->next);
1604 # endif
1605 
1607  l_ptr_a[0]->v->co, l_ptr_a[1]->v->co, l_ptr_a[2]->v->co, l_ptr_b[2]->v->co))) {
1608  /* flip out of degenerate 0-2 state. */
1609  l_ptr_a[2] = l_ptr_b[2];
1610  l_ptr_b[0] = l_ptr_a[1];
1611  }
1612  }
1613 
1614 #endif /* USE_TESSFACE_SPEEDUP */
1615 
1616  else {
1617  int j;
1618 
1619  BMLoop *l_iter;
1620  BMLoop *l_first;
1621  BMLoop **l_arr;
1622 
1623  float axis_mat[3][3];
1624  float(*projverts)[2];
1625  uint(*tris)[3];
1626 
1627  const int totfilltri = efa->len - 2;
1628 
1629  if (UNLIKELY(arena == NULL)) {
1630  arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
1631  }
1632 
1633  tris = BLI_memarena_alloc(arena, sizeof(*tris) * totfilltri);
1634  l_arr = BLI_memarena_alloc(arena, sizeof(*l_arr) * efa->len);
1635  projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * efa->len);
1636 
1637  axis_dominant_v3_to_m3_negate(axis_mat, efa->no);
1638 
1639  j = 0;
1640  l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
1641  do {
1642  l_arr[j] = l_iter;
1643  mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co);
1644  j++;
1645  } while ((l_iter = l_iter->next) != l_first);
1646 
1647  BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, arena);
1648 
1649  for (j = 0; j < totfilltri; j++) {
1650  BMLoop **l_ptr = looptris[i++];
1651  uint *tri = tris[j];
1652 
1653  l_ptr[0] = l_arr[tri[0]];
1654  l_ptr[1] = l_arr[tri[1]];
1655  l_ptr[2] = l_arr[tri[2]];
1656  }
1657 
1658  BLI_memarena_clear(arena);
1659  }
1660  }
1661 
1662  if (arena) {
1663  BLI_memarena_free(arena);
1664  arena = NULL;
1665  }
1666 
1667  *r_looptris_tot = i;
1668 
1669  BLI_assert(i <= looptris_tot);
1670 
1671 #undef USE_TESSFACE_SPEEDUP
1672 }
1673 
1677 void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot)
1678 {
1679  /* this assumes all faces can be scan-filled, which isn't always true,
1680  * worst case we over alloc a little which is acceptable */
1681 #ifndef NDEBUG
1682  const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
1683 #endif
1684 
1685  BMIter iter;
1686  BMFace *efa;
1687  int i = 0;
1688 
1689  MemArena *pf_arena = NULL;
1690 
1691  /* use_beauty */
1692  Heap *pf_heap = NULL;
1693 
1694  BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
1695  /* don't consider two-edged faces */
1696  if (UNLIKELY(efa->len < 3)) {
1697  /* do nothing */
1698  }
1699  else if (efa->len == 3) {
1700  BMLoop *l;
1701  BMLoop **l_ptr = looptris[i++];
1702  l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
1703  l_ptr[1] = l = l->next;
1704  l_ptr[2] = l->next;
1705  }
1706  else if (efa->len == 4) {
1707  BMLoop *l_v1 = BM_FACE_FIRST_LOOP(efa);
1708  BMLoop *l_v2 = l_v1->next;
1709  BMLoop *l_v3 = l_v2->next;
1710  BMLoop *l_v4 = l_v1->prev;
1711 
1712  /* #BM_verts_calc_rotate_beauty performs excessive checks we don't need!
1713  * It's meant for rotating edges, it also calculates a new normal.
1714  *
1715  * Use #BLI_polyfill_beautify_quad_rotate_calc since we have the normal.
1716  */
1717 #if 0
1718  const bool split_13 = (BM_verts_calc_rotate_beauty(
1719  l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) < 0.0f);
1720 #else
1721  float axis_mat[3][3], v_quad[4][2];
1722  axis_dominant_v3_to_m3(axis_mat, efa->no);
1723  mul_v2_m3v3(v_quad[0], axis_mat, l_v1->v->co);
1724  mul_v2_m3v3(v_quad[1], axis_mat, l_v2->v->co);
1725  mul_v2_m3v3(v_quad[2], axis_mat, l_v3->v->co);
1726  mul_v2_m3v3(v_quad[3], axis_mat, l_v4->v->co);
1727 
1728  const bool split_13 = BLI_polyfill_beautify_quad_rotate_calc(
1729  v_quad[0], v_quad[1], v_quad[2], v_quad[3]) < 0.0f;
1730 #endif
1731 
1732  BMLoop **l_ptr_a = looptris[i++];
1733  BMLoop **l_ptr_b = looptris[i++];
1734  if (split_13) {
1735  l_ptr_a[0] = l_v1;
1736  l_ptr_a[1] = l_v2;
1737  l_ptr_a[2] = l_v3;
1738 
1739  l_ptr_b[0] = l_v1;
1740  l_ptr_b[1] = l_v3;
1741  l_ptr_b[2] = l_v4;
1742  }
1743  else {
1744  l_ptr_a[0] = l_v1;
1745  l_ptr_a[1] = l_v2;
1746  l_ptr_a[2] = l_v4;
1747 
1748  l_ptr_b[0] = l_v2;
1749  l_ptr_b[1] = l_v3;
1750  l_ptr_b[2] = l_v4;
1751  }
1752  }
1753  else {
1754  int j;
1755 
1756  BMLoop *l_iter;
1757  BMLoop *l_first;
1758  BMLoop **l_arr;
1759 
1760  float axis_mat[3][3];
1761  float(*projverts)[2];
1762  unsigned int(*tris)[3];
1763 
1764  const int totfilltri = efa->len - 2;
1765 
1766  if (UNLIKELY(pf_arena == NULL)) {
1767  pf_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
1769  }
1770 
1771  tris = BLI_memarena_alloc(pf_arena, sizeof(*tris) * totfilltri);
1772  l_arr = BLI_memarena_alloc(pf_arena, sizeof(*l_arr) * efa->len);
1773  projverts = BLI_memarena_alloc(pf_arena, sizeof(*projverts) * efa->len);
1774 
1775  axis_dominant_v3_to_m3_negate(axis_mat, efa->no);
1776 
1777  j = 0;
1778  l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
1779  do {
1780  l_arr[j] = l_iter;
1781  mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co);
1782  j++;
1783  } while ((l_iter = l_iter->next) != l_first);
1784 
1785  BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, pf_arena);
1786 
1787  BLI_polyfill_beautify(projverts, efa->len, tris, pf_arena, pf_heap);
1788 
1789  for (j = 0; j < totfilltri; j++) {
1790  BMLoop **l_ptr = looptris[i++];
1791  unsigned int *tri = tris[j];
1792 
1793  l_ptr[0] = l_arr[tri[0]];
1794  l_ptr[1] = l_arr[tri[1]];
1795  l_ptr[2] = l_arr[tri[2]];
1796  }
1797 
1798  BLI_memarena_clear(pf_arena);
1799  }
1800  }
1801 
1802  if (pf_arena) {
1803  BLI_memarena_free(pf_arena);
1804 
1805  BLI_heap_free(pf_heap, NULL);
1806  }
1807 
1808  *r_looptris_tot = i;
1809 
1810  BLI_assert(i <= looptris_tot);
1811 }
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const struct CustomData *data, int type)
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:36
#define BLI_array_grow_items(arr, num)
Definition: BLI_array.h:99
#define BLI_assert(a)
Definition: BLI_assert.h:58
A min-heap / priority queue ADT.
void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1)
Definition: BLI_heap.c:221
Heap * BLI_heap_new_ex(unsigned int tot_reserve) ATTR_WARN_UNUSED_RESULT
Definition: BLI_heap.c:201
MINLINE float saacos(float fac)
MINLINE float max_ff(float a, float b)
int isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
Definition: math_geom.c:1151
float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:68
MINLINE int poly_to_tri_count(const int poly_count, const int corner_count)
int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:6184
bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr, const bool use_holes)
bool is_quad_flip_v3_first_third_fast(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:6206
void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3])
Definition: math_geom.c:3772
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
Normal to x,y matrix.
Definition: math_geom.c:3752
float area_squared_tri_v3(const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:123
void closest_to_line_segment_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:375
bool is_poly_convex_v2(const float verts[][2], unsigned int nr)
Definition: math_geom.c:6139
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:51
#define ISECT_LINE_LINE_CROSS
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
Definition: math_matrix.c:921
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:901
void axis_sort_v3(const float axis_values[3], int r_axis_order[3])
Definition: math_vector.c:1090
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
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:1020
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void sub_v2_v2(float r[2], const float a[2])
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 add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
Definition: math_vector.c:674
MINLINE void add_v2_v2(float r[2], const float a[2])
void project_plane_normalized_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
Definition: math_vector.c:757
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 add_v2_fl(float r[2], float f)
MINLINE void negate_v3(float r[3])
void mid_v2_v2v2(float r[2], const float a[2], const float b[2])
Definition: math_vector.c:277
MINLINE float normalize_v3_v3(float r[3], const float a[3])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:270
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_vector.c:289
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:109
#define BLI_MEMARENA_STD_BUFSIZE
Definition: BLI_memarena.h:36
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:131
void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:185
struct MemArena * BLI_memarena_new(const size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:79
void BLI_polyfill_calc_arena(const float(*coords)[2], const unsigned int coords_tot, const int coords_sign, unsigned int(*r_tris)[3], struct MemArena *arena)
Definition: polyfill_2d.c:847
void BLI_polyfill_calc(const float(*coords)[2], const unsigned int coords_tot, const int coords_sign, unsigned int(*r_tris)[3])
Definition: polyfill_2d.c:905
#define BLI_POLYFILL_ALLOC_NGON_RESERVE
#define BLI_polyfill_beautify_quad_rotate_calc(v1, v2, v3, v4)
void BLI_polyfill_beautify(const float(*coords)[2], const unsigned int coords_tot, unsigned int(*tris)[3], struct MemArena *arena, struct Heap *eheap)
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNPACK2(a)
#define INIT_MINMAX(min, max)
#define ARRAY_SET_ITEMS(...)
#define UNLIKELY(x)
#define ELEM(...)
These structs are the foundation for all linked lists in the library system.
@ MOD_TRIANGULATE_QUAD_SHORTEDGE
@ MOD_TRIANGULATE_QUAD_FIXED
@ MOD_TRIANGULATE_QUAD_BEAUTY
@ MOD_TRIANGULATE_QUAD_ALTERNATE
@ MOD_TRIANGULATE_NGON_BEAUTY
NSNotificationCenter * center
_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 order
Read Guarded memory(de)allocation.
float BM_verts_calc_rotate_beauty(const BMVert *v1, const BMVert *v2, const BMVert *v3, const BMVert *v4, const short flag, const short method)
@ BM_LOOP
Definition: bmesh_class.h:385
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:553
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:530
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src, void *ele_dst)
void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b)
Definition: bmesh_core.c:2952
BMFace * BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len, const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
Definition: bmesh_core.c:500
void BM_face_kill(BMesh *bm, BMFace *f)
Definition: bmesh_core.c:881
void bmesh_kernel_loop_reverse(BMesh *bm, BMFace *f, const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip)
Loop Reverse.
Definition: bmesh_core.c:1037
@ BM_CREATE_NOP
Definition: bmesh_core.h:27
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:125
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:28
void BM_face_interp_multires_ex(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset)
Definition: bmesh_interp.c:591
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_EDGE
@ BM_FACES_OF_MESH
@ BM_LOOPS_OF_FACE
#define BM_ITER_ELEM_INDEX(ele, iter, data, itype, indexvar)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3])
void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3])
float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset)
void poly_rotate_plane(const float normal[3], float(*verts)[3], const uint nverts)
POLY ROTATE PLANE.
void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len)
void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3])
void BM_vert_normal_update(BMVert *v)
void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3])
void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot)
void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4])
void BM_face_triangulate(BMesh *bm, BMFace *f, BMFace **r_faces_new, int *r_faces_new_tot, BMEdge **r_edges_new, int *r_edges_new_tot, LinkNode **r_faces_double, const int quad_method, const int ngon_method, const bool use_tag, MemArena *pf_arena, struct Heap *pf_heap)
BMESH TRIANGULATE FACE.
static int bm_vert_tri_find_unique_edge(BMVert *verts[3])
float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3])
void BM_face_calc_point_in_face(const BMFace *f, float r_co[3])
void BM_verts_calc_normal_from_cloud(BMVert **varr, int varr_len, float r_normal[3])
bool BM_face_point_inside_test(const BMFace *f, const float co[3])
bool BM_vert_calc_normal(const BMVert *v, float r_no[3])
void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3])
static float bm_face_calc_poly_normal_vertex_cos(const BMFace *f, float r_no[3], float const (*vertexCos)[3])
COMPUTE POLY NORMAL (BMFace)
Definition: bmesh_polygon.c:79
void BM_face_normal_flip_ex(BMesh *bm, BMFace *f, const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip)
Face Flip Normal.
void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3])
void BM_face_normal_update(BMFace *f)
void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3])
bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3])
void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4])
static void bm_face_calc_poly_center_median_vertex_cos(const BMFace *f, float r_cent[3], float const (*vertexCos)[3])
COMPUTE POLY CENTER (BMFace)
void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot)
BM_mesh_calc_tessellation get the looptris and its number from a certain bmesh.
void BM_face_normal_flip(BMesh *bm, BMFace *f)
void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3])
void BM_verts_calc_normal_from_cloud_ex(BMVert **varr, int varr_len, float r_normal[3], float r_center[3], int *r_index_tangent)
void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3])
float BM_face_calc_area(const BMFace *f)
#define EDGE_SHARE_VERT(e1, e2)
float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3])
void BM_face_calc_center_median_vcos(const BMesh *bm, const BMFace *f, float r_cent[3], float const (*vertexCos)[3])
float BM_face_calc_normal(const BMFace *f, float r_no[3])
BMESH UPDATE FACE NORMAL.
float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3])
void BM_face_calc_center_bounds_vcos(const BMesh *bm, const BMFace *f, float r_cent[3], float const (*vertexCos)[3])
static void bm_loop_normal_accum(const BMLoop *l, float no[3])
void BM_vert_tri_calc_tangent_edge_pair(BMVert *verts[3], float r_tangent[3])
void BM_face_calc_tessellation(const BMFace *f, const bool use_fixed_quad, BMLoop **r_loops, uint(*r_index)[3])
void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3])
static float bm_face_calc_poly_normal(const BMFace *f, float n[3])
COMPUTE POLY NORMAL (BMFace)
Definition: bmesh_polygon.c:51
void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3])
void BM_vert_normal_update_all(BMVert *v)
float BM_face_calc_perimeter(const BMFace *f)
float BM_face_calc_normal_vcos(const BMesh *bm, const BMFace *f, float r_no[3], float const (*vertexCos)[3])
void BM_edge_normals_update(BMEdge *e)
bool BM_face_is_normal_valid(const BMFace *f)
Definition: bmesh_query.c:2533
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:366
float BM_edge_calc_length(const BMEdge *e)
Definition: bmesh_query.c:713
BMLoop * BM_face_find_longest_loop(BMFace *f)
Definition: bmesh_query.c:1950
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
BLI_INLINE BMEdge * bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
static float verts[][3]
IconTextureDrawCall normal
#define fabsf(x)
static void area(int d1, int d2, int e1, int e2, float weights[2])
#define min(a, b)
Definition: sort.c:51
int len
Definition: bmesh_class.h:279
float no[3]
Definition: bmesh_class.h:280
struct BMVert * v
Definition: bmesh_class.h:165
struct BMEdge * e
Definition: bmesh_class.h:176
struct BMLoop * radial_next
Definition: bmesh_class.h:216
struct BMLoop * prev
Definition: bmesh_class.h:245
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245
float co[3]
Definition: bmesh_class.h:99
struct BMEdge * e
Definition: bmesh_class.h:109
float no[3]
Definition: bmesh_class.h:100
char elem_index_dirty
Definition: bmesh_class.h:305
int totloop
Definition: bmesh_class.h:297
CustomData ldata
Definition: bmesh_class.h:337
int totface
Definition: bmesh_class.h:297
Definition: BLI_heap.c:57
float max
__forceinline avxf cross(const avxf &a, const avxf &b)
Definition: util_avxf.h:119
uint len