PageRenderTime 66ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/blender-2.63a/source/blender/bmesh/intern/bmesh_core.c

#
C | 2128 lines | 1349 code | 368 blank | 411 comment | 369 complexity | 3523c0ed8259bbca01be2ba7b82eff74 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, BSD-3-Clause, LGPL-3.0, BSD-2-Clause, Apache-2.0, AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  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, Geoffrey Bantle, Campbell Barton
  19. *
  20. * ***** END GPL LICENSE BLOCK *****
  21. */
  22. /** \file blender/bmesh/intern/bmesh_core.c
  23. * \ingroup bmesh
  24. *
  25. */
  26. #include "MEM_guardedalloc.h"
  27. #include "BLI_math_vector.h"
  28. #include "BKE_DerivedMesh.h"
  29. #include "BLI_listbase.h"
  30. #include "BLI_array.h"
  31. #include "bmesh.h"
  32. #include "intern/bmesh_private.h"
  33. /* use so valgrinds memcheck alerts us when undefined index is used.
  34. * TESTING ONLY! */
  35. // #define USE_DEBUG_INDEX_MEMCHECK
  36. #ifdef USE_DEBUG_INDEX_MEMCHECK
  37. #define DEBUG_MEMCHECK_INDEX_INVALIDATE(ele) \
  38. { \
  39. int undef_idx; \
  40. BM_elem_index_set(ele, undef_idx); /* set_ok_invalid */ \
  41. } \
  42. #endif
  43. /**
  44. * \brief Main function for creating a new vertex.
  45. */
  46. BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example)
  47. {
  48. BMVert *v = BLI_mempool_calloc(bm->vpool);
  49. #ifdef USE_DEBUG_INDEX_MEMCHECK
  50. DEBUG_MEMCHECK_INDEX_INVALIDATE(v)
  51. #else
  52. BM_elem_index_set(v, -1); /* set_ok_invalid */
  53. #endif
  54. bm->elem_index_dirty |= BM_VERT; /* may add to middle of the pool */
  55. bm->totvert++;
  56. v->head.htype = BM_VERT;
  57. /* 'v->no' is handled by BM_elem_attrs_copy */
  58. if (co) {
  59. copy_v3_v3(v->co, co);
  60. }
  61. /* allocate flag */
  62. v->oflags = BLI_mempool_calloc(bm->toolflagpool);
  63. CustomData_bmesh_set_default(&bm->vdata, &v->head.data);
  64. if (example) {
  65. BM_elem_attrs_copy(bm, bm, example, v);
  66. }
  67. BM_CHECK_ELEMENT(v);
  68. return v;
  69. }
  70. /**
  71. * \brief Main function for creating a new edge.
  72. *
  73. * \note Duplicate edges are supported by the API however users should _never_ see them.
  74. * so unless you need a unique edge or know the edge won't exist, you should call wih \a nodouble=TRUE
  75. */
  76. BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble)
  77. {
  78. BMEdge *e;
  79. if (nodouble && (e = BM_edge_exists(v1, v2)))
  80. return e;
  81. e = BLI_mempool_calloc(bm->epool);
  82. #ifdef USE_DEBUG_INDEX_MEMCHECK
  83. DEBUG_MEMCHECK_INDEX_INVALIDATE(e)
  84. #else
  85. BM_elem_index_set(e, -1); /* set_ok_invalid */
  86. #endif
  87. bm->elem_index_dirty |= BM_EDGE; /* may add to middle of the pool */
  88. bm->totedge++;
  89. e->head.htype = BM_EDGE;
  90. /* allocate flag */
  91. e->oflags = BLI_mempool_calloc(bm->toolflagpool);
  92. e->v1 = v1;
  93. e->v2 = v2;
  94. BM_elem_flag_enable(e, BM_ELEM_SMOOTH);
  95. CustomData_bmesh_set_default(&bm->edata, &e->head.data);
  96. bmesh_disk_edge_append(e, e->v1);
  97. bmesh_disk_edge_append(e, e->v2);
  98. if (example)
  99. BM_elem_attrs_copy(bm, bm, example, e);
  100. BM_CHECK_ELEMENT(e);
  101. return e;
  102. }
  103. static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, const BMLoop *example)
  104. {
  105. BMLoop *l = NULL;
  106. l = BLI_mempool_calloc(bm->lpool);
  107. l->next = l->prev = NULL;
  108. l->v = v;
  109. l->e = e;
  110. l->f = f;
  111. l->radial_next = l->radial_prev = NULL;
  112. l->head.data = NULL;
  113. l->head.htype = BM_LOOP;
  114. bm->totloop++;
  115. if (example) {
  116. CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data);
  117. }
  118. else {
  119. CustomData_bmesh_set_default(&bm->ldata, &l->head.data);
  120. }
  121. return l;
  122. }
  123. static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte)
  124. {
  125. #ifdef USE_BMESH_HOLES
  126. BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool);
  127. #endif
  128. BMLoop *l = bm_loop_create(bm, startv, starte, f, NULL);
  129. bmesh_radial_append(starte, l);
  130. #ifdef USE_BMESH_HOLES
  131. lst->first = lst->last = l;
  132. BLI_addtail(&f->loops, lst);
  133. #else
  134. f->l_first = l;
  135. #endif
  136. l->f = f;
  137. return l;
  138. }
  139. BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short copyedges)
  140. {
  141. BMVert **verts = NULL;
  142. BMEdge **edges = NULL;
  143. BLI_array_fixedstack_declare(verts, BM_NGON_STACK_SIZE, f->len, __func__);
  144. BLI_array_fixedstack_declare(edges, BM_NGON_STACK_SIZE, f->len, __func__);
  145. BMLoop *l_iter;
  146. BMLoop *l_first;
  147. BMLoop *l_copy;
  148. BMFace *f_copy;
  149. int i;
  150. l_iter = l_first = BM_FACE_FIRST_LOOP(f);
  151. i = 0;
  152. do {
  153. if (copyverts) {
  154. verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v);
  155. }
  156. else {
  157. verts[i] = l_iter->v;
  158. }
  159. i++;
  160. } while ((l_iter = l_iter->next) != l_first);
  161. l_iter = l_first = BM_FACE_FIRST_LOOP(f);
  162. i = 0;
  163. do {
  164. if (copyedges) {
  165. BMVert *v1, *v2;
  166. if (l_iter->e->v1 == verts[i]) {
  167. v1 = verts[i];
  168. v2 = verts[(i + 1) % f->len];
  169. }
  170. else {
  171. v2 = verts[i];
  172. v1 = verts[(i + 1) % f->len];
  173. }
  174. edges[i] = BM_edge_create(bm, v1, v2, l_iter->e, FALSE);
  175. }
  176. else {
  177. edges[i] = l_iter->e;
  178. }
  179. i++;
  180. } while ((l_iter = l_iter->next) != l_first);
  181. f_copy = BM_face_create(bm, verts, edges, f->len, FALSE);
  182. BM_elem_attrs_copy(bm, bm, f, f_copy);
  183. l_iter = l_first = BM_FACE_FIRST_LOOP(f);
  184. l_copy = BM_FACE_FIRST_LOOP(f_copy);
  185. do {
  186. BM_elem_attrs_copy(bm, bm, l_iter, l_copy);
  187. l_copy = l_copy->next;
  188. } while ((l_iter = l_iter->next) != l_first);
  189. BLI_array_fixedstack_free(verts);
  190. BLI_array_fixedstack_free(edges);
  191. return f_copy;
  192. }
  193. /**
  194. * only create the face, since this calloc's the length is initialized to 0,
  195. * leave adding loops to the caller.
  196. */
  197. BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm)
  198. {
  199. BMFace *f;
  200. f = BLI_mempool_calloc(bm->fpool);
  201. #ifdef USE_DEBUG_INDEX_MEMCHECK
  202. DEBUG_MEMCHECK_INDEX_INVALIDATE(f)
  203. #else
  204. BM_elem_index_set(f, -1); /* set_ok_invalid */
  205. #endif
  206. bm->elem_index_dirty |= BM_FACE; /* may add to middle of the pool */
  207. bm->totface++;
  208. f->head.htype = BM_FACE;
  209. /* allocate flag */
  210. f->oflags = BLI_mempool_calloc(bm->toolflagpool);
  211. CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
  212. #ifdef USE_BMESH_HOLES
  213. f->totbounds = 0;
  214. #endif
  215. return f;
  216. }
  217. /**
  218. * \brief Main face creation function
  219. */
  220. BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble)
  221. {
  222. BMFace *f = NULL;
  223. BMLoop *l, *startl, *lastl;
  224. int i, overlap;
  225. if (len == 0) {
  226. /* just return NULL for no */
  227. return NULL;
  228. }
  229. if (nodouble) {
  230. /* Check if face already exists */
  231. overlap = BM_face_exists(bm, verts, len, &f);
  232. if (overlap) {
  233. return f;
  234. }
  235. else {
  236. BLI_assert(f == NULL);
  237. }
  238. }
  239. f = bm_face_create__internal(bm);
  240. startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0]);
  241. startl->v = verts[0];
  242. startl->e = edges[0];
  243. for (i = 1; i < len; i++) {
  244. l = bm_loop_create(bm, verts[i], edges[i], f, edges[i]->l);
  245. l->f = f;
  246. bmesh_radial_append(edges[i], l);
  247. l->prev = lastl;
  248. lastl->next = l;
  249. lastl = l;
  250. }
  251. startl->prev = lastl;
  252. lastl->next = startl;
  253. f->len = len;
  254. BM_CHECK_ELEMENT(f);
  255. return f;
  256. }
  257. /**
  258. * Check the element is valid.
  259. *
  260. * BMESH_TODO, when this raises an error the output is incredible confusing.
  261. * need to have some nice way to print/debug what the hecks going on.
  262. */
  263. int bmesh_elem_check(void *element, const char htype)
  264. {
  265. BMHeader *head = element;
  266. int err = 0;
  267. if (!element)
  268. return 1;
  269. if (head->htype != htype)
  270. return 2;
  271. switch (htype) {
  272. case BM_VERT: {
  273. BMVert *v = element;
  274. if (v->e && v->e->head.htype != BM_EDGE) {
  275. err |= 4;
  276. }
  277. break;
  278. }
  279. case BM_EDGE: {
  280. BMEdge *e = element;
  281. if (e->l && e->l->head.htype != BM_LOOP)
  282. err |= 8;
  283. if (e->l && e->l->f->head.htype != BM_FACE)
  284. err |= 16;
  285. if (e->v1_disk_link.prev == NULL ||
  286. e->v2_disk_link.prev == NULL ||
  287. e->v1_disk_link.next == NULL ||
  288. e->v2_disk_link.next == NULL)
  289. {
  290. err |= 32;
  291. }
  292. if (e->l && (e->l->radial_next == NULL || e->l->radial_prev == NULL))
  293. err |= 64;
  294. if (e->l && e->l->f->len <= 0)
  295. err |= 128;
  296. break;
  297. }
  298. case BM_LOOP: {
  299. BMLoop *l = element, *l2;
  300. int i;
  301. if (l->f->head.htype != BM_FACE)
  302. err |= 256;
  303. if (l->e->head.htype != BM_EDGE)
  304. err |= 512;
  305. if (l->v->head.htype != BM_VERT)
  306. err |= 1024;
  307. if (!BM_vert_in_edge(l->e, l->v)) {
  308. fprintf(stderr, "%s: fatal bmesh error (vert not in edge)! (bmesh internal error)\n", __func__);
  309. err |= 2048;
  310. }
  311. if (l->radial_next == NULL || l->radial_prev == NULL)
  312. err |= (1 << 12);
  313. if (l->f->len <= 0)
  314. err |= (1 << 13);
  315. /* validate boundary loop -- invalid for hole loops, of course,
  316. * but we won't be allowing those for a while yet */
  317. l2 = l;
  318. i = 0;
  319. do {
  320. if (i >= BM_NGON_MAX) {
  321. break;
  322. }
  323. i++;
  324. } while ((l2 = l2->next) != l);
  325. if (i != l->f->len || l2 != l)
  326. err |= (1 << 14);
  327. if (!bmesh_radial_validate(bmesh_radial_length(l), l))
  328. err |= (1 << 15);
  329. break;
  330. }
  331. case BM_FACE: {
  332. BMFace *f = element;
  333. BMLoop *l_iter;
  334. BMLoop *l_first;
  335. int len = 0;
  336. #ifdef USE_BMESH_HOLES
  337. if (!f->loops.first)
  338. #else
  339. if (!f->l_first)
  340. #endif
  341. {
  342. err |= (1 << 16);
  343. }
  344. l_iter = l_first = BM_FACE_FIRST_LOOP(f);
  345. do {
  346. if (l_iter->f != f) {
  347. fprintf(stderr, "%s: loop inside one face points to another! (bmesh internal error)\n", __func__);
  348. err |= (1 << 17);
  349. }
  350. if (!l_iter->e)
  351. err |= (1 << 18);
  352. if (!l_iter->v)
  353. err |= (1 << 19);
  354. if (!BM_vert_in_edge(l_iter->e, l_iter->v) || !BM_vert_in_edge(l_iter->e, l_iter->next->v)) {
  355. err |= (1 << 20);
  356. }
  357. if (!bmesh_radial_validate(bmesh_radial_length(l_iter), l_iter))
  358. err |= (1 << 21);
  359. if (!bmesh_disk_count(l_iter->v) || !bmesh_disk_count(l_iter->next->v))
  360. err |= (1 << 22);
  361. len++;
  362. } while ((l_iter = l_iter->next) != l_first);
  363. if (len != f->len)
  364. err |= (1 << 23);
  365. }
  366. }
  367. BMESH_ASSERT(err == 0);
  368. return err;
  369. }
  370. /**
  371. * low level function, only frees the vert,
  372. * doesn't change or adjust surrounding geometry
  373. */
  374. static void bm_kill_only_vert(BMesh *bm, BMVert *v)
  375. {
  376. bm->totvert--;
  377. bm->elem_index_dirty |= BM_VERT;
  378. BM_select_history_remove(bm, v);
  379. if (v->head.data)
  380. CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
  381. BLI_mempool_free(bm->toolflagpool, v->oflags);
  382. BLI_mempool_free(bm->vpool, v);
  383. }
  384. /**
  385. * low level function, only frees the edge,
  386. * doesn't change or adjust surrounding geometry
  387. */
  388. static void bm_kill_only_edge(BMesh *bm, BMEdge *e)
  389. {
  390. bm->totedge--;
  391. bm->elem_index_dirty |= BM_EDGE;
  392. BM_select_history_remove(bm, (BMElem *)e);
  393. if (e->head.data)
  394. CustomData_bmesh_free_block(&bm->edata, &e->head.data);
  395. BLI_mempool_free(bm->toolflagpool, e->oflags);
  396. BLI_mempool_free(bm->epool, e);
  397. }
  398. /**
  399. * low level function, only frees the face,
  400. * doesn't change or adjust surrounding geometry
  401. */
  402. static void bm_kill_only_face(BMesh *bm, BMFace *f)
  403. {
  404. if (bm->act_face == f)
  405. bm->act_face = NULL;
  406. bm->totface--;
  407. bm->elem_index_dirty |= BM_FACE;
  408. BM_select_history_remove(bm, (BMElem *)f);
  409. if (f->head.data)
  410. CustomData_bmesh_free_block(&bm->pdata, &f->head.data);
  411. BLI_mempool_free(bm->toolflagpool, f->oflags);
  412. BLI_mempool_free(bm->fpool, f);
  413. }
  414. /**
  415. * low level function, only frees the loop,
  416. * doesn't change or adjust surrounding geometry
  417. */
  418. static void bm_kill_only_loop(BMesh *bm, BMLoop *l)
  419. {
  420. bm->totloop--;
  421. if (l->head.data)
  422. CustomData_bmesh_free_block(&bm->ldata, &l->head.data);
  423. BLI_mempool_free(bm->lpool, l);
  424. }
  425. /**
  426. * kills all edges associated with \a f, along with any other faces containing
  427. * those edges
  428. */
  429. void BM_face_edges_kill(BMesh *bm, BMFace *f)
  430. {
  431. BMEdge **edges = NULL;
  432. BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE);
  433. BMLoop *l_iter;
  434. BMLoop *l_first;
  435. int i;
  436. l_iter = l_first = BM_FACE_FIRST_LOOP(f);
  437. do {
  438. BLI_array_append(edges, l_iter->e);
  439. } while ((l_iter = l_iter->next) != l_first);
  440. for (i = 0; i < BLI_array_count(edges); i++) {
  441. BM_edge_kill(bm, edges[i]);
  442. }
  443. BLI_array_free(edges);
  444. }
  445. /**
  446. * kills all verts associated with \a f, along with any other faces containing
  447. * those vertices
  448. */
  449. void BM_face_verts_kill(BMesh *bm, BMFace *f)
  450. {
  451. BMVert **verts = NULL;
  452. BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE);
  453. BMLoop *l_iter;
  454. BMLoop *l_first;
  455. int i;
  456. l_iter = l_first = BM_FACE_FIRST_LOOP(f);
  457. do {
  458. BLI_array_append(verts, l_iter->v);
  459. } while ((l_iter = l_iter->next) != l_first);
  460. for (i = 0; i < BLI_array_count(verts); i++) {
  461. BM_vert_kill(bm, verts[i]);
  462. }
  463. BLI_array_free(verts);
  464. }
  465. /**
  466. * Kills \a f and its loops.
  467. */
  468. void BM_face_kill(BMesh *bm, BMFace *f)
  469. {
  470. #ifdef USE_BMESH_HOLES
  471. BMLoopList *ls, *ls_next;
  472. #endif
  473. BM_CHECK_ELEMENT(f);
  474. #ifdef USE_BMESH_HOLES
  475. for (ls = f->loops.first; ls; ls = ls_next)
  476. #else
  477. if (f->l_first)
  478. #endif
  479. {
  480. BMLoop *l_iter, *l_next, *l_first;
  481. #ifdef USE_BMESH_HOLES
  482. ls_next = ls->next;
  483. l_iter = l_first = ls->first;
  484. #else
  485. l_iter = l_first = f->l_first;
  486. #endif
  487. do {
  488. l_next = l_iter->next;
  489. bmesh_radial_loop_remove(l_iter, l_iter->e);
  490. bm_kill_only_loop(bm, l_iter);
  491. } while ((l_iter = l_next) != l_first);
  492. #ifdef USE_BMESH_HOLES
  493. BLI_mempool_free(bm->looplistpool, ls);
  494. #endif
  495. }
  496. bm_kill_only_face(bm, f);
  497. }
  498. /**
  499. * kills \a e and all faces that use it.
  500. */
  501. void BM_edge_kill(BMesh *bm, BMEdge *e)
  502. {
  503. bmesh_disk_edge_remove(e, e->v1);
  504. bmesh_disk_edge_remove(e, e->v2);
  505. if (e->l) {
  506. BMLoop *l = e->l, *lnext, *startl = e->l;
  507. do {
  508. lnext = l->radial_next;
  509. if (lnext->f == l->f) {
  510. BM_face_kill(bm, l->f);
  511. break;
  512. }
  513. BM_face_kill(bm, l->f);
  514. if (l == lnext)
  515. break;
  516. l = lnext;
  517. } while (l != startl);
  518. }
  519. bm_kill_only_edge(bm, e);
  520. }
  521. /**
  522. * kills \a v and all edges that use it.
  523. */
  524. void BM_vert_kill(BMesh *bm, BMVert *v)
  525. {
  526. if (v->e) {
  527. BMEdge *e, *nexte;
  528. e = v->e;
  529. while (v->e) {
  530. nexte = bmesh_disk_edge_next(e, v);
  531. BM_edge_kill(bm, e);
  532. e = nexte;
  533. }
  534. }
  535. bm_kill_only_vert(bm, v);
  536. }
  537. /********** private disk and radial cycle functions ********** */
  538. /**
  539. * return the length of the face, should always equal \a l->f->len
  540. */
  541. static int UNUSED_FUNCTION(bm_loop_length)(BMLoop *l)
  542. {
  543. BMLoop *l_first = l;
  544. int i = 0;
  545. do {
  546. i++;
  547. } while ((l = l->next) != l_first);
  548. return i;
  549. }
  550. /**
  551. * \brief Loop Reverse
  552. *
  553. * Changes the winding order of a face from CW to CCW or vice versa.
  554. * This euler is a bit peculiar in comparison to others as it is its
  555. * own inverse.
  556. *
  557. * BMESH_TODO: reinsert validation code.
  558. *
  559. * \return Success
  560. */
  561. static int bm_loop_reverse_loop(BMesh *bm, BMFace *f
  562. #ifdef USE_BMESH_HOLES
  563. , BMLoopList *lst
  564. #endif
  565. )
  566. {
  567. #ifdef USE_BMESH_HOLES
  568. BMLoop *l_first = lst->first;
  569. #else
  570. BMLoop *l_first = f->l_first;
  571. #endif
  572. const int len = f->len;
  573. const int do_disps = CustomData_has_layer(&bm->ldata, CD_MDISPS);
  574. BMLoop *l_iter, *oldprev, *oldnext;
  575. BMEdge **edar = NULL;
  576. BLI_array_fixedstack_declare(edar, BM_NGON_STACK_SIZE, len, __func__);
  577. int i, j, edok;
  578. for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) {
  579. bmesh_radial_loop_remove(l_iter, (edar[i] = l_iter->e));
  580. }
  581. /* actually reverse the loop */
  582. for (i = 0, l_iter = l_first; i < len; i++) {
  583. oldnext = l_iter->next;
  584. oldprev = l_iter->prev;
  585. l_iter->next = oldprev;
  586. l_iter->prev = oldnext;
  587. l_iter = oldnext;
  588. if (do_disps) {
  589. float (*co)[3];
  590. int x, y, sides;
  591. MDisps *md;
  592. md = CustomData_bmesh_get(&bm->ldata, l_iter->head.data, CD_MDISPS);
  593. if (!md->totdisp || !md->disps)
  594. continue;
  595. sides = (int)sqrt(md->totdisp);
  596. co = md->disps;
  597. for (x = 0; x < sides; x++) {
  598. for (y = 0; y < x; y++) {
  599. swap_v3_v3(co[y * sides + x], co[sides * x + y]);
  600. }
  601. }
  602. }
  603. }
  604. if (len == 2) { /* two edged face */
  605. /* do some verification here! */
  606. l_first->e = edar[1];
  607. l_first->next->e = edar[0];
  608. }
  609. else {
  610. for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) {
  611. edok = 0;
  612. for (j = 0; j < len; j++) {
  613. edok = bmesh_verts_in_edge(l_iter->v, l_iter->next->v, edar[j]);
  614. if (edok) {
  615. l_iter->e = edar[j];
  616. break;
  617. }
  618. }
  619. }
  620. }
  621. /* rebuild radia */
  622. for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next)
  623. bmesh_radial_append(l_iter->e, l_iter);
  624. /* validate radia */
  625. for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) {
  626. BM_CHECK_ELEMENT(l_iter);
  627. BM_CHECK_ELEMENT(l_iter->e);
  628. BM_CHECK_ELEMENT(l_iter->v);
  629. BM_CHECK_ELEMENT(l_iter->f);
  630. }
  631. BLI_array_fixedstack_free(edar);
  632. BM_CHECK_ELEMENT(f);
  633. return 1;
  634. }
  635. /**
  636. * \brief Flip the faces direction
  637. */
  638. int bmesh_loop_reverse(BMesh *bm, BMFace *f)
  639. {
  640. #ifdef USE_BMESH_HOLES
  641. return bmesh_loop_reverse_loop(bm, f, f->loops.first);
  642. #else
  643. return bm_loop_reverse_loop(bm, f);
  644. #endif
  645. }
  646. static void bm_elements_systag_enable(void *veles, int tot, int flag)
  647. {
  648. BMHeader **eles = veles;
  649. int i;
  650. for (i = 0; i < tot; i++) {
  651. BM_ELEM_API_FLAG_ENABLE((BMElemF *)eles[i], flag);
  652. }
  653. }
  654. static void bm_elements_systag_disable(void *veles, int tot, int flag)
  655. {
  656. BMHeader **eles = veles;
  657. int i;
  658. for (i = 0; i < tot; i++) {
  659. BM_ELEM_API_FLAG_DISABLE((BMElemF *)eles[i], flag);
  660. }
  661. }
  662. #define FACE_MARK (1 << 10)
  663. static int count_flagged_radial(BMesh *bm, BMLoop *l, int flag)
  664. {
  665. BMLoop *l2 = l;
  666. int i = 0, c = 0;
  667. do {
  668. if (UNLIKELY(!l2)) {
  669. BMESH_ASSERT(0);
  670. goto error;
  671. }
  672. i += BM_ELEM_API_FLAG_TEST(l2->f, flag) ? 1 : 0;
  673. l2 = l2->radial_next;
  674. if (UNLIKELY(c >= BM_LOOP_RADIAL_MAX)) {
  675. BMESH_ASSERT(0);
  676. goto error;
  677. }
  678. c++;
  679. } while (l2 != l);
  680. return i;
  681. error:
  682. BMO_error_raise(bm, bm->currentop, BMERR_MESH_ERROR, NULL);
  683. return 0;
  684. }
  685. static int UNUSED_FUNCTION(count_flagged_disk)(BMVert *v, int flag)
  686. {
  687. BMEdge *e = v->e;
  688. int i = 0;
  689. if (!e)
  690. return 0;
  691. do {
  692. i += BM_ELEM_API_FLAG_TEST(e, flag) ? 1 : 0;
  693. } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
  694. return i;
  695. }
  696. static int disk_is_flagged(BMVert *v, int flag)
  697. {
  698. BMEdge *e = v->e;
  699. if (!e)
  700. return FALSE;
  701. do {
  702. BMLoop *l = e->l;
  703. if (!l) {
  704. return FALSE;
  705. }
  706. if (bmesh_radial_length(l) == 1)
  707. return FALSE;
  708. do {
  709. if (!BM_ELEM_API_FLAG_TEST(l->f, flag))
  710. return FALSE;
  711. l = l->radial_next;
  712. } while (l != e->l);
  713. e = bmesh_disk_edge_next(e, v);
  714. } while (e != v->e);
  715. return TRUE;
  716. }
  717. /* Mid-level Topology Manipulation Functions */
  718. /**
  719. * \brief Join Connected Faces
  720. *
  721. * Joins a collected group of faces into one. Only restriction on
  722. * the input data is that the faces must be connected to each other.
  723. *
  724. * \return The newly created combine BMFace.
  725. *
  726. * \note If a pair of faces share multiple edges,
  727. * the pair of faces will be joined at every edge.
  728. *
  729. * \note this is a generic, flexible join faces function,
  730. * almost everything uses this, including #BM_faces_join_pair
  731. */
  732. BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del)
  733. {
  734. BMFace *f, *newf;
  735. #ifdef USE_BMESH_HOLES
  736. BMLoopList *lst;
  737. ListBase holes = {NULL, NULL};
  738. #endif
  739. BMLoop *l_iter;
  740. BMLoop *l_first;
  741. BMEdge **edges = NULL;
  742. BMEdge **deledges = NULL;
  743. BMVert **delverts = NULL;
  744. BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE);
  745. BLI_array_staticdeclare(deledges, BM_NGON_STACK_SIZE);
  746. BLI_array_staticdeclare(delverts, BM_NGON_STACK_SIZE);
  747. BMVert *v1 = NULL, *v2 = NULL;
  748. const char *err = NULL;
  749. int i, tote = 0;
  750. if (UNLIKELY(!totface)) {
  751. BMESH_ASSERT(0);
  752. return NULL;
  753. }
  754. if (totface == 1)
  755. return faces[0];
  756. bm_elements_systag_enable(faces, totface, _FLAG_JF);
  757. for (i = 0; i < totface; i++) {
  758. f = faces[i];
  759. l_iter = l_first = BM_FACE_FIRST_LOOP(f);
  760. do {
  761. int rlen = count_flagged_radial(bm, l_iter, _FLAG_JF);
  762. if (rlen > 2) {
  763. err = "Input faces do not form a contiguous manifold region";
  764. goto error;
  765. }
  766. else if (rlen == 1) {
  767. BLI_array_append(edges, l_iter->e);
  768. if (!v1) {
  769. v1 = l_iter->v;
  770. v2 = BM_edge_other_vert(l_iter->e, l_iter->v);
  771. }
  772. tote++;
  773. }
  774. else if (rlen == 2) {
  775. int d1, d2;
  776. d1 = disk_is_flagged(l_iter->e->v1, _FLAG_JF);
  777. d2 = disk_is_flagged(l_iter->e->v2, _FLAG_JF);
  778. if (!d1 && !d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e, _FLAG_JF)) {
  779. /* don't remove an edge it makes up the side of another face
  780. * else this will remove the face as well - campbell */
  781. if (BM_edge_face_count(l_iter->e) <= 2) {
  782. if (do_del) {
  783. BLI_array_append(deledges, l_iter->e);
  784. }
  785. BM_ELEM_API_FLAG_ENABLE(l_iter->e, _FLAG_JF);
  786. }
  787. }
  788. else {
  789. if (d1 && !BM_ELEM_API_FLAG_TEST(l_iter->e->v1, _FLAG_JF)) {
  790. if (do_del) {
  791. BLI_array_append(delverts, l_iter->e->v1);
  792. }
  793. BM_ELEM_API_FLAG_ENABLE(l_iter->e->v1, _FLAG_JF);
  794. }
  795. if (d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e->v2, _FLAG_JF)) {
  796. if (do_del) {
  797. BLI_array_append(delverts, l_iter->e->v2);
  798. }
  799. BM_ELEM_API_FLAG_ENABLE(l_iter->e->v2, _FLAG_JF);
  800. }
  801. }
  802. }
  803. } while ((l_iter = l_iter->next) != l_first);
  804. #ifdef USE_BMESH_HOLES
  805. for (lst = f->loops.first; lst; lst = lst->next) {
  806. if (lst == f->loops.first) {
  807. continue;
  808. }
  809. BLI_remlink(&f->loops, lst);
  810. BLI_addtail(&holes, lst);
  811. }
  812. #endif
  813. }
  814. /* create region face */
  815. newf = BM_face_create_ngon(bm, v1, v2, edges, tote, FALSE);
  816. if (!newf || BMO_error_occurred(bm)) {
  817. if (!BMO_error_occurred(bm))
  818. err = "Invalid boundary region to join faces";
  819. goto error;
  820. }
  821. /* copy over loop data */
  822. l_iter = l_first = BM_FACE_FIRST_LOOP(newf);
  823. do {
  824. BMLoop *l2 = l_iter->radial_next;
  825. do {
  826. if (BM_ELEM_API_FLAG_TEST(l2->f, _FLAG_JF))
  827. break;
  828. l2 = l2->radial_next;
  829. } while (l2 != l_iter);
  830. if (l2 != l_iter) {
  831. /* I think this is correct */
  832. if (l2->v != l_iter->v) {
  833. l2 = l2->next;
  834. }
  835. BM_elem_attrs_copy(bm, bm, l2, l_iter);
  836. }
  837. } while ((l_iter = l_iter->next) != l_first);
  838. BM_elem_attrs_copy(bm, bm, faces[0], newf);
  839. #ifdef USE_BMESH_HOLES
  840. /* add hole */
  841. BLI_movelisttolist(&newf->loops, &holes);
  842. #endif
  843. /* update loop face pointer */
  844. #ifdef USE_BMESH_HOLES
  845. for (lst = newf->loops.first; lst; lst = lst->next)
  846. #endif
  847. {
  848. #ifdef USE_BMESH_HOLES
  849. l_iter = l_first = lst->first;
  850. #else
  851. l_iter = l_first = BM_FACE_FIRST_LOOP(newf);
  852. #endif
  853. do {
  854. l_iter->f = newf;
  855. } while ((l_iter = l_iter->next) != l_first);
  856. }
  857. bm_elements_systag_disable(faces, totface, _FLAG_JF);
  858. BM_ELEM_API_FLAG_DISABLE(newf, _FLAG_JF);
  859. /* handle multi-res data */
  860. if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
  861. l_iter = l_first = BM_FACE_FIRST_LOOP(newf);
  862. do {
  863. for (i = 0; i < totface; i++) {
  864. BM_loop_interp_multires(bm, l_iter, faces[i]);
  865. }
  866. } while ((l_iter = l_iter->next) != l_first);
  867. }
  868. /* delete old geometry */
  869. if (do_del) {
  870. for (i = 0; i < BLI_array_count(deledges); i++) {
  871. BM_edge_kill(bm, deledges[i]);
  872. }
  873. for (i = 0; i < BLI_array_count(delverts); i++) {
  874. BM_vert_kill(bm, delverts[i]);
  875. }
  876. }
  877. else {
  878. /* otherwise we get both old and new faces */
  879. for (i = 0; i < totface; i++) {
  880. BM_face_kill(bm, faces[i]);
  881. }
  882. }
  883. BLI_array_free(edges);
  884. BLI_array_free(deledges);
  885. BLI_array_free(delverts);
  886. BM_CHECK_ELEMENT(newf);
  887. return newf;
  888. error:
  889. bm_elements_systag_disable(faces, totface, _FLAG_JF);
  890. BLI_array_free(edges);
  891. BLI_array_free(deledges);
  892. BLI_array_free(delverts);
  893. if (err) {
  894. BMO_error_raise(bm, bm->currentop, BMERR_DISSOLVEFACES_FAILED, err);
  895. }
  896. return NULL;
  897. }
  898. static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *UNUSED(example))
  899. {
  900. BMFace *f;
  901. #ifdef USE_BMESH_HOLES
  902. BMLoopList *lst;
  903. #endif
  904. f = bm_face_create__internal(bm);
  905. #ifdef USE_BMESH_HOLES
  906. lst = BLI_mempool_calloc(bm->looplistpool);
  907. BLI_addtail(&f->loops, lst);
  908. #endif
  909. #ifdef USE_BMESH_HOLES
  910. f->totbounds = 1;
  911. #endif
  912. return f;
  913. }
  914. /**
  915. * \brief Split Face Make Edge (SFME)
  916. *
  917. * Takes as input two vertices in a single face. An edge is created which divides the original face
  918. * into two distinct regions. One of the regions is assigned to the original face and it is closed off.
  919. * The second region has a new face assigned to it.
  920. *
  921. * \par Examples:
  922. *
  923. * Before: After:
  924. * +--------+ +--------+
  925. * | | | |
  926. * | | | f1 |
  927. * v1 f1 v2 v1======v2
  928. * | | | f2 |
  929. * | | | |
  930. * +--------+ +--------+
  931. *
  932. * \note the input vertices can be part of the same edge. This will
  933. * result in a two edged face. This is desirable for advanced construction
  934. * tools and particularly essential for edge bevel. Because of this it is
  935. * up to the caller to decide what to do with the extra edge.
  936. *
  937. * \note If \a holes is NULL, then both faces will lose
  938. * all holes from the original face. Also, you cannot split between
  939. * a hole vert and a boundary vert; that case is handled by higher-
  940. * level wrapping functions (when holes are fully implemented, anyway).
  941. *
  942. * \note that holes represents which holes goes to the new face, and of
  943. * course this requires removing them from the existing face first, since
  944. * you cannot have linked list links inside multiple lists.
  945. *
  946. * \return A BMFace pointer
  947. */
  948. BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
  949. BMLoop **r_l,
  950. #ifdef USE_BMESH_HOLES
  951. ListBase *holes,
  952. #endif
  953. BMEdge *example,
  954. const short nodouble
  955. )
  956. {
  957. #ifdef USE_BMESH_HOLES
  958. BMLoopList *lst, *lst2;
  959. #endif
  960. BMFace *f2;
  961. BMLoop *l_iter, *l_first;
  962. BMLoop *v1loop = NULL, *v2loop = NULL, *f1loop = NULL, *f2loop = NULL;
  963. BMEdge *e;
  964. int i, len, f1len, f2len, first_loop_f1;
  965. /* verify that v1 and v2 are in face */
  966. len = f->len;
  967. for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < len; i++, l_iter = l_iter->next) {
  968. if (l_iter->v == v1) v1loop = l_iter;
  969. else if (l_iter->v == v2) v2loop = l_iter;
  970. }
  971. if (!v1loop || !v2loop) {
  972. return NULL;
  973. }
  974. /* allocate new edge between v1 and v2 */
  975. e = BM_edge_create(bm, v1, v2, example, nodouble);
  976. f2 = bm_face_create__sfme(bm, f);
  977. f1loop = bm_loop_create(bm, v2, e, f, v2loop);
  978. f2loop = bm_loop_create(bm, v1, e, f2, v1loop);
  979. f1loop->prev = v2loop->prev;
  980. f2loop->prev = v1loop->prev;
  981. v2loop->prev->next = f1loop;
  982. v1loop->prev->next = f2loop;
  983. f1loop->next = v1loop;
  984. f2loop->next = v2loop;
  985. v1loop->prev = f1loop;
  986. v2loop->prev = f2loop;
  987. #ifdef USE_BMESH_HOLES
  988. lst = f->loops.first;
  989. lst2 = f2->loops.first;
  990. lst2->first = lst2->last = f2loop;
  991. lst->first = lst->last = f1loop;
  992. #else
  993. /* find which of the faces the original first loop is in */
  994. l_iter = l_first = f1loop;
  995. first_loop_f1 = 0;
  996. do {
  997. if (l_iter == f->l_first)
  998. first_loop_f1 = 1;
  999. } while ((l_iter = l_iter->next) != l_first);
  1000. if (first_loop_f1) {
  1001. /* original first loop was in f1, find a suitable first loop for f2
  1002. * which is as similar as possible to f1. the order matters for tools
  1003. * such as duplifaces. */
  1004. if (f->l_first->prev == f1loop)
  1005. f2->l_first = f2loop->prev;
  1006. else if (f->l_first->next == f1loop)
  1007. f2->l_first = f2loop->next;
  1008. else
  1009. f2->l_first = f2loop;
  1010. }
  1011. else {
  1012. /* original first loop was in f2, further do same as above */
  1013. f2->l_first = f->l_first;
  1014. if (f->l_first->prev == f2loop)
  1015. f->l_first = f1loop->prev;
  1016. else if (f->l_first->next == f2loop)
  1017. f->l_first = f1loop->next;
  1018. else
  1019. f->l_first = f1loop;
  1020. }
  1021. #endif
  1022. /* validate both loop */
  1023. /* I don't know how many loops are supposed to be in each face at this point! FIXME */
  1024. /* go through all of f2's loops and make sure they point to it properly */
  1025. l_iter = l_first = BM_FACE_FIRST_LOOP(f2);
  1026. f2len = 0;
  1027. do {
  1028. l_iter->f = f2;
  1029. f2len++;
  1030. } while ((l_iter = l_iter->next) != l_first);
  1031. /* link up the new loops into the new edges radial */
  1032. bmesh_radial_append(e, f1loop);
  1033. bmesh_radial_append(e, f2loop);
  1034. f2->len = f2len;
  1035. f1len = 0;
  1036. l_iter = l_first = BM_FACE_FIRST_LOOP(f);
  1037. do {
  1038. f1len++;
  1039. } while ((l_iter = l_iter->next) != l_first);
  1040. f->len = f1len;
  1041. if (r_l) *r_l = f2loop;
  1042. #ifdef USE_BMESH_HOLES
  1043. if (holes) {
  1044. BLI_movelisttolist(&f2->loops, holes);
  1045. }
  1046. else {
  1047. /* this code is not significant until holes actually work */
  1048. //printf("warning: call to split face euler without holes argument; holes will be tossed.\n");
  1049. for (lst = f->loops.last; lst != f->loops.first; lst = lst2) {
  1050. lst2 = lst->prev;
  1051. BLI_mempool_free(bm->looplistpool, lst);
  1052. }
  1053. }
  1054. #endif
  1055. BM_CHECK_ELEMENT(e);
  1056. BM_CHECK_ELEMENT(f);
  1057. BM_CHECK_ELEMENT(f2);
  1058. return f2;
  1059. }
  1060. /**
  1061. * \brief Split Edge Make Vert (SEMV)
  1062. *
  1063. * Takes \a e edge and splits it into two, creating a new vert.
  1064. * \a tv should be one end of \a e : the newly created edge
  1065. * will be attached to that end and is returned in \a r_e.
  1066. *
  1067. * \par Examples:
  1068. *
  1069. * E
  1070. * Before: OV-------------TV
  1071. *
  1072. * E RE
  1073. * After: OV------NV-----TV
  1074. *
  1075. * \return The newly created BMVert pointer.
  1076. */
  1077. BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
  1078. {
  1079. BMLoop *nextl;
  1080. BMEdge *ne;
  1081. BMVert *nv, *ov;
  1082. int i, edok, valence1 = 0, valence2 = 0;
  1083. BLI_assert(bmesh_vert_in_edge(e, tv) != FALSE);
  1084. ov = bmesh_edge_other_vert_get(e, tv);
  1085. valence1 = bmesh_disk_count(ov);
  1086. valence2 = bmesh_disk_count(tv);
  1087. nv = BM_vert_create(bm, tv->co, tv);
  1088. ne = BM_edge_create(bm, nv, tv, e, FALSE);
  1089. bmesh_disk_edge_remove(ne, tv);
  1090. bmesh_disk_edge_remove(ne, nv);
  1091. /* remove e from tv's disk cycle */
  1092. bmesh_disk_edge_remove(e, tv);
  1093. /* swap out tv for nv in e */
  1094. bmesh_edge_swapverts(e, tv, nv);
  1095. /* add e to nv's disk cycle */
  1096. bmesh_disk_edge_append(e, nv);
  1097. /* add ne to nv's disk cycle */
  1098. bmesh_disk_edge_append(ne, nv);
  1099. /* add ne to tv's disk cycle */
  1100. bmesh_disk_edge_append(ne, tv);
  1101. /* verify disk cycle */
  1102. edok = bmesh_disk_validate(valence1, ov->e, ov);
  1103. BMESH_ASSERT(edok != FALSE);
  1104. edok = bmesh_disk_validate(valence2, tv->e, tv);
  1105. BMESH_ASSERT(edok != FALSE);
  1106. edok = bmesh_disk_validate(2, nv->e, nv);
  1107. BMESH_ASSERT(edok != FALSE);
  1108. /* Split the radial cycle if present */
  1109. nextl = e->l;
  1110. e->l = NULL;
  1111. if (nextl) {
  1112. BMLoop *nl, *l;
  1113. int radlen = bmesh_radial_length(nextl);
  1114. int first1 = 0, first2 = 0;
  1115. /* Take the next loop. Remove it from radial. Split it. Append to appropriate radials */
  1116. while (nextl) {
  1117. l = nextl;
  1118. l->f->len++;
  1119. nextl = nextl != nextl->radial_next ? nextl->radial_next : NULL;
  1120. bmesh_radial_loop_remove(l, NULL);
  1121. nl = bm_loop_create(bm, NULL, NULL, l->f, l);
  1122. nl->prev = l;
  1123. nl->next = (l->next);
  1124. nl->prev->next = nl;
  1125. nl->next->prev = nl;
  1126. nl->v = nv;
  1127. /* assign the correct edge to the correct loop */
  1128. if (bmesh_verts_in_edge(nl->v, nl->next->v, e)) {
  1129. nl->e = e;
  1130. l->e = ne;
  1131. /* append l into ne's rad cycle */
  1132. if (!first1) {
  1133. first1 = 1;
  1134. l->radial_next = l->radial_prev = NULL;
  1135. }
  1136. if (!first2) {
  1137. first2 = 1;
  1138. l->radial_next = l->radial_prev = NULL;
  1139. }
  1140. bmesh_radial_append(nl->e, nl);
  1141. bmesh_radial_append(l->e, l);
  1142. }
  1143. else if (bmesh_verts_in_edge(nl->v, nl->next->v, ne)) {
  1144. nl->e = ne;
  1145. l->e = e;
  1146. /* append l into ne's rad cycle */
  1147. if (!first1) {
  1148. first1 = 1;
  1149. l->radial_next = l->radial_prev = NULL;
  1150. }
  1151. if (!first2) {
  1152. first2 = 1;
  1153. l->radial_next = l->radial_prev = NULL;
  1154. }
  1155. bmesh_radial_append(nl->e, nl);
  1156. bmesh_radial_append(l->e, l);
  1157. }
  1158. }
  1159. /* verify length of radial cycle */
  1160. edok = bmesh_radial_validate(radlen, e->l);
  1161. BMESH_ASSERT(edok != FALSE);
  1162. edok = bmesh_radial_validate(radlen, ne->l);
  1163. BMESH_ASSERT(edok != FALSE);
  1164. /* verify loop->v and loop->next->v pointers for e */
  1165. for (i = 0, l = e->l; i < radlen; i++, l = l->radial_next) {
  1166. BMESH_ASSERT(l->e == e);
  1167. //BMESH_ASSERT(l->radial_next == l);
  1168. BMESH_ASSERT(!(l->prev->e != ne && l->next->e != ne));
  1169. edok = bmesh_verts_in_edge(l->v, l->next->v, e);
  1170. BMESH_ASSERT(edok != FALSE);
  1171. BMESH_ASSERT(l->v != l->next->v);
  1172. BMESH_ASSERT(l->e != l->next->e);
  1173. /* verify loop cycle for kloop-> */
  1174. BM_CHECK_ELEMENT(l);
  1175. BM_CHECK_ELEMENT(l->v);
  1176. BM_CHECK_ELEMENT(l->e);
  1177. BM_CHECK_ELEMENT(l->f);
  1178. }
  1179. /* verify loop->v and loop->next->v pointers for ne */
  1180. for (i = 0, l = ne->l; i < radlen; i++, l = l->radial_next) {
  1181. BMESH_ASSERT(l->e == ne);
  1182. // BMESH_ASSERT(l->radial_next == l);
  1183. BMESH_ASSERT(!(l->prev->e != e && l->next->e != e));
  1184. edok = bmesh_verts_in_edge(l->v, l->next->v, ne);
  1185. BMESH_ASSERT(edok != FALSE);
  1186. BMESH_ASSERT(l->v != l->next->v);
  1187. BMESH_ASSERT(l->e != l->next->e);
  1188. BM_CHECK_ELEMENT(l);
  1189. BM_CHECK_ELEMENT(l->v);
  1190. BM_CHECK_ELEMENT(l->e);
  1191. BM_CHECK_ELEMENT(l->f);
  1192. }
  1193. }
  1194. BM_CHECK_ELEMENT(ne);
  1195. BM_CHECK_ELEMENT(nv);
  1196. BM_CHECK_ELEMENT(ov);
  1197. BM_CHECK_ELEMENT(e);
  1198. BM_CHECK_ELEMENT(tv);
  1199. if (r_e) *r_e = ne;
  1200. return nv;
  1201. }
  1202. /**
  1203. * \brief Join Edge Kill Vert (JEKV)
  1204. *
  1205. * Takes an edge \a ke and pointer to one of its vertices \a kv
  1206. * and collapses the edge on that vertex.
  1207. *
  1208. * \par Examples:
  1209. *
  1210. * Before: OE KE
  1211. * ------- -------
  1212. * | || |
  1213. * OV KV TV
  1214. *
  1215. *
  1216. * After: OE
  1217. * ---------------
  1218. * | |
  1219. * OV TV
  1220. *
  1221. * \par Restrictions:
  1222. * KV is a vertex that must have a valance of exactly two. Furthermore
  1223. * both edges in KV's disk cycle (OE and KE) must be unique (no double edges).
  1224. *
  1225. * \return The resulting edge, NULL for failure.
  1226. *
  1227. * \note This euler has the possibility of creating
  1228. * faces with just 2 edges. It is up to the caller to decide what to do with
  1229. * these faces.
  1230. */
  1231. BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_double)
  1232. {
  1233. BMEdge *oe;
  1234. BMVert *ov, *tv;
  1235. BMLoop *killoop, *l;
  1236. int len, radlen = 0, halt = 0, i, valence1, valence2, edok;
  1237. if (bmesh_vert_in_edge(ke, kv) == 0) {
  1238. return NULL;
  1239. }
  1240. len = bmesh_disk_count(kv);
  1241. if (len == 2) {
  1242. oe = bmesh_disk_edge_next(ke, kv);
  1243. tv = bmesh_edge_other_vert_get(ke, kv);
  1244. ov = bmesh_edge_other_vert_get(oe, kv);
  1245. halt = bmesh_verts_in_edge(kv, tv, oe); /* check for double edge */
  1246. if (halt) {
  1247. return NULL;
  1248. }
  1249. else {
  1250. BMEdge *e_splice;
  1251. /* For verification later, count valence of ov and t */
  1252. valence1 = bmesh_disk_count(ov);
  1253. valence2 = bmesh_disk_count(tv);
  1254. if (check_edge_double) {
  1255. e_splice = BM_edge_exists(tv, ov);
  1256. }
  1257. /* remove oe from kv's disk cycle */
  1258. bmesh_disk_edge_remove(oe, kv);
  1259. /* relink oe->kv to be oe->tv */
  1260. bmesh_edge_swapverts(oe, kv, tv);
  1261. /* append oe to tv's disk cycle */
  1262. bmesh_disk_edge_append(oe, tv);
  1263. /* remove ke from tv's disk cycle */
  1264. bmesh_disk_edge_remove(ke, tv);
  1265. /* deal with radial cycle of ke */
  1266. radlen = bmesh_radial_length(ke->l);
  1267. if (ke->l) {
  1268. /* first step, fix the neighboring loops of all loops in ke's radial cycle */
  1269. for (i = 0, killoop = ke->l; i < radlen; i++, killoop = killoop->radial_next) {
  1270. /* relink loops and fix vertex pointer */
  1271. if (killoop->next->v == kv) {
  1272. killoop->next->v = tv;
  1273. }
  1274. killoop->next->prev = killoop->prev;
  1275. killoop->prev->next = killoop->next;
  1276. if (BM_FACE_FIRST_LOOP(killoop->f) == killoop) {
  1277. BM_FACE_FIRST_LOOP(killoop->f) = killoop->next;
  1278. }
  1279. killoop->next = NULL;
  1280. killoop->prev = NULL;
  1281. /* fix len attribute of face */
  1282. killoop->f->len--;
  1283. }
  1284. /* second step, remove all the hanging loops attached to ke */
  1285. radlen = bmesh_radial_length(ke->l);
  1286. if (LIKELY(radlen)) {
  1287. BMLoop **loops = NULL;
  1288. BLI_array_fixedstack_declare(loops, BM_NGON_STACK_SIZE, radlen, __func__);
  1289. killoop = ke->l;
  1290. /* this should be wrapped into a bme_free_radial function to be used by bmesh_KF as well... */
  1291. for (i = 0; i < radlen; i++) {
  1292. loops[i] = killoop;
  1293. killoop = killoop->radial_next;
  1294. }
  1295. for (i = 0; i < radlen; i++) {
  1296. bm->totloop--;
  1297. BLI_mempool_free(bm->lpool, loops[i]);
  1298. }
  1299. BLI_array_fixedstack_free(loops);
  1300. }
  1301. /* Validate radial cycle of oe */
  1302. edok = bmesh_radial_validate(radlen, oe->l);
  1303. BMESH_ASSERT(edok != FALSE);
  1304. }
  1305. /* deallocate edg */
  1306. bm_kill_only_edge(bm, ke);
  1307. /* deallocate verte */
  1308. bm_kill_only_vert(bm, kv);
  1309. /* Validate disk cycle lengths of ov, tv are unchanged */
  1310. edok = bmesh_disk_validate(valence1, ov->e, ov);
  1311. BMESH_ASSERT(edok != FALSE);
  1312. edok = bmesh_disk_validate(valence2, tv->e, tv);
  1313. BMESH_ASSERT(edok != FALSE);
  1314. /* Validate loop cycle of all faces attached to oe */
  1315. for (i = 0, l = oe->l; i < radlen; i++, l = l->radial_next) {
  1316. BMESH_ASSERT(l->e == oe);
  1317. edok = bmesh_verts_in_edge(l->v, l->next->v, oe);
  1318. BMESH_ASSERT(edok != FALSE);
  1319. edok = bmesh_loop_validate(l->f);
  1320. BMESH_ASSERT(edok != FALSE);
  1321. BM_CHECK_ELEMENT(l);
  1322. BM_CHECK_ELEMENT(l->v);
  1323. BM_CHECK_ELEMENT(l->e);
  1324. BM_CHECK_ELEMENT(l->f);
  1325. }
  1326. if (check_edge_double) {
  1327. if (e_splice) {
  1328. /* removes e_splice */
  1329. BM_edge_splice(bm, e_splice, oe);
  1330. }
  1331. }
  1332. BM_CHECK_ELEMENT(ov);
  1333. BM_CHECK_ELEMENT(tv);
  1334. BM_CHECK_ELEMENT(oe);
  1335. return oe;
  1336. }
  1337. }
  1338. return NULL;
  1339. }
  1340. /**
  1341. * \brief Join Face Kill Edge (JFKE)
  1342. *
  1343. * Takes two faces joined by a single 2-manifold edge and fuses them together.
  1344. * The edge shared by the faces must not be connected to any other edges which have
  1345. * Both faces in its radial cycle
  1346. *
  1347. * \par Examples:
  1348. *
  1349. * A B
  1350. * +--------+ +--------+
  1351. * | | | |
  1352. * | f1 | | f1 |
  1353. * v1========v2 = Ok! v1==V2==v3 == Wrong!
  1354. * | f2 | | f2 |
  1355. * | | | |
  1356. * +--------+ +--------+
  1357. *
  1358. * In the example A, faces \a f1 and \a f2 are joined by a single edge,
  1359. * and the euler can safely be used.
  1360. * In example B however, \a f1 and \a f2 are joined by multiple edges and will produce an error.
  1361. * The caller in this case should call #bmesh_jekv on the extra edges
  1362. * before attempting to fuse \a f1 and \a f2.
  1363. *
  1364. * \note The order of arguments decides whether or not certain per-face attributes are present
  1365. * in the resultant face. For instance vertex winding, material index, smooth flags, etc are inherited
  1366. * from \a f1, not \a f2.
  1367. *
  1368. * \return A BMFace pointer
  1369. */
  1370. BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
  1371. {
  1372. BMLoop *l_iter, *f1loop = NULL, *f2loop = NULL;
  1373. int newlen = 0, i, f1len = 0, f2len = 0, edok;
  1374. /* can't join a face to itself */
  1375. if (f1 == f2) {
  1376. return NULL;
  1377. }
  1378. /* validate that edge is 2-manifold edge */
  1379. if (!BM_edge_is_manifold(e)) {
  1380. return NULL;
  1381. }
  1382. /* verify that e is in both f1 and f2 */
  1383. f1len = f1->len;
  1384. f2len = f2->len;
  1385. if (!((f1loop = BM_face_edge_share_loop(f1, e)) &&
  1386. (f2loop = BM_face_edge_share_loop(f2, e))))
  1387. {
  1388. return NULL;
  1389. }
  1390. /* validate direction of f2's loop cycle is compatible */
  1391. if (f1loop->v == f2loop->v) {
  1392. return NULL;
  1393. }
  1394. /* validate that for each face, each vertex has another edge in its disk cycle that is
  1395. * not e, and not shared. */
  1396. if (bmesh_radial_face_find(f1loop->next->e, f2) ||
  1397. bmesh_radial_face_find(f1loop->prev->e, f2) ||
  1398. bmesh_radial_face_find(f2loop->next->e, f1) ||
  1399. bmesh_radial_face_find(f2loop->prev->e, f1) )
  1400. {
  1401. return NULL;
  1402. }
  1403. /* validate only one shared edge */
  1404. if (BM_face_share_edge_count(f1, f2) > 1) {
  1405. return NULL;
  1406. }
  1407. /* validate no internal join */
  1408. for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) {
  1409. BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG);
  1410. }
  1411. for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) {
  1412. BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG);
  1413. }
  1414. for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) {
  1415. if (l_iter != f1loop) {
  1416. BM_elem_flag_enable(l_iter->v, BM_ELEM_INTERNAL_TAG);
  1417. }
  1418. }
  1419. for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) {
  1420. if (l_iter != f2loop) {
  1421. /* as soon as a duplicate is found, bail out */
  1422. if (BM_elem_flag_test(l_iter->v, BM_ELEM_INTERNAL_TAG)) {
  1423. return NULL;
  1424. }
  1425. }
  1426. }
  1427. /* join the two loop */
  1428. f1loop->prev->next = f2loop->next;
  1429. f2loop->next->prev = f1loop->prev;
  1430. f1loop->next->prev = f2loop->prev;
  1431. f2loop->prev->next = f1loop->next;
  1432. /* if f1loop was baseloop, make f1loop->next the base. */
  1433. if (BM_FACE_FIRST_LOOP(f1) == f1loop)
  1434. BM_FACE_FIRST_LOOP(f1) = f1loop->next;
  1435. /* increase length of f1 */
  1436. f1->len += (f2->len - 2);
  1437. /* make sure each loop points to the proper face */
  1438. newlen = f1->len;
  1439. for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < newlen; i++, l_iter = l_iter->next)
  1440. l_iter->f = f1;
  1441. /* remove edge from the disk cycle of its two vertices */
  1442. bmesh_disk_edge_remove(f1loop->e, f1loop->e->v1);
  1443. bmesh_disk_edge_remove(f1loop->e, f1loop->e->v2);
  1444. /* deallocate edge and its two loops as well as f2 */
  1445. BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags);
  1446. BLI_mempool_free(bm->epool, f1loop->e);
  1447. bm->totedge--;
  1448. BLI_mempool_free(bm->lpool, f1loop);
  1449. bm->totloop--;
  1450. BLI_mempool_free(bm->lpool, f2loop);
  1451. bm->totloop--;
  1452. BLI_mempool_free(bm->toolflagpool, f2->oflags);
  1453. BLI_mempool_free(bm->fpool, f2);
  1454. bm->totface--;
  1455. /* account for both above */
  1456. bm->elem_index_dirty |= BM_EDGE | BM_FACE;
  1457. BM_CHECK_ELEMENT(f1);
  1458. /* validate the new loop cycle */
  1459. edok = bmesh_loop_validate(f1);
  1460. BMESH_ASSERT(edok != FALSE);
  1461. return f1;
  1462. }
  1463. /**
  1464. * \brief Splice Vert
  1465. *
  1466. * Merges two verts into one (\a v into \a vtarget).
  1467. *
  1468. * \return Success
  1469. */
  1470. int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *vtarget)
  1471. {
  1472. BMEdge *e;
  1473. BMLoop *l;
  1474. BMIter liter;
  1475. /* verts already spliced */
  1476. if (v == vtarget) {
  1477. return FALSE;
  1478. }
  1479. /* retarget all the loops of v to vtarget */
  1480. BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
  1481. l->v = vtarget;
  1482. }
  1483. /* move all the edges from v's disk to vtarget's disk */
  1484. while ((e = v->e)) {
  1485. bmesh_disk_edge_remove(e, v);
  1486. bmesh_edge_swapverts(e, v, vtarget);
  1487. bmesh_disk_edge_append(e, vtarget);
  1488. }
  1489. BM_CHECK_ELEMENT(v);
  1490. BM_CHECK_ELEMENT(vtarget);
  1491. /* v is unused now, and can be killed */
  1492. BM_vert_kill(bm, v);
  1493. return TRUE;
  1494. }
  1495. /**
  1496. * \brief Separate Vert
  1497. *
  1498. * Separates all disjoint fans that meet at a vertex, making a unique
  1499. * vertex for each region. returns an array of all resulting vertices.
  1500. *
  1501. * \note this is a low level function, bm_edge_separate needs to run on edges first
  1502. * or, the faces sharing verts must not be sharing edges for them to split at least.
  1503. *
  1504. * \return Success
  1505. */
  1506. int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len)
  1507. {
  1508. BMEdge **stack = NULL;
  1509. BLI_array_declare(stack);
  1510. BMVert **verts = NULL;
  1511. GHash *visithash;
  1512. BMIter eiter, liter;
  1513. BMLoop *l;
  1514. BMEdge *e;
  1515. int i, maxindex;
  1516. BMLoop *nl;
  1517. visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
  1518. maxindex = 0;
  1519. BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
  1520. if (BLI_ghash_haskey(visithash, e)) {
  1521. continue;
  1522. }
  1523. /* Prime the stack with this unvisited edge */
  1524. BLI_array_append(stack, e);
  1525. /* Considering only edges and faces incident on vertex v, walk
  1526. * the edges & faces and assign an index to each connected set */
  1527. while ((e = BLI_array_pop(stack))) {
  1528. BLI_ghash_insert(visithash, e, SET_INT_IN_POINTER(maxindex));
  1529. BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
  1530. nl = (l->v == v) ? l->prev : l->next;
  1531. if (!BLI_ghash_haskey(visithash, nl->e)) {
  1532. BLI_array_append(stack, nl->e);
  1533. }
  1534. }
  1535. }
  1536. maxindex++;
  1537. }
  1538. /* Make enough verts to split v for each group */
  1539. verts = MEM_callocN(sizeof(BMVert *) * maxindex, __func__);
  1540. verts[0] = v;
  1541. for (i = 1; i < maxindex; i++) {
  1542. verts[i] = BM_vert_create(bm, v->co, v);
  1543. }
  1544. /* Replace v with the new verts in each group */
  1545. #if 0
  1546. BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
  1547. /* call first since its faster then a hash lookup */
  1548. if (l->v != v) {
  1549. continue;
  1550. }
  1551. i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, l->e));
  1552. if (i == 0) {
  1553. continue;
  1554. }
  1555. /* Loops here should always refer to an edge that has v as an
  1556. * endpoint. For each appearance of this vert in a face, there
  1557. * will actually be two iterations: one for the loop heading
  1558. * towards vertex v, and another for the loop heading out from
  1559. * vertex v. Only need to swap the vertex on one of those times,
  1560. * on the outgoing loop. */
  1561. /* XXX - because this clobbers the iterator, this *whole* block is commented, see below */
  1562. l->v = verts[i];
  1563. }
  1564. #else
  1565. /* note: this is the same as the commented code above *except* that it doesn't break iterator
  1566. * by modifying data it loops over [#30632], this re-uses the 'stack' variable which is a bit
  1567. * bad practice but save alloc'ing a new array - note, the comment above is useful, keep it
  1568. * if you are tidying up code - campbell */
  1569. BLI_array_empty(stack);
  1570. BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
  1571. if (l->v == v) {
  1572. BLI_array_append(stack, (BMEdge *)l);
  1573. }
  1574. }
  1575. while ((l = (BMLoop *)(BLI_array_pop(stack)))) {
  1576. if ((i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, l->e)))) {
  1577. l->v = verts[i];
  1578. }
  1579. }
  1580. #endif
  1581. BLI_array_free(stack);
  1582. BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
  1583. i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, e));
  1584. if (i == 0) {
  1585. continue;
  1586. }
  1587. BLI_assert(e->v1 == v || e->v2 == v);
  1588. bmesh_disk_edge_remove(e, v);
  1589. bmesh_edge_swapverts(e, v, verts[i]);
  1590. bmesh_disk_edge_append(e, verts[i]);
  1591. }
  1592. BLI_ghash_free(visithash, NULL, NULL);
  1593. for (i = 0; i < maxindex; i++) {
  1594. BM_CHECK_ELEMENT(verts[i]);
  1595. }
  1596. if (r_vout_len != NULL) {
  1597. *r_vout_len = maxindex;
  1598. }
  1599. if (r_vout != NULL) {
  1600. *r_vout = verts;
  1601. }
  1602. else {
  1603. MEM_freeN(verts);
  1604. }
  1605. return TRUE;
  1606. }
  1607. /**
  1608. * High level function which wraps both #bm_vert_separate and #bm_edge_separate
  1609. */
  1610. int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
  1611. BMEdge **e_in, int e_in_len)
  1612. {
  1613. int i;
  1614. for (i = 0; i < e_in_len; i++) {
  1615. BMEdge *e = e_in[i];
  1616. if (e->l && BM_vert_in_edge(e, v)) {
  1617. bmesh_edge_separate(bm, e, e->l);
  1618. }
  1619. }
  1620. return bmesh_vert_separate(bm, v, r_vout, r_vout_len);
  1621. }
  1622. /**
  1623. * \brief Splice Edge
  1624. *
  1625. * Splice two unique edges which share the same two vertices into one edge.
  1626. *
  1627. * \return Success
  1628. *
  1629. * \note Edges must already have the same vertices.
  1630. */
  1631. int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget)
  1632. {
  1633. BMLoop *l;
  1634. if (!BM_vert_in_edge(e, etarget->v1) || !BM_vert_in_edge(e, etarget->v2)) {
  1635. /* not the same vertices can't splice */
  1636. return FALSE;
  1637. }
  1638. while (e->l) {
  1639. l = e->l;
  1640. BLI_assert(BM_vert_in_edge(etarget, l->v));
  1641. BLI_assert(BM_vert_in_edge(etarget, l->next->v));
  1642. bmesh_radial_loop_remove(l, e);
  1643. bmesh_radial_append(etarget, l);
  1644. }
  1645. BLI_assert(bmesh_radial_length(e->l) == 0);
  1646. BM_CHECK_ELEMENT(e);
  1647. BM_CHECK_ELEMENT(etarget);
  1648. /* removes from disks too */
  1649. BM_edge_kill(bm, e);
  1650. return TRUE;
  1651. }
  1652. /**
  1653. * \brief Separate Edge
  1654. *
  1655. * Separates a single edge into two edge: the original edge and
  1656. * a new edge that has only \a l_sep in its radial.
  1657. *
  1658. * \return Success
  1659. *
  1660. * \note Does nothing if \a l_sep is already the only loop in the
  1661. * edge radial.
  1662. */
  1663. int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep)
  1664. {
  1665. BMEdge *ne;
  1666. int radlen;
  1667. BLI_assert(l_sep->e == e);
  1668. BLI_assert(e->l);
  1669. radlen = bmesh_radial_length(e->l);
  1670. if (radlen < 2) {
  1671. /* no cut required */
  1672. return TRUE;
  1673. }
  1674. if (l_sep == e->l) {
  1675. e->l = l_sep->radial_next;
  1676. }
  1677. ne = BM_edge_create(bm, e->v1, e->v2, e, FALSE);
  1678. bmesh_radial_loop_remove(l_sep, e);
  1679. bmesh_radial_append(ne, l_sep);
  1680. l_sep->e = ne;
  1681. BLI_assert(bmesh_radial_length(e->l) == radlen - 1);
  1682. BLI_assert(bmesh_radial_length(ne->l) == 1);
  1683. BM_CHECK_ELEMENT(ne);
  1684. BM_CHECK_ELEMENT(e);
  1685. return TRUE;
  1686. }
  1687. /**
  1688. * \brief Unglue Region Make Vert (URMV)
  1689. *
  1690. * Disconnects a face from its vertex fan at loop \a sl
  1691. *
  1692. * \return The newly created BMVert
  1693. */
  1694. BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl)
  1695. {
  1696. BMVert **vtar;
  1697. int len, i;
  1698. BMVert *nv = NULL;
  1699. BMVert *sv = sl->v;
  1700. /* peel the face from the edge radials on both sides of the
  1701. * loop vert, disconnecting the face from its fan */
  1702. bmesh_edge_separate(bm, sl->e, sl);
  1703. bmesh_edge_separate(bm, sl->prev->e, sl->prev);
  1704. if (bmesh_disk_count(sv) == 2) {
  1705. /* If there are still only two edges out of sv, then
  1706. * this whole URMV was just a no-op, so exit now. */
  1707. return sv;
  1708. }
  1709. /* Update the disk start, so that v->e points to an edge
  1710. * not touching the split loop. This is so that BM_vert_split
  1711. * will leave the original sv on some *other* fan (not the
  1712. * one-face fan that holds the unglue face). */
  1713. while (sv->e == sl->e || sv->e == sl->prev->e) {
  1714. sv->e = bmesh_disk_edge_next(sv->e, sv);
  1715. }
  1716. /* Split all fans connected to the vert, duplicating it for
  1717. * each fans. */
  1718. bmesh_vert_separate(bm, sv, &vtar, &len);
  1719. /* There should have been at least two fans cut apart here,
  1720. * otherwise the early exit would have kicked in. */
  1721. BLI_assert(len >= 2);
  1722. nv = sl->v;
  1723. /* Desired result here is that a new vert should always be
  1724. * created for the unglue face. This is so we can glue any
  1725. * extras back into the original vert. */
  1726. BLI_assert(nv != sv);
  1727. BLI_assert(sv == vtar[0]);
  1728. /* If there are more than two verts as a result, glue together
  1729. * all the verts except the one this URMV intended to create */
  1730. if (len > 2) {
  1731. for (i = 0; i < len; i++) {
  1732. if (vtar[i] == nv) {
  1733. break;
  1734. }
  1735. }
  1736. if (i != len) {
  1737. /* Swap the single vert that was needed for the
  1738. * unglue into the last array slot */
  1739. SWAP(BMVert *, vtar[i], vtar[len - 1]);
  1740. /* And then glue the rest back together */
  1741. for (i = 1; i < len - 1;

Large files files are truncated, but you can click here to view the full file