Cleanup: remove redundant doxygen \file argument
[blender.git] / source / blender / bmesh / operators / bmo_bridge.c
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
17 /** \file \ingroup bmesh
18  *
19  * Connect verts across faces (splits faces) and bridge tool.
20  */
21
22 #include "BLI_math.h"
23 #include "BLI_utildefines.h"
24 #include "BLI_listbase.h"
25
26 #include "bmesh.h"
27
28 #include "intern/bmesh_operators_private.h" /* own include */
29
30 #define EDGE_MARK       4
31 #define EDGE_OUT        8
32 #define FACE_OUT        16
33
34 /* el_a and el_b _must_ be same size */
35 static void bm_bridge_splice_loops(BMesh *bm, LinkData *el_a, LinkData *el_b, const float merge_factor)
36 {
37         BMOperator op_weld;
38         BMOpSlot *slot_targetmap;
39
40         BMO_op_init(bm, &op_weld, 0, "weld_verts");
41
42         slot_targetmap = BMO_slot_get(op_weld.slots_in, "targetmap");
43
44         do {
45                 BMVert *v_a = el_a->data, *v_b = el_b->data;
46                 BM_data_interp_from_verts(bm, v_a, v_b, v_b, merge_factor);
47                 interp_v3_v3v3(v_b->co, v_a->co, v_b->co, merge_factor);
48                 BLI_assert(v_a != v_b);
49                 BMO_slot_map_elem_insert(&op_weld, slot_targetmap, v_a, v_b);
50         } while ((void)
51                  (el_b = el_b->next),
52                  (el_a = el_a->next));
53
54         BMO_op_exec(bm, &op_weld);
55         BMO_op_finish(bm, &op_weld);
56 }
57
58 /* get the 2 loops matching 2 verts.
59  * first attempt to get the face corners that use the edge defined by v1 & v2,
60  * if that fails just get any loop thats on the vert (the first one) */
61 static void bm_vert_loop_pair(BMesh *bm, BMVert *v1, BMVert *v2, BMLoop **l1, BMLoop **l2)
62 {
63         BMEdge *e = BM_edge_exists(v1, v2);
64         BMLoop *l = e->l;
65
66         if (l) {
67                 if (l->v == v1) {
68                         *l1 = l;
69                         *l2 = l->next;
70                 }
71                 else {
72                         *l2 = l;
73                         *l1 = l->next;
74                 }
75         }
76         else {
77                 /* fallback to _any_ loop */
78                 *l1 = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v1, 0);
79                 *l2 = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v2, 0);
80         }
81 }
82
83 /* el_b can have any offset */
84 static float bm_edgeloop_offset_length(
85         LinkData *el_a, LinkData *el_b,
86         LinkData *el_b_first, const float len_max)
87 {
88         float len = 0.0f;
89         BLI_assert(el_a->prev == NULL);  /* must be first */
90         do {
91                 len += len_v3v3(((BMVert *)el_a->data)->co, ((BMVert *)el_b->data)->co);
92         } while ((void)
93                  (el_b = el_b->next ? el_b->next : el_b_first),
94                  (el_a = el_a->next) && (len < len_max));
95         return len;
96 }
97
98 static void bm_bridge_best_rotation(struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b)
99 {
100         ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
101         ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
102         LinkData *el_a = lb_a->first;
103         LinkData *el_b = lb_b->first;
104         LinkData *el_b_first = el_b;
105         LinkData *el_b_best = NULL;
106
107         float len_best = FLT_MAX;
108
109         for (; el_b; el_b = el_b->next) {
110                 const float len = bm_edgeloop_offset_length(el_a, el_b, el_b_first, len_best);
111                 if (len < len_best) {
112                         el_b_best = el_b;
113                         len_best = len;
114                 }
115         }
116
117         if (el_b_best) {
118                 BLI_listbase_rotate_first(lb_b, el_b_best);
119         }
120 }
121
122 static void bm_face_edges_tag_out(BMesh *bm, BMFace *f)
123 {
124         BMLoop *l_iter, *l_first;
125         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
126         do {
127                 BMO_edge_flag_enable(bm, l_iter->e, EDGE_OUT);
128         } while ((l_iter = l_iter->next) != l_first);
129 }
130
131 static bool bm_edge_test_cb(BMEdge *e, void *bm_v)
132 {
133         return BMO_edge_flag_test((BMesh *)bm_v, e, EDGE_MARK);
134 }
135
136 static void bridge_loop_pair(
137         BMesh *bm,
138         struct BMEdgeLoopStore *el_store_a,
139         struct BMEdgeLoopStore *el_store_b,
140         const bool use_merge, const float merge_factor, const int twist_offset)
141 {
142         const float eps = 0.00001f;
143         LinkData *el_a_first, *el_b_first;
144         const bool is_closed = BM_edgeloop_is_closed(el_store_a) && BM_edgeloop_is_closed(el_store_b);
145         int el_store_a_len, el_store_b_len;
146         bool el_store_b_free = false;
147         float el_dir[3];
148         float dot_a, dot_b;
149         const bool use_edgeout = true;
150
151         el_store_a_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_a);
152         el_store_b_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_b);
153
154         if (el_store_a_len < el_store_b_len) {
155                 SWAP(int, el_store_a_len, el_store_b_len);
156                 SWAP(struct BMEdgeLoopStore *, el_store_a, el_store_b);
157         }
158
159         if (use_merge) {
160                 BLI_assert((el_store_a_len == el_store_b_len));
161         }
162
163         if (el_store_a_len != el_store_b_len) {
164                 BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false);
165         }
166
167         sub_v3_v3v3(el_dir, BM_edgeloop_center_get(el_store_a), BM_edgeloop_center_get(el_store_b));
168
169         if (is_closed) {
170                 /* if all loops are closed this will calculate twice for all loops */
171                 BM_edgeloop_calc_normal(bm, el_store_a);
172                 BM_edgeloop_calc_normal(bm, el_store_b);
173         }
174         else {
175                 ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
176                 ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
177
178                 /* normalizing isn't strictly needed but without we may get very large values */
179                 float no[3];
180                 float dir_a_orig[3], dir_b_orig[3];
181                 float dir_a[3], dir_b[3];
182                 const float *test_a, *test_b;
183
184                 sub_v3_v3v3(dir_a_orig,
185                             ((BMVert *)(((LinkData *)lb_a->first)->data))->co,
186                             ((BMVert *)(((LinkData *)lb_a->last)->data))->co);
187                 sub_v3_v3v3(dir_b_orig,
188                             ((BMVert *)(((LinkData *)lb_b->first)->data))->co,
189                             ((BMVert *)(((LinkData *)lb_b->last)->data))->co);
190
191                 /* make the directions point out from the normals, 'no' is used as a temp var */
192                 cross_v3_v3v3(no, dir_a_orig, el_dir); cross_v3_v3v3(dir_a, no, el_dir);
193                 cross_v3_v3v3(no, dir_b_orig, el_dir); cross_v3_v3v3(dir_b, no, el_dir);
194
195                 if (LIKELY(!is_zero_v3(dir_a) && !is_zero_v3(dir_b))) {
196                         test_a = dir_a;
197                         test_b = dir_b;
198                 }
199                 else {
200                         /**
201                          * This is a corner case:
202                          *
203                          * <pre>
204                          *  (loop a)    (loop b)
205                          * +--------+  +--------+
206                          * </pre>
207                          *
208                          * When loops are aligned to the direction between the loops values of 'dir_a/b' is degenerate,
209                          * in this case compare the original directions (before they were corrected by 'el_dir'), see: T43013
210                          */
211                         test_a = dir_a_orig;
212                         test_b = dir_b_orig;
213                 }
214
215                 if (dot_v3v3(test_a, test_b) < 0.0f) {
216                         BM_edgeloop_flip(bm, el_store_b);
217                 }
218
219                 normalize_v3_v3(no, el_dir);
220                 BM_edgeloop_calc_normal_aligned(bm, el_store_a, no);
221                 BM_edgeloop_calc_normal_aligned(bm, el_store_b, no);
222         }
223
224         dot_a = dot_v3v3(BM_edgeloop_normal_get(el_store_a), el_dir);
225         dot_b = dot_v3v3(BM_edgeloop_normal_get(el_store_b), el_dir);
226
227         if (UNLIKELY((len_squared_v3(el_dir) < eps) ||
228                      ((fabsf(dot_a) < eps) && (fabsf(dot_b) < eps))))
229         {
230                 /* in this case there is no depth between the two loops,
231                  * eg: 2x 2d circles, one scaled smaller,
232                  * in this case 'el_dir' cant be used, just ensure we have matching flipping. */
233                 if (dot_v3v3(BM_edgeloop_normal_get(el_store_a),
234                              BM_edgeloop_normal_get(el_store_b)) < 0.0f)
235                 {
236                         BM_edgeloop_flip(bm, el_store_b);
237                 }
238         }
239         else if ((dot_a < 0.0f) != (dot_b < 0.0f)) {
240                 BM_edgeloop_flip(bm, el_store_b);
241         }
242
243         /* we only care about flipping if we make faces */
244         if (use_merge == false) {
245                 float no[3];
246
247                 add_v3_v3v3(no, BM_edgeloop_normal_get(el_store_a), BM_edgeloop_normal_get(el_store_b));
248
249                 if (dot_v3v3(no, el_dir) < 0.0f) {
250                         BM_edgeloop_flip(bm, el_store_a);
251                         BM_edgeloop_flip(bm, el_store_b);
252                 }
253
254                 /* vote on winding (so new face winding is based on existing connected faces) */
255                 if (bm->totface) {
256                         struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b};
257                         int i;
258                         int winding_votes[2] = {0, 0};
259                         int winding_dir = 1;
260                         for (i = 0; i < 2; i++, winding_dir = -winding_dir) {
261                                 LinkData *el;
262                                 for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
263                                         LinkData *el_next = BM_EDGELINK_NEXT(estore_pair[i], el);
264                                         if (el_next) {
265                                                 BMEdge *e = BM_edge_exists(el->data, el_next->data);
266                                                 if (e && BM_edge_is_boundary(e)) {
267                                                         winding_votes[i] += ((e->l->v == el->data) ? winding_dir : -winding_dir);
268                                                 }
269                                         }
270                                 }
271                         }
272
273                         if (winding_votes[0] || winding_votes[1]) {
274                                 bool flip[2] = {false, false};
275
276                                 /* for direction aligned loops we can't rely on the directly we have,
277                                  * use the winding defined by the connected faces (see T48356). */
278                                 if (fabsf(dot_a) < eps) {
279                                         if (winding_votes[0] < 0) {
280                                                 flip[0] = !flip[0];
281                                                 winding_votes[0] *= -1;
282
283                                         }
284                                 }
285                                 if (fabsf(dot_b) < eps) {
286                                         if (winding_votes[1] < 0) {
287                                                 flip[1] = !flip[1];
288                                                 winding_votes[1] *= -1;
289                                         }
290                                 }
291
292                                 /* when both loops contradict the winding, flip them so surrounding geometry matches */
293                                 if ((winding_votes[0] + winding_votes[1]) < 0) {
294                                         flip[0] = !flip[0];
295                                         flip[1] = !flip[1];
296
297                                         /* valid but unused */
298 #if 0
299                                         winding_votes[0] *= -1;
300                                         winding_votes[1] *= -1;
301 #endif
302                                 }
303
304                                 if (flip[0]) {
305                                         BM_edgeloop_flip(bm, el_store_a);
306                                 }
307                                 if (flip[1]) {
308                                         BM_edgeloop_flip(bm, el_store_b);
309                                 }
310                         }
311                 }
312         }
313
314         if (el_store_a_len > el_store_b_len) {
315                 el_store_b = BM_edgeloop_copy(el_store_b);
316                 BM_edgeloop_expand(bm, el_store_b, el_store_a_len, false, NULL);
317                 el_store_b_free = true;
318         }
319
320         if (is_closed) {
321                 bm_bridge_best_rotation(el_store_a, el_store_b);
322
323                 /* add twist */
324                 if (twist_offset != 0) {
325                         const int len_b = BM_edgeloop_length_get(el_store_b);
326                         ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
327                         LinkData *el_b = BLI_rfindlink(lb_b, mod_i(twist_offset, len_b));
328                         BLI_listbase_rotate_first(lb_b, el_b);
329                 }
330         }
331
332         /* Assign after flipping is finalized */
333         el_a_first = BM_edgeloop_verts_get(el_store_a)->first;
334         el_b_first = BM_edgeloop_verts_get(el_store_b)->first;
335
336
337         if (use_merge) {
338                 bm_bridge_splice_loops(bm, el_a_first, el_b_first, merge_factor);
339         }
340         else {
341                 LinkData *el_a = el_a_first;
342                 LinkData *el_b = el_b_first;
343
344                 LinkData *el_a_next;
345                 LinkData *el_b_next;
346
347
348                 while (true) {
349                         BMFace *f, *f_example;
350                         BMLoop *l_iter;
351                         BMVert *v_a, *v_b, *v_a_next, *v_b_next;
352
353                         BMLoop *l_a = NULL;
354                         BMLoop *l_b = NULL;
355                         BMLoop *l_a_next = NULL;
356                         BMLoop *l_b_next = NULL;
357
358                         if (is_closed) {
359                                 el_a_next = BM_EDGELINK_NEXT(el_store_a, el_a);
360                                 el_b_next = BM_EDGELINK_NEXT(el_store_b, el_b);
361                         }
362                         else {
363                                 el_a_next = el_a->next;
364                                 el_b_next = el_b->next;
365                                 if (ELEM(NULL, el_a_next, el_b_next)) {
366                                         break;
367                                 }
368                         }
369
370                         v_a = el_a->data;
371                         v_b = el_b->data;
372                         v_a_next = el_a_next->data;
373                         v_b_next = el_b_next->data;
374
375                         /* get loop data - before making the face */
376                         if (v_b != v_b_next) {
377                                 bm_vert_loop_pair(bm, v_a, v_a_next, &l_a, &l_a_next);
378                                 bm_vert_loop_pair(bm, v_b, v_b_next, &l_b, &l_b_next);
379                         }
380                         else {
381                                 /* lazy, could be more clever here */
382                                 bm_vert_loop_pair(bm, v_a, v_a_next, &l_a, &l_a_next);
383                                 l_b = l_b_next = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v_b, 0);
384                         }
385
386                         if (l_a && l_a_next == NULL) l_a_next = l_a;
387                         if (l_a_next && l_a == NULL) l_a = l_a_next;
388                         if (l_b && l_b_next == NULL) l_b_next = l_b;
389                         if (l_b_next && l_b == NULL) l_b = l_b_next;
390                         f_example = l_a ? l_a->f : (l_b ? l_b->f : NULL);
391
392                         if (v_b != v_b_next) {
393                                 BMVert *v_arr[4] = {v_a, v_b, v_b_next, v_a_next};
394                                 f = BM_face_exists(v_arr, 4);
395                                 if (f == NULL) {
396                                         /* copy if loop data if its is missing on one ring */
397                                         f = BM_face_create_verts(bm, v_arr, 4, NULL, BM_CREATE_NOP, true);
398
399                                         l_iter = BM_FACE_FIRST_LOOP(f);
400                                         if (l_b)      { BM_elem_attrs_copy(bm, bm, l_b,      l_iter); } l_iter = l_iter->next;
401                                         if (l_b_next) { BM_elem_attrs_copy(bm, bm, l_b_next, l_iter); } l_iter = l_iter->next;
402                                         if (l_a_next) { BM_elem_attrs_copy(bm, bm, l_a_next, l_iter); } l_iter = l_iter->next;
403                                         if (l_a)      { BM_elem_attrs_copy(bm, bm, l_a,      l_iter); }
404                                 }
405                         }
406                         else {
407                                 BMVert *v_arr[3] = {v_a, v_b, v_a_next};
408                                 f = BM_face_exists(v_arr, 3);
409                                 if (f == NULL) {
410                                         /* fan-fill a triangle */
411                                         f = BM_face_create_verts(bm, v_arr, 3, NULL, BM_CREATE_NOP, true);
412
413                                         l_iter = BM_FACE_FIRST_LOOP(f);
414                                         if (l_b)      { BM_elem_attrs_copy(bm, bm, l_b,      l_iter); } l_iter = l_iter->next;
415                                         if (l_a_next) { BM_elem_attrs_copy(bm, bm, l_a_next, l_iter); } l_iter = l_iter->next;
416                                         if (l_a)      { BM_elem_attrs_copy(bm, bm, l_a,      l_iter); }
417                                 }
418                         }
419
420                         if (f_example && (f_example != f)) {
421                                 BM_elem_attrs_copy(bm, bm, f_example, f);
422                         }
423                         BMO_face_flag_enable(bm, f, FACE_OUT);
424                         BM_elem_flag_enable(f, BM_ELEM_TAG);
425
426                         /* tag all edges of the face, untag the loop edges after */
427                         if (use_edgeout) {
428                                 bm_face_edges_tag_out(bm, f);
429                         }
430
431                         if (el_a_next == el_a_first) {
432                                 break;
433                         }
434
435                         el_a = el_a_next;
436                         el_b = el_b_next;
437                 }
438         }
439
440         if (el_store_a_len != el_store_b_len) {
441                 struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b};
442                 int i;
443
444                 BMOperator op_sub;
445                 /* when we have to bridge between different sized edge-loops,
446                  * be clever and post-process for best results */
447
448
449                 /* triangulate inline */
450                 BMO_op_initf(bm, &op_sub, 0,
451                              "triangulate faces=%hf",
452                              BM_ELEM_TAG, true);
453                 /* calc normals for input faces before executing */
454                 {
455                         BMOIter siter;
456                         BMFace *f;
457                         BMO_ITER (f, &siter, op_sub.slots_in, "faces", BM_FACE) {
458                                 BM_face_normal_update(f);
459                         }
460                 }
461                 BMO_op_exec(bm, &op_sub);
462                 BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "faces.out", BM_FACE, FACE_OUT);
463                 BMO_slot_buffer_hflag_enable(bm, op_sub.slots_out, "faces.out", BM_FACE, BM_ELEM_TAG, false);
464                 BMO_op_finish(bm, &op_sub);
465
466
467                 /* tag verts on each side so we can restrict rotation of edges to verts on the same side */
468                 for (i = 0; i < 2; i++) {
469                         LinkData *el;
470                         for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
471                                 BM_elem_flag_set((BMVert *)el->data, BM_ELEM_TAG, i);
472                         }
473                 }
474
475
476                 BMO_op_initf(bm, &op_sub, 0,
477                              "beautify_fill faces=%hf edges=ae use_restrict_tag=%b method=%i",
478                              BM_ELEM_TAG, true, 1);
479
480                 if (use_edgeout) {
481                         BMOIter siter;
482                         BMFace *f;
483                         BMO_ITER (f, &siter, op_sub.slots_in, "faces", BM_FACE) {
484                                 BMO_face_flag_enable(bm, f, FACE_OUT);
485                                 bm_face_edges_tag_out(bm, f);
486                         }
487                 }
488
489                 BMO_op_exec(bm, &op_sub);
490                 /* there may also be tagged faces that didnt rotate, mark input */
491
492                 if (use_edgeout) {
493                         BMOIter siter;
494                         BMFace *f;
495                         BMO_ITER (f, &siter, op_sub.slots_out, "geom.out", BM_FACE) {
496                                 BMO_face_flag_enable(bm, f, FACE_OUT);
497                                 bm_face_edges_tag_out(bm, f);
498                         }
499                 }
500                 else {
501                         BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "geom.out", BM_FACE, FACE_OUT);
502                 }
503
504                 BMO_op_finish(bm, &op_sub);
505         }
506
507         if (use_edgeout && use_merge == false) {
508                 /* we've enabled all face edges above, now disable all loop edges */
509                 struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b};
510                 int i;
511                 for (i = 0; i < 2; i++) {
512                         LinkData *el;
513                         for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
514                                 LinkData *el_next = BM_EDGELINK_NEXT(estore_pair[i], el);
515                                 if (el_next) {
516                                         if (el->data != el_next->data) {
517                                                 BMEdge *e = BM_edge_exists(el->data, el_next->data);
518                                                 BMO_edge_flag_disable(bm, e, EDGE_OUT);
519                                         }
520                                 }
521                         }
522                 }
523         }
524
525         if (el_store_b_free) {
526                 BM_edgeloop_free(el_store_b);
527         }
528 }
529
530 void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
531 {
532         ListBase eloops = {NULL};
533         LinkData *el_store;
534
535         /* merge-bridge support */
536         const bool  use_pairs    = BMO_slot_bool_get(op->slots_in,  "use_pairs");
537         const bool  use_merge    = BMO_slot_bool_get(op->slots_in,  "use_merge");
538         const float merge_factor = BMO_slot_float_get(op->slots_in, "merge_factor");
539         const bool  use_cyclic   = BMO_slot_bool_get(op->slots_in,  "use_cyclic") && (use_merge == false);
540         const int   twist_offset = BMO_slot_int_get(op->slots_in,   "twist_offset");
541         int count;
542         bool changed = false;
543
544         BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
545
546         count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, bm);
547
548         BM_mesh_edgeloops_calc_center(bm, &eloops);
549
550         if (count < 2) {
551                 BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
552                                 "Select at least two edge loops");
553                 goto cleanup;
554         }
555
556         if (use_pairs && (count % 2)) {
557                 BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
558                                 "Select an even number of loops to bridge pairs");
559                 goto cleanup;
560         }
561
562         if (use_merge) {
563                 bool match = true;
564                 const int eloop_len = BM_edgeloop_length_get(eloops.first);
565                 for (el_store = eloops.first; el_store; el_store = el_store->next) {
566                         if (eloop_len != BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store)) {
567                                 match = false;
568                                 break;
569                         }
570                 }
571                 if (!match) {
572                         BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
573                                         "Selected loops must have equal edge counts");
574                         goto cleanup;
575                 }
576         }
577
578         if (count > 2) {
579                 if (use_pairs) {
580                         BM_mesh_edgeloops_calc_normal(bm, &eloops);
581                 }
582                 BM_mesh_edgeloops_calc_order(bm, &eloops, use_pairs);
583         }
584
585         for (el_store = eloops.first; el_store; el_store = el_store->next) {
586                 LinkData *el_store_next = el_store->next;
587
588                 if (el_store_next == NULL) {
589                         if (use_cyclic && (count > 2)) {
590                                 el_store_next = eloops.first;
591                         }
592                         else {
593                                 break;
594                         }
595                 }
596
597                 bridge_loop_pair(bm,
598                                  (struct BMEdgeLoopStore *)el_store,
599                                  (struct BMEdgeLoopStore *)el_store_next,
600                                  use_merge, merge_factor, twist_offset);
601                 if (use_pairs) {
602                         el_store = el_store->next;
603                 }
604                 changed = true;
605         }
606
607 cleanup:
608         BM_mesh_edgeloops_free(&eloops);
609
610         if (changed) {
611                 if (use_merge == false) {
612                         BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
613                         BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
614                 }
615         }
616 }