Blender  V2.93
bmo_subdivide_edgering.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 
34 #include "MEM_guardedalloc.h"
35 
36 #include "BLI_alloca.h"
37 #include "BLI_listbase.h"
38 #include "BLI_math.h"
39 #include "BLI_utildefines.h"
40 #include "BLI_utildefines_stack.h"
41 
42 #include "BKE_curve.h"
43 
44 #include "bmesh.h"
45 
46 #include "intern/bmesh_operators_private.h" /* own include */
47 
48 #define VERT_SHARED (1 << 0)
49 
50 #define EDGE_RING (1 << 0)
51 #define EDGE_RIM (1 << 1)
52 #define EDGE_IN_STACK (1 << 2)
53 
54 #define FACE_OUT (1 << 0)
55 #define FACE_SHARED (1 << 1)
56 #define FACE_IN_STACK (1 << 2)
57 
58 /* -------------------------------------------------------------------- */
59 /* Specialized Utility Funcs */
60 
61 #ifndef NDEBUG
63 {
64  int count = 0;
65  BMIter iter;
66  BMVert *v;
67  BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
69  count++;
70  }
71  }
72  return count;
73 }
74 #endif
75 
76 static float bezier_handle_calc_length_v3(const float co_a[3],
77  const float no_a[3],
78  const float co_b[3],
79  const float no_b[3])
80 {
81  const float dot = dot_v3v3(no_a, no_b);
82  /* gives closest approx at a circle with 2 parallel handles */
83  float fac = 1.333333f;
84  float len;
85  if (dot < 0.0f) {
86  /* scale down to 0.666 if we point directly at each other rough but ok */
87  /* TODO, current blend from dot may not be optimal but its also a detail */
88  const float t = 1.0f + dot;
89  fac = (fac * t) + (0.75f * (1.0f - t));
90  }
91 
92 #if 0
93  len = len_v3v3(co_a, co_b);
94 #else
95  /* 2d length projected on plane of normals */
96  {
97  float co_a_ofs[3];
98  cross_v3_v3v3(co_a_ofs, no_a, no_b);
99  if (len_squared_v3(co_a_ofs) > FLT_EPSILON) {
100  add_v3_v3(co_a_ofs, co_a);
101  closest_to_line_v3(co_a_ofs, co_b, co_a, co_a_ofs);
102  }
103  else {
104  copy_v3_v3(co_a_ofs, co_a);
105  }
106  len = len_v3v3(co_a_ofs, co_b);
107  }
108 #endif
109 
110  return (len * 0.5f) * fac;
111 }
112 
113 static void bm_edgeloop_vert_tag(struct BMEdgeLoopStore *el_store, const bool tag)
114 {
116  do {
117  BM_elem_flag_set((BMVert *)node->data, BM_ELEM_TAG, tag);
118  } while ((node = node->next));
119 }
120 
122  struct BMEdgeLoopStore *el_store,
123  const short oflag,
124  const bool tag)
125 {
127  do {
128  BMO_vert_flag_set(bm, (BMVert *)node->data, oflag, tag);
129  } while ((node = node->next));
130 }
131 
132 static bool bmo_face_is_vert_tag_all(BMesh *bm, BMFace *f, short oflag)
133 {
134  BMLoop *l_iter, *l_first;
135  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
136  do {
137  if (!BMO_vert_flag_test(bm, l_iter->v, oflag)) {
138  return false;
139  }
140  } while ((l_iter = l_iter->next) != l_first);
141  return true;
142 }
143 
145 {
146  BMIter eiter;
147  BMEdge *e;
148 
149  BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
150  if (BMO_edge_flag_test(bm, e, EDGE_RING)) {
151  BMVert *v_other = BM_edge_other_vert(e, v);
152  if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
153  return true;
154  }
155  }
156  }
157  return false;
158 }
159 
160 /* for now we need full overlap,
161  * supporting partial overlap could be done but gets complicated
162  * when trimming endpoints is not enough to ensure consistency.
163  */
165  struct BMEdgeLoopStore *el_store_a,
166  struct BMEdgeLoopStore *el_store_b)
167 {
168  bool has_overlap = true;
169  LinkData *node;
170 
171  ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
172  ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
173 
174  bm_edgeloop_vert_tag(el_store_a, false);
175  bm_edgeloop_vert_tag(el_store_b, true);
176 
177  for (node = lb_a->first; node; node = node->next) {
178  if (bm_vert_is_tag_edge_connect(bm, node->data) == false) {
179  has_overlap = false;
180  goto finally;
181  }
182  }
183 
184  bm_edgeloop_vert_tag(el_store_a, true);
185  bm_edgeloop_vert_tag(el_store_b, false);
186 
187  for (node = lb_b->first; node; node = node->next) {
188  if (bm_vert_is_tag_edge_connect(bm, node->data) == false) {
189  has_overlap = false;
190  goto finally;
191  }
192  }
193 
194 finally:
195  bm_edgeloop_vert_tag(el_store_a, false);
196  bm_edgeloop_vert_tag(el_store_b, false);
197  return has_overlap;
198 }
199 
200 /* -------------------------------------------------------------------- */
201 /* Edge Loop Pairs */
202 /* key (ordered loop pointers) */
204 {
219  GSet *eloop_pair_gs = BLI_gset_pair_new(__func__);
220  GHash *vert_eloop_gh = BLI_ghash_ptr_new(__func__);
221 
222  struct BMEdgeLoopStore *el_store;
223 
224  /* create vert -> eloop map */
225  for (el_store = eloops_rim->first; el_store; el_store = BM_EDGELOOP_NEXT(el_store)) {
227  do {
228  BLI_ghash_insert(vert_eloop_gh, node->data, el_store);
229  } while ((node = node->next));
230  }
231 
232  /* collect eloop pairs */
233  for (el_store = eloops_rim->first; el_store; el_store = BM_EDGELOOP_NEXT(el_store)) {
234  BMIter eiter;
235  BMEdge *e;
236 
237  BMVert *v = ((LinkData *)BM_edgeloop_verts_get(el_store)->first)->data;
238 
239  BM_ITER_ELEM (e, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) {
240  if (BMO_edge_flag_test(bm, e, EDGE_RING)) {
241  struct BMEdgeLoopStore *el_store_other;
242  BMVert *v_other = BM_edge_other_vert(e, v);
243  GHashPair pair_test;
244 
245  el_store_other = BLI_ghash_lookup(vert_eloop_gh, v_other);
246 
247  /* in rare cases we cant find a match */
248  if (el_store_other) {
249  pair_test.first = el_store;
250  pair_test.second = el_store_other;
251 
252  if (pair_test.first > pair_test.second) {
253  SWAP(const void *, pair_test.first, pair_test.second);
254  }
255 
256  void **pair_key_p;
257  if (!BLI_gset_ensure_p_ex(eloop_pair_gs, &pair_test, &pair_key_p)) {
258  *pair_key_p = BLI_ghashutil_pairalloc(pair_test.first, pair_test.second);
259  }
260  }
261  }
262  }
263  }
264 
265  BLI_ghash_free(vert_eloop_gh, NULL, NULL);
266 
267  if (BLI_gset_len(eloop_pair_gs) == 0) {
268  BLI_gset_free(eloop_pair_gs, NULL);
269  eloop_pair_gs = NULL;
270  }
271 
272  return eloop_pair_gs;
273 }
274 
275 /* -------------------------------------------------------------------- */
276 /* Subdivide an edge 'n' times and return an open edgeloop */
277 
279  BMesh *bm, ListBase *eloops, BMEdge *e, BMVert *v_a, const int cuts)
280 {
281  struct BMEdgeLoopStore *eloop;
282  BMVert **v_arr = BLI_array_alloca(v_arr, cuts + 2);
283  BMVert *v_b;
285 
286  v_b = BM_edge_other_vert(e, v_a);
287 
288  BM_edge_split_n(bm, e, cuts, &v_arr[1]);
289  if (v_a == e->v1) {
290  v_arr[0] = v_a;
291  v_arr[cuts + 1] = v_b;
292  }
293  else {
294  v_arr[0] = v_b;
295  v_arr[cuts + 1] = v_a;
296  }
297 
298  eloop = BM_edgeloop_from_verts(v_arr, cuts + 2, false);
299 
300  if (v_a == e->v1) {
301  BM_edgeloop_flip(bm, eloop);
302  }
303 
304  BLI_addtail(eloops, eloop);
305 }
306 
307 /* -------------------------------------------------------------------- */
308 /* LoopPair Cache (struct and util funcs) */
309 
320 static void bm_vert_calc_surface_tangent(BMesh *bm, BMVert *v, float r_no[3])
321 {
322  BMIter eiter;
323  BMEdge *e;
324 
325  /* get outer normal, fallback to inner (if this vertex is on a boundary) */
326  bool found_outer = false, found_inner = false, found_outer_tag = false;
327 
328  float no_outer[3] = {0.0f}, no_inner[3] = {0.0f};
329 
330  /* first find rim edges, typically we will only add 2 normals */
331  BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
332  if (UNLIKELY(BM_edge_is_wire(e))) {
333  /* pass - this may confuse things */
334  }
335  else if (BMO_edge_flag_test(bm, e, EDGE_RIM)) {
336  BMIter liter;
337  BMLoop *l;
338  BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
339  /* use unmarked (surrounding) faces to create surface tangent */
340  float no[3];
341  // BM_face_normal_update(l->f);
343  if (BMO_face_flag_test(bm, l->f, FACE_SHARED)) {
344  add_v3_v3(no_inner, no);
345  found_inner = true;
346  }
347  else {
348  add_v3_v3(no_outer, no);
349  found_outer = true;
350 
351  /* other side is used too, blend midway */
352  if (BMO_face_flag_test(bm, l->f, FACE_OUT)) {
353  found_outer_tag = true;
354  }
355  }
356  }
357  }
358  }
359 
360  /* detect if this vertex is in-between 2 loops (when blending multiple),
361  * if so - take both inner and outer into account */
362 
363  if (found_inner && found_outer_tag) {
364  /* blend between the 2 */
365  negate_v3(no_outer);
366  normalize_v3(no_outer);
367  normalize_v3(no_inner);
368  add_v3_v3v3(r_no, no_outer, no_inner);
369  normalize_v3(r_no);
370  }
371  else if (found_outer) {
372  negate_v3(no_outer);
373  normalize_v3_v3(r_no, no_outer);
374  }
375  else {
376  /* we always have inner geometry */
377  BLI_assert(found_inner == true);
378  normalize_v3_v3(r_no, no_inner);
379  }
380 }
381 
386 static void bm_faces_share_tag_flush(BMesh *bm, BMEdge **e_arr, const uint e_arr_len)
387 {
388  uint i;
389 
390  for (i = 0; i < e_arr_len; i++) {
391  BMEdge *e = e_arr[i];
392  BMLoop *l_iter, *l_first;
393 
394  l_iter = l_first = e->l;
395  do {
396  if (!BMO_face_flag_test(bm, l_iter->f, FACE_SHARED)) {
397  if (bmo_face_is_vert_tag_all(bm, l_iter->f, VERT_SHARED)) {
399  }
400  }
401  } while ((l_iter = l_iter->radial_next) != l_first);
402  }
403 }
404 
408 static void bm_faces_share_tag_clear(BMesh *bm, BMEdge **e_arr_iter, const uint e_arr_len_iter)
409 {
410  uint i;
411 
412  for (i = 0; i < e_arr_len_iter; i++) {
413  BMEdge *e = e_arr_iter[i];
414  BMLoop *l_iter, *l_first;
415 
416  l_iter = l_first = e->l;
417  do {
419  } while ((l_iter = l_iter->radial_next) != l_first);
420  }
421 }
422 
430 typedef struct LoopPairStore {
431  /* handle array for splines */
432  float (*nors_a)[3];
433  float (*nors_b)[3];
434 
435  /* since we don't have reliable index values into the array,
436  * store a map (BMVert -> index) */
440 
442  struct BMEdgeLoopStore *el_store_a,
443  struct BMEdgeLoopStore *el_store_b,
444  const int interp_mode)
445 {
446  LoopPairStore *lpair = MEM_mallocN(sizeof(*lpair), __func__);
447 
448  if (interp_mode == SUBD_RING_INTERP_SURF) {
449  const uint len_a = BM_edgeloop_length_get(el_store_a);
450  const uint len_b = BM_edgeloop_length_get(el_store_b);
451  const uint e_arr_a_len = len_a - (BM_edgeloop_is_closed(el_store_a) ? 0 : 1);
452  const uint e_arr_b_len = len_b - (BM_edgeloop_is_closed(el_store_b) ? 0 : 1);
453  BMEdge **e_arr_a = BLI_array_alloca(e_arr_a, e_arr_a_len);
454  BMEdge **e_arr_b = BLI_array_alloca(e_arr_b, e_arr_b_len);
455  uint i;
456 
457  struct BMEdgeLoopStore *el_store_pair[2] = {el_store_a, el_store_b};
458  uint side_index;
459  float(*nors_pair[2])[3];
460  GHash *nors_gh_pair[2];
461 
462  BM_edgeloop_edges_get(el_store_a, e_arr_a);
463  BM_edgeloop_edges_get(el_store_b, e_arr_b);
464 
465  lpair->nors_a = MEM_mallocN(sizeof(*lpair->nors_a) * len_a, __func__);
466  lpair->nors_b = MEM_mallocN(sizeof(*lpair->nors_b) * len_b, __func__);
467 
468  nors_pair[0] = lpair->nors_a;
469  nors_pair[1] = lpair->nors_b;
470 
471  lpair->nors_gh_a = BLI_ghash_ptr_new(__func__);
472  lpair->nors_gh_b = BLI_ghash_ptr_new(__func__);
473 
474  nors_gh_pair[0] = lpair->nors_gh_a;
475  nors_gh_pair[1] = lpair->nors_gh_b;
476 
477  /* now calculate nor */
478 
479  /* all other verts must _not_ be tagged */
480  bmo_edgeloop_vert_tag(bm, el_store_a, VERT_SHARED, true);
481  bmo_edgeloop_vert_tag(bm, el_store_b, VERT_SHARED, true);
482 
483  /* tag all faces that are in-between both loops */
484  bm_faces_share_tag_flush(bm, e_arr_a, e_arr_a_len);
485  bm_faces_share_tag_flush(bm, e_arr_b, e_arr_b_len);
486 
487  /* now we have all data we need, calculate vertex spline nor! */
488  for (side_index = 0; side_index < 2; side_index++) {
489  /* iter vars */
490  struct BMEdgeLoopStore *el_store = el_store_pair[side_index];
491  ListBase *lb = BM_edgeloop_verts_get(el_store);
492  GHash *nors_gh_iter = nors_gh_pair[side_index];
493  float(*nor)[3] = nors_pair[side_index];
494 
495  LinkData *v_iter;
496 
497  for (v_iter = lb->first, i = 0; v_iter; v_iter = v_iter->next, i++) {
498  BMVert *v = v_iter->data;
500  BLI_ghash_insert(nors_gh_iter, v, POINTER_FROM_UINT(i));
501  }
502  }
503 
504  /* cleanup verts share */
505  bmo_edgeloop_vert_tag(bm, el_store_a, VERT_SHARED, false);
506  bmo_edgeloop_vert_tag(bm, el_store_b, VERT_SHARED, false);
507 
508  /* cleanup faces share */
509  bm_faces_share_tag_clear(bm, e_arr_a, e_arr_a_len);
510  bm_faces_share_tag_clear(bm, e_arr_b, e_arr_b_len);
511  }
512  return lpair;
513 }
514 
515 static void bm_edgering_pair_store_free(LoopPairStore *lpair, const int interp_mode)
516 {
517  if (interp_mode == SUBD_RING_INTERP_SURF) {
518  MEM_freeN(lpair->nors_a);
519  MEM_freeN(lpair->nors_b);
520 
521  BLI_ghash_free(lpair->nors_gh_a, NULL, NULL);
522  BLI_ghash_free(lpair->nors_gh_b, NULL, NULL);
523  }
524  MEM_freeN(lpair);
525 }
526 
527 /* -------------------------------------------------------------------- */
528 /* Interpolation Function */
529 
531  LoopPairStore *lpair,
532  struct BMEdgeLoopStore *el_store_a,
533  struct BMEdgeLoopStore *el_store_b,
534  ListBase *eloops_ring,
535  const int interp_mode,
536  const int cuts,
537  const float smooth,
538  const float *falloff_cache)
539 {
540  const int resolu = cuts + 2;
541  const int dims = 3;
542  bool is_a_no_valid, is_b_no_valid;
543  int i;
544 
545  float el_store_a_co[3], el_store_b_co[3];
546  float el_store_a_no[3], el_store_b_no[3];
547 
548  struct BMEdgeLoopStore *el_store_ring;
549 
550  float(*coord_array_main)[3] = NULL;
551 
552  BM_edgeloop_calc_center(bm, el_store_a);
553  BM_edgeloop_calc_center(bm, el_store_b);
554 
555  is_a_no_valid = BM_edgeloop_calc_normal(bm, el_store_a);
556  is_b_no_valid = BM_edgeloop_calc_normal(bm, el_store_b);
557 
558  copy_v3_v3(el_store_a_co, BM_edgeloop_center_get(el_store_a));
559  copy_v3_v3(el_store_b_co, BM_edgeloop_center_get(el_store_b));
560 
561  /* correct normals need to be flipped to face each other
562  * we know both normals point in the same direction so one will need flipping */
563  {
564  float el_dir[3];
565  float no[3];
566  sub_v3_v3v3(el_dir, el_store_a_co, el_store_b_co);
567  normalize_v3_v3(no, el_dir);
568 
569  if (is_a_no_valid == false) {
570  is_a_no_valid = BM_edgeloop_calc_normal_aligned(bm, el_store_a, no);
571  }
572  if (is_b_no_valid == false) {
573  is_b_no_valid = BM_edgeloop_calc_normal_aligned(bm, el_store_b, no);
574  }
575  (void)is_a_no_valid, (void)is_b_no_valid;
576 
577  copy_v3_v3(el_store_a_no, BM_edgeloop_normal_get(el_store_a));
578  copy_v3_v3(el_store_b_no, BM_edgeloop_normal_get(el_store_b));
579 
580  if (dot_v3v3(el_store_a_no, el_dir) > 0.0f) {
581  negate_v3(el_store_a_no);
582  }
583  if (dot_v3v3(el_store_b_no, el_dir) < 0.0f) {
584  negate_v3(el_store_b_no);
585  }
586  }
587  /* now normals are correct, don't touch! */
588 
589  /* calculate the center spline, multiple */
590  if ((interp_mode == SUBD_RING_INTERP_PATH) || falloff_cache) {
591  float handle_a[3], handle_b[3];
592  float handle_len;
593 
594  handle_len = bezier_handle_calc_length_v3(
595  el_store_a_co, el_store_a_no, el_store_b_co, el_store_b_no) *
596  smooth;
597 
598  mul_v3_v3fl(handle_a, el_store_a_no, handle_len);
599  mul_v3_v3fl(handle_b, el_store_b_no, handle_len);
600 
601  add_v3_v3(handle_a, el_store_a_co);
602  add_v3_v3(handle_b, el_store_b_co);
603 
604  coord_array_main = MEM_mallocN(dims * (resolu) * sizeof(float), __func__);
605 
606  for (i = 0; i < dims; i++) {
607  BKE_curve_forward_diff_bezier(el_store_a_co[i],
608  handle_a[i],
609  handle_b[i],
610  el_store_b_co[i],
611  ((float *)coord_array_main) + i,
612  resolu - 1,
613  sizeof(float) * dims);
614  }
615  }
616 
617  switch (interp_mode) {
619  if (falloff_cache) {
620  float(*coord_array)[3] = MEM_mallocN(dims * (resolu) * sizeof(float), __func__);
621  for (i = 0; i < resolu; i++) {
623  coord_array[i], el_store_a_co, el_store_b_co, (float)i / (float)(resolu - 1));
624  }
625 
626  for (el_store_ring = eloops_ring->first; el_store_ring;
627  el_store_ring = BM_EDGELOOP_NEXT(el_store_ring)) {
628  ListBase *lb_ring = BM_edgeloop_verts_get(el_store_ring);
629  LinkData *v_iter;
630 
631  for (v_iter = lb_ring->first, i = 0; v_iter; v_iter = v_iter->next, i++) {
632  if (i > 0 && i < resolu - 1) {
633  /* shape */
634  if (falloff_cache) {
635  interp_v3_v3v3(((BMVert *)v_iter->data)->co,
636  coord_array[i],
637  ((BMVert *)v_iter->data)->co,
638  falloff_cache[i]);
639  }
640  }
641  }
642  }
643 
644  MEM_freeN(coord_array);
645  }
646 
647  break;
648  }
649  case SUBD_RING_INTERP_PATH: {
650  float(*direction_array)[3] = MEM_mallocN(dims * (resolu) * sizeof(float), __func__);
651  float(*quat_array)[4] = MEM_mallocN(resolu * sizeof(*quat_array), __func__);
652  float(*tri_array)[3][3] = MEM_mallocN(resolu * sizeof(*tri_array), __func__);
653  float(*tri_sta)[3], (*tri_end)[3], (*tri_tmp)[3];
654 
655  /* very similar to make_bevel_list_3D_minimum_twist */
656 
657  /* calculate normals */
658  copy_v3_v3(direction_array[0], el_store_a_no);
659  negate_v3_v3(direction_array[resolu - 1], el_store_b_no);
660  for (i = 1; i < resolu - 1; i++) {
661  bisect_v3_v3v3v3(direction_array[i],
662  coord_array_main[i - 1],
663  coord_array_main[i],
664  coord_array_main[i + 1]);
665  }
666 
667  vec_to_quat(quat_array[0], direction_array[0], 5, 1);
668  normalize_qt(quat_array[0]);
669 
670  for (i = 1; i < resolu; i++) {
671  float angle = angle_normalized_v3v3(direction_array[i - 1], direction_array[i]);
672  // BLI_assert(angle < DEG2RADF(90.0f));
673  if (angle > 0.0f) { /* otherwise we can keep as is */
674  float cross_tmp[3];
675  float q[4];
676  cross_v3_v3v3(cross_tmp, direction_array[i - 1], direction_array[i]);
677  axis_angle_to_quat(q, cross_tmp, angle);
678  mul_qt_qtqt(quat_array[i], q, quat_array[i - 1]);
679  normalize_qt(quat_array[i]);
680  }
681  else {
682  copy_qt_qt(quat_array[i], quat_array[i - 1]);
683  }
684  }
685 
686  /* init base tri */
687  for (i = 0; i < resolu; i++) {
688  int j;
689 
690  const float shape_size = falloff_cache ? falloff_cache[i] : 1.0f;
691 
692  tri_tmp = tri_array[i];
693 
694  /* create the triangle and transform */
695  for (j = 0; j < 3; j++) {
696  zero_v3(tri_tmp[j]);
697  if (j == 1) {
698  tri_tmp[j][0] = shape_size;
699  }
700  else if (j == 2) {
701  tri_tmp[j][1] = shape_size;
702  }
703  mul_qt_v3(quat_array[i], tri_tmp[j]);
704  add_v3_v3(tri_tmp[j], coord_array_main[i]);
705  }
706  }
707 
708  tri_sta = tri_array[0];
709  tri_end = tri_array[resolu - 1];
710 
711  for (el_store_ring = eloops_ring->first; el_store_ring;
712  el_store_ring = BM_EDGELOOP_NEXT(el_store_ring)) {
713  ListBase *lb_ring = BM_edgeloop_verts_get(el_store_ring);
714  LinkData *v_iter;
715 
716  BMVert *v_a = ((LinkData *)lb_ring->first)->data;
717  BMVert *v_b = ((LinkData *)lb_ring->last)->data;
718 
719  /* skip first and last */
720  for (v_iter = ((LinkData *)lb_ring->first)->next, i = 1; v_iter != lb_ring->last;
721  v_iter = v_iter->next, i++) {
722  float co_a[3], co_b[3];
723 
724  tri_tmp = tri_array[i];
725 
726  transform_point_by_tri_v3(co_a, v_a->co, UNPACK3(tri_tmp), UNPACK3(tri_sta));
727  transform_point_by_tri_v3(co_b, v_b->co, UNPACK3(tri_tmp), UNPACK3(tri_end));
728 
729  interp_v3_v3v3(((BMVert *)v_iter->data)->co, co_a, co_b, (float)i / (float)(resolu - 1));
730  }
731  }
732 
733  MEM_freeN(direction_array);
734  MEM_freeN(quat_array);
735  MEM_freeN(tri_array);
736  break;
737  }
738  case SUBD_RING_INTERP_SURF: {
739  float(*coord_array)[3] = MEM_mallocN(dims * (resolu) * sizeof(float), __func__);
740 
741  /* calculate a bezier handle per edge ring */
742  for (el_store_ring = eloops_ring->first; el_store_ring;
743  el_store_ring = BM_EDGELOOP_NEXT(el_store_ring)) {
744  ListBase *lb_ring = BM_edgeloop_verts_get(el_store_ring);
745  LinkData *v_iter;
746 
747  BMVert *v_a = ((LinkData *)lb_ring->first)->data;
748  BMVert *v_b = ((LinkData *)lb_ring->last)->data;
749 
750  float co_a[3], no_a[3], handle_a[3], co_b[3], no_b[3], handle_b[3];
751  float handle_len;
752 
753  copy_v3_v3(co_a, v_a->co);
754  copy_v3_v3(co_b, v_b->co);
755 
756  /* don't calculate normals here else we get into feedback loop
757  * when subdividing 2+ connected edge rings */
758 #if 0
759  bm_vert_calc_surface_tangent(bm, v_a, no_a);
760  bm_vert_calc_surface_tangent(bm, v_b, no_b);
761 #else
762  {
763  const uint index_a = POINTER_AS_UINT(BLI_ghash_lookup(lpair->nors_gh_a, v_a));
764  const uint index_b = POINTER_AS_UINT(BLI_ghash_lookup(lpair->nors_gh_b, v_b));
765 
766  BLI_assert(BLI_ghash_haskey(lpair->nors_gh_a, v_a));
767  BLI_assert(BLI_ghash_haskey(lpair->nors_gh_b, v_b));
768 
769  copy_v3_v3(no_a, lpair->nors_a[index_a]);
770  copy_v3_v3(no_b, lpair->nors_b[index_b]);
771  }
772 #endif
773  handle_len = bezier_handle_calc_length_v3(co_a, no_a, co_b, no_b) * smooth;
774 
775  mul_v3_v3fl(handle_a, no_a, handle_len);
776  mul_v3_v3fl(handle_b, no_b, handle_len);
777 
778  add_v3_v3(handle_a, co_a);
779  add_v3_v3(handle_b, co_b);
780 
781  for (i = 0; i < dims; i++) {
783  handle_a[i],
784  handle_b[i],
785  co_b[i],
786  ((float *)coord_array) + i,
787  resolu - 1,
788  sizeof(float) * dims);
789  }
790 
791  /* skip first and last */
792  for (v_iter = ((LinkData *)lb_ring->first)->next, i = 1; v_iter != lb_ring->last;
793  v_iter = v_iter->next, i++) {
794  if (i > 0 && i < resolu - 1) {
795  copy_v3_v3(((BMVert *)v_iter->data)->co, coord_array[i]);
796 
797  /* shape */
798  if (falloff_cache) {
799  interp_v3_v3v3(((BMVert *)v_iter->data)->co,
800  coord_array_main[i],
801  ((BMVert *)v_iter->data)->co,
802  falloff_cache[i]);
803  }
804  }
805  }
806  }
807 
808  MEM_freeN(coord_array);
809 
810  break;
811  }
812  }
813 
814  if (coord_array_main) {
815  MEM_freeN(coord_array_main);
816  }
817 }
818 
822 static void bm_face_slice(BMesh *bm, BMLoop *l, const int cuts)
823 {
824  /* TODO, interpolate edge data */
825  BMLoop *l_new = l;
826  int i;
827 
828  for (i = 0; i < cuts; i++) {
829  /* no chance of double */
830  BM_face_split(bm, l_new->f, l_new->prev, l_new->next->next, &l_new, NULL, false);
831  if (l_new == NULL) {
832  /* This happens when l_new->prev and l_new->next->next are adjacent. Since
833  * this sets l_new to NULL, we cannot continue this for-loop. */
834  break;
835  }
836  if (l_new->f->len < l_new->radial_next->f->len) {
837  l_new = l_new->radial_next;
838  }
839  BMO_face_flag_enable(bm, l_new->f, FACE_OUT);
841  }
842 }
843 
845  struct BMEdgeLoopStore *el_store_a,
846  struct BMEdgeLoopStore *el_store_b)
847 {
848  ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
849  ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
850 
851  LinkData *v_iter_a_first = lb_a->first;
852  LinkData *v_iter_b_first = lb_b->first;
853 
854  LinkData *v_iter_a_step = v_iter_a_first;
855  LinkData *v_iter_b_step = v_iter_b_first;
856 
857  /* we _must_ have same starting edge shared */
858  BLI_assert(BM_edge_exists(v_iter_a_first->data, v_iter_b_first->data));
859 
860  /* step around any fan-faces on both sides */
861  do {
862  v_iter_a_step = v_iter_a_step->next;
863  } while (v_iter_a_step && ((BM_edge_exists(v_iter_a_step->data, v_iter_b_first->data)) ||
864  (BM_edge_exists(v_iter_a_step->data, v_iter_b_first->next->data))));
865  do {
866  v_iter_b_step = v_iter_b_step->next;
867  } while (v_iter_b_step && ((BM_edge_exists(v_iter_b_step->data, v_iter_a_first->data)) ||
868  (BM_edge_exists(v_iter_b_step->data, v_iter_a_first->next->data))));
869 
870  v_iter_a_step = v_iter_a_step ? v_iter_a_step->prev : lb_a->last;
871  v_iter_b_step = v_iter_b_step ? v_iter_b_step->prev : lb_b->last;
872 
873  return !(BM_edge_exists(v_iter_a_step->data, v_iter_b_step->data) ||
874  BM_edge_exists(v_iter_a_first->next->data, v_iter_b_step->data) ||
875  BM_edge_exists(v_iter_b_first->next->data, v_iter_a_step->data));
876 }
877 
883  struct BMEdgeLoopStore *el_store_a,
884  struct BMEdgeLoopStore *el_store_b)
885 {
886  ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
887  ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
888 
889  LinkData *node;
890 
891  bm_edgeloop_vert_tag(el_store_a, false);
892  bm_edgeloop_vert_tag(el_store_b, true);
893 
894  /* before going much further, get ourselves in order
895  * - align loops (not strictly necessary but handy)
896  * - ensure winding is set for both loops */
897  if (BM_edgeloop_is_closed(el_store_a) && BM_edgeloop_is_closed(el_store_b)) {
898  BMIter eiter;
899  BMEdge *e;
900  BMVert *v_other;
901 
902  node = lb_a->first;
903 
904  BM_ITER_ELEM (e, &eiter, (BMVert *)node->data, BM_EDGES_OF_VERT) {
905  if (BMO_edge_flag_test(bm, e, EDGE_RING)) {
906  v_other = BM_edge_other_vert(e, (BMVert *)node->data);
907  if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
908  break;
909  }
910  v_other = NULL;
911  }
912  }
913  BLI_assert(v_other != NULL);
914 
915  for (node = lb_b->first; node; node = node->next) {
916  if (node->data == v_other) {
917  break;
918  }
919  }
920  BLI_assert(node != NULL);
921 
923 
924  /* now check we are winding the same way */
925  if (bm_edgering_pair_order_is_flipped(bm, el_store_a, el_store_b)) {
926  BM_edgeloop_flip(bm, el_store_b);
927  /* re-ensure the first node */
929  }
930 
931  /* sanity checks that we are aligned & winding now */
932  BLI_assert(bm_edgering_pair_order_is_flipped(bm, el_store_a, el_store_b) == false);
933  }
934  else {
935  /* If we don't share and edge - flip. */
936  BMEdge *e = BM_edge_exists(((LinkData *)lb_a->first)->data, ((LinkData *)lb_b->first)->data);
937  if (e == NULL || !BMO_edge_flag_test(bm, e, EDGE_RING)) {
938  BM_edgeloop_flip(bm, el_store_b);
939  }
940  }
941 
942  /* for cases with multiple loops */
943  bm_edgeloop_vert_tag(el_store_b, false);
944 }
945 
952  struct BMEdgeLoopStore *el_store_a,
953  struct BMEdgeLoopStore *el_store_b,
954  ListBase *eloops_ring,
955  const int cuts)
956 {
957  ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
958  // ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
959  const int stack_max = max_ii(BM_edgeloop_length_get(el_store_a),
960  BM_edgeloop_length_get(el_store_b)) *
961  2;
962  BMEdge **edges_ring_arr = BLI_array_alloca(edges_ring_arr, stack_max);
963  BMFace **faces_ring_arr = BLI_array_alloca(faces_ring_arr, stack_max);
964  STACK_DECLARE(edges_ring_arr);
965  STACK_DECLARE(faces_ring_arr);
966  struct BMEdgeLoopStore *el_store_ring;
967  LinkData *node;
968  BMEdge *e;
969  BMFace *f;
970 
971  STACK_INIT(edges_ring_arr, stack_max);
972  STACK_INIT(faces_ring_arr, stack_max);
973 
974  bm_edgeloop_vert_tag(el_store_a, false);
975  bm_edgeloop_vert_tag(el_store_b, true);
976 
977  for (node = lb_a->first; node; node = node->next) {
978  BMIter eiter;
979 
980  BM_ITER_ELEM (e, &eiter, (BMVert *)node->data, BM_EDGES_OF_VERT) {
982  BMVert *v_other = BM_edge_other_vert(e, (BMVert *)node->data);
983  if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
984  BMIter fiter;
985 
987  STACK_PUSH(edges_ring_arr, e);
988 
989  /* add faces to the stack */
990  BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
991  if (BMO_face_flag_test(bm, f, FACE_OUT)) {
992  if (!BMO_face_flag_test(bm, f, FACE_IN_STACK)) {
994  STACK_PUSH(faces_ring_arr, f);
995  }
996  }
997  }
998  }
999  }
1000  }
1001  }
1002 
1003  while ((e = STACK_POP(edges_ring_arr))) {
1004  /* found opposite edge */
1005  BMVert *v_other;
1006 
1008 
1009  /* unrelated to subdiv, but if we _don't_ clear flag, multiple rings fail */
1011 
1012  v_other = BM_elem_flag_test(e->v1, BM_ELEM_TAG) ? e->v1 : e->v2;
1013  bm_edge_subdiv_as_loop(bm, eloops_ring, e, v_other, cuts);
1014  }
1015 
1016  while ((f = STACK_POP(faces_ring_arr))) {
1017  BMLoop *l_iter, *l_first;
1018 
1020 
1021  /* Check each edge of the face */
1022  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1023  do {
1024  if (BMO_edge_flag_test(bm, l_iter->e, EDGE_RIM)) {
1025  bm_face_slice(bm, l_iter, cuts);
1026  break;
1027  }
1028  } while ((l_iter = l_iter->next) != l_first);
1029  }
1030 
1031  /* clear tags so subdiv verts don't get tagged too */
1032  for (el_store_ring = eloops_ring->first; el_store_ring;
1033  el_store_ring = BM_EDGELOOP_NEXT(el_store_ring)) {
1034  bm_edgeloop_vert_tag(el_store_ring, false);
1035  }
1036 
1037  /* cleanup after */
1038  bm_edgeloop_vert_tag(el_store_b, false);
1039 }
1040 
1042  LoopPairStore *lpair,
1043  struct BMEdgeLoopStore *el_store_a,
1044  struct BMEdgeLoopStore *el_store_b,
1045  const int interp_mode,
1046  const int cuts,
1047  const float smooth,
1048  const float *falloff_cache)
1049 {
1050  ListBase eloops_ring = {NULL};
1051  bm_edgering_pair_order(bm, el_store_a, el_store_b);
1052  bm_edgering_pair_subdiv(bm, el_store_a, el_store_b, &eloops_ring, cuts);
1054  bm, lpair, el_store_a, el_store_b, &eloops_ring, interp_mode, cuts, smooth, falloff_cache);
1055  BM_mesh_edgeloops_free(&eloops_ring);
1056 }
1057 
1058 static bool bm_edge_rim_test_cb(BMEdge *e, void *bm_v)
1059 {
1060  BMesh *bm = bm_v;
1062 }
1063 
1064 /* keep this operator fast, its used in a modifier */
1066 {
1067  ListBase eloops_rim = {NULL};
1068  BMOIter siter;
1069  BMEdge *e;
1070  int count;
1071  bool changed = false;
1072 
1073  const int cuts = BMO_slot_int_get(op->slots_in, "cuts");
1074  const int interp_mode = BMO_slot_int_get(op->slots_in, "interp_mode");
1075  const float smooth = BMO_slot_float_get(op->slots_in, "smooth");
1076  const int resolu = cuts + 2;
1077 
1078  /* optional 'shape' */
1079  const int profile_shape = BMO_slot_int_get(op->slots_in, "profile_shape");
1080  const float profile_shape_factor = BMO_slot_float_get(op->slots_in, "profile_shape_factor");
1081  float *falloff_cache = (profile_shape_factor != 0.0f) ?
1082  BLI_array_alloca(falloff_cache, cuts + 2) :
1083  NULL;
1084 
1086 
1088 
1089  /* -------------------------------------------------------------------- */
1090  /* flag outer edges (loops defined as edges on the bounds of the edge ring) */
1091 
1092  BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
1093  BMIter fiter;
1094  BMFace *f;
1095 
1096  BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
1097  /* could support ngons, other areas would need updating too, see T48926. */
1098  if ((f->len <= 4) && !BMO_face_flag_test(bm, f, FACE_OUT)) {
1099  BMIter liter;
1100  BMLoop *l;
1101  bool ok = false;
1102 
1103  /* check at least 2 edges in the face are rings */
1104  BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
1105  if (BMO_edge_flag_test(bm, l->e, EDGE_RING) && e != l->e) {
1106  ok = true;
1107  break;
1108  }
1109  }
1110 
1111  if (ok) {
1113 
1114  BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
1115  if (!BMO_edge_flag_test(bm, l->e, EDGE_RING)) {
1117  }
1118  }
1119  }
1120  }
1121  }
1122  }
1123 
1124  /* -------------------------------------------------------------------- */
1125  /* Cache falloff for each step (symmetrical) */
1126 
1127  if (falloff_cache) {
1128  int i;
1129  for (i = 0; i < resolu; i++) {
1130  float shape_size = 1.0f;
1131  float fac = (float)i / (float)(resolu - 1);
1132  fac = fabsf(1.0f - 2.0f * fabsf(0.5f - fac));
1133  fac = bmesh_subd_falloff_calc(profile_shape, fac);
1134  shape_size += fac * profile_shape_factor;
1135 
1136  falloff_cache[i] = shape_size;
1137  }
1138  }
1139 
1140  /* -------------------------------------------------------------------- */
1141  /* Execute subdivision on all ring pairs */
1142 
1143  count = BM_mesh_edgeloops_find(bm, &eloops_rim, bm_edge_rim_test_cb, (void *)bm);
1144 
1145  if (count < 2) {
1146  BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "No edge rings found");
1147  goto cleanup;
1148  }
1149  else if (count == 2) {
1150  /* this case could be removed,
1151  * but simple to avoid 'bm_edgering_pair_calc' in this case since there's only one. */
1152  struct BMEdgeLoopStore *el_store_a = eloops_rim.first;
1153  struct BMEdgeLoopStore *el_store_b = eloops_rim.last;
1154  LoopPairStore *lpair;
1155 
1156  if (bm_edgeloop_check_overlap_all(bm, el_store_a, el_store_b)) {
1157  lpair = bm_edgering_pair_store_create(bm, el_store_a, el_store_b, interp_mode);
1158  }
1159  else {
1160  lpair = NULL;
1161  }
1162 
1163  if (lpair) {
1165  bm, lpair, el_store_a, el_store_b, interp_mode, cuts, smooth, falloff_cache);
1166  bm_edgering_pair_store_free(lpair, interp_mode);
1167  changed = true;
1168  }
1169  else {
1170  BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Edge-ring pair isn't connected");
1171  goto cleanup;
1172  }
1173  }
1174  else {
1175  GSetIterator gs_iter;
1176  int i;
1177 
1178  GSet *eloop_pairs_gs = bm_edgering_pair_calc(bm, &eloops_rim);
1179  LoopPairStore **lpair_arr;
1180 
1181  if (eloop_pairs_gs == NULL) {
1182  BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Edge-rings are not connected");
1183  goto cleanup;
1184  }
1185 
1186  lpair_arr = BLI_array_alloca(lpair_arr, BLI_gset_len(eloop_pairs_gs));
1187 
1188  /* first cache pairs */
1189  GSET_ITER_INDEX (gs_iter, eloop_pairs_gs, i) {
1190  GHashPair *eloop_pair = BLI_gsetIterator_getKey(&gs_iter);
1191  struct BMEdgeLoopStore *el_store_a = (void *)eloop_pair->first;
1192  struct BMEdgeLoopStore *el_store_b = (void *)eloop_pair->second;
1193  LoopPairStore *lpair;
1194 
1195  if (bm_edgeloop_check_overlap_all(bm, el_store_a, el_store_b)) {
1196  lpair = bm_edgering_pair_store_create(bm, el_store_a, el_store_b, interp_mode);
1197  }
1198  else {
1199  lpair = NULL;
1200  }
1201  lpair_arr[i] = lpair;
1202 
1204  }
1205 
1206  GSET_ITER_INDEX (gs_iter, eloop_pairs_gs, i) {
1207  GHashPair *eloop_pair = BLI_gsetIterator_getKey(&gs_iter);
1208  struct BMEdgeLoopStore *el_store_a = (void *)eloop_pair->first;
1209  struct BMEdgeLoopStore *el_store_b = (void *)eloop_pair->second;
1210  LoopPairStore *lpair = lpair_arr[i];
1211 
1212  if (lpair) {
1214  bm, lpair, el_store_a, el_store_b, interp_mode, cuts, smooth, falloff_cache);
1215  bm_edgering_pair_store_free(lpair, interp_mode);
1216  changed = true;
1217  }
1218 
1220  }
1221  BLI_gset_free(eloop_pairs_gs, MEM_freeN);
1222  }
1223 
1224 cleanup:
1225  BM_mesh_edgeloops_free(&eloops_rim);
1226 
1227  /* flag output */
1228  if (changed) {
1230  }
1231 }
typedef float(TangentPoint)[2]
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition: curve.c:1804
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:36
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define GSET_ITER_INDEX(gs_iter_, gset_, i_)
Definition: BLI_ghash.h:272
struct GSet GSet
Definition: BLI_ghash.h:189
bool BLI_gset_ensure_p_ex(GSet *gs, const void *key, void ***r_key)
Definition: BLI_ghash.c:1171
unsigned int BLI_gset_len(GSet *gs) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1138
GHashPair * BLI_ghashutil_pairalloc(const void *first, const void *second)
bool BLI_ghash_haskey(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:941
GSet * BLI_gset_pair_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:756
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1253
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
BLI_INLINE void * BLI_gsetIterator_getKey(GSetIterator *gsi)
Definition: BLI_ghash.h:255
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
void BLI_listbase_rotate_first(struct ListBase *lb, void *vlink) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
MINLINE int max_ii(int a, int b)
void transform_point_by_tri_v3(float pt_tar[3], float const pt_src[3], const float tri_tar_p1[3], const float tri_tar_p2[3], const float tri_tar_p3[3], const float tri_src_p1[3], const float tri_src_p2[3], const float tri_src_p3[3])
Definition: math_geom.c:4121
float closest_to_line_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3364
void axis_angle_to_quat(float r[4], const float axis[3], const float angle)
float normalize_qt(float q[4])
void mul_qt_v3(const float q[4], float r[3])
Definition: math_rotation.c:97
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
Definition: math_rotation.c:65
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:52
void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], const float t)
Definition: math_vector.c:49
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_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 void negate_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
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 float normalize_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
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:505
MINLINE void add_v3_v3(float r[3], const float a[3])
void bisect_v3_v3v3v3(float r[3], const float a[3], const float b[3], const float c[3])
Definition: math_vector.c:791
unsigned int uint
Definition: BLI_sys_types.h:83
#define SWAP(type, a, b)
#define POINTER_AS_UINT(i)
#define UNUSED(x)
#define UNPACK3(a)
#define UNLIKELY(x)
#define POINTER_FROM_UINT(i)
#define STACK_POP(stack)
#define STACK_PUSH(stack, val)
#define STACK_DECLARE(stack)
#define STACK_INIT(stack, tot)
_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 GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Read Guarded memory(de)allocation.
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:553
const float * BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store)
void BM_mesh_edgeloops_free(ListBase *eloops)
BMEdgeLoopStore * BM_edgeloop_from_verts(BMVert **v_arr, const int v_arr_tot, bool is_closed)
int BM_mesh_edgeloops_find(BMesh *bm, ListBase *r_eloops, bool(*test_fn)(BMEdge *, void *user_data), void *user_data)
int BM_edgeloop_length_get(BMEdgeLoopStore *el_store)
bool BM_edgeloop_is_closed(BMEdgeLoopStore *el_store)
void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr)
ListBase * BM_edgeloop_verts_get(BMEdgeLoopStore *el_store)
bool BM_edgeloop_calc_normal(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
bool BM_edgeloop_calc_normal_aligned(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store, const float no_align[3])
const float * BM_edgeloop_normal_get(struct BMEdgeLoopStore *el_store)
void BM_edgeloop_flip(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
void BM_edgeloop_calc_center(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
#define BM_EDGELOOP_NEXT(el_store)
@ BMERR_INVALID_SELECTION
Definition: bmesh_error.h:60
void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg)
#define BM_elem_flag_set(ele, hflag, val)
Definition: bmesh_inline.h:30
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_EDGE
@ BM_VERTS_OF_MESH
@ BM_LOOPS_OF_EDGE
@ BM_EDGES_OF_VERT
@ BM_LOOPS_OF_FACE
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
BMVert * BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr)
Split an edge multiple times evenly.
Definition: bmesh_mods.c:711
BMFace * BM_face_split(BMesh *bm, BMFace *f, BMLoop *l_a, BMLoop *l_b, BMLoop **r_l, BMEdge *example, const bool no_double)
Face Split.
Definition: bmesh_mods.c:252
void BMO_slot_buffer_flag_enable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag)
BMO_FLAG_BUFFER.
#define BMO_edge_flag_test_bool(bm, e, oflag)
#define BMO_edge_flag_test(bm, e, oflag)
#define BMO_edge_flag_enable(bm, e, oflag)
float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
#define BMO_vert_flag_set(bm, e, oflag, val)
#define BMO_face_flag_enable(bm, e, oflag)
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag)
#define BMO_vert_flag_test(bm, e, oflag)
int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
#define BMO_face_flag_disable(bm, e, oflag)
#define BMO_edge_flag_disable(bm, e, oflag)
#define BMO_face_flag_test(bm, e, oflag)
void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag)
ATTR_WARN_UNUSED_RESULT const BMFlagLayer const short oflag
@ SUBD_RING_INTERP_SURF
@ SUBD_RING_INTERP_PATH
@ SUBD_RING_INTERP_LINEAR
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1995
float bmesh_subd_falloff_calc(const int falloff, float val)
Definition: bmesh_query.c:2984
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:1803
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) 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 BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
struct LoopPairStore LoopPairStore
static void bm_edgering_pair_order(BMesh *bm, struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b)
void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
#define FACE_OUT
static bool bm_edge_rim_test_cb(BMEdge *e, void *bm_v)
static float bezier_handle_calc_length_v3(const float co_a[3], const float no_a[3], const float co_b[3], const float no_b[3])
static void bm_edge_subdiv_as_loop(BMesh *bm, ListBase *eloops, BMEdge *e, BMVert *v_a, const int cuts)
static void bm_faces_share_tag_flush(BMesh *bm, BMEdge **e_arr, const uint e_arr_len)
#define FACE_IN_STACK
static uint bm_verts_tag_count(BMesh *bm)
static bool bmo_face_is_vert_tag_all(BMesh *bm, BMFace *f, short oflag)
static void bm_edgering_pair_ringsubd(BMesh *bm, LoopPairStore *lpair, struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b, const int interp_mode, const int cuts, const float smooth, const float *falloff_cache)
static void bm_faces_share_tag_clear(BMesh *bm, BMEdge **e_arr_iter, const uint e_arr_len_iter)
static void bm_face_slice(BMesh *bm, BMLoop *l, const int cuts)
static bool bm_edgeloop_check_overlap_all(BMesh *bm, struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b)
static void bm_vert_calc_surface_tangent(BMesh *bm, BMVert *v, float r_no[3])
#define EDGE_RING
static void bm_edgering_pair_store_free(LoopPairStore *lpair, const int interp_mode)
static void bm_edgering_pair_interpolate(BMesh *bm, LoopPairStore *lpair, struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b, ListBase *eloops_ring, const int interp_mode, const int cuts, const float smooth, const float *falloff_cache)
static void bm_edgeloop_vert_tag(struct BMEdgeLoopStore *el_store, const bool tag)
static bool bm_vert_is_tag_edge_connect(BMesh *bm, BMVert *v)
#define EDGE_IN_STACK
static bool bm_edgering_pair_order_is_flipped(BMesh *UNUSED(bm), struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b)
static void bm_edgering_pair_subdiv(BMesh *bm, struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b, ListBase *eloops_ring, const int cuts)
static GSet * bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim)
#define FACE_SHARED
#define VERT_SHARED
static void bmo_edgeloop_vert_tag(BMesh *bm, struct BMEdgeLoopStore *el_store, const short oflag, const bool tag)
#define EDGE_RIM
static LoopPairStore * bm_edgering_pair_store_create(BMesh *bm, struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b, const int interp_mode)
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
OperationNode * node
uint nor
int count
#define fabsf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static ulong * next
int len
Definition: bmesh_class.h:279
struct BMVert * v
Definition: bmesh_class.h:165
struct BMEdge * e
Definition: bmesh_class.h:176
struct BMLoop * radial_next
Definition: bmesh_class.h:216
struct BMLoop * prev
Definition: bmesh_class.h:245
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]
float co[3]
Definition: bmesh_class.h:99
const void * second
Definition: BLI_ghash.h:382
const void * first
Definition: BLI_ghash.h:381
void * data
Definition: DNA_listBase.h:42
struct LinkData * next
Definition: DNA_listBase.h:41
struct LinkData * prev
Definition: DNA_listBase.h:41
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
ccl_device_inline float dot(const float2 &a, const float2 &b)
uint len