bmo_bridge.c 18 KB

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