PageRenderTime 58ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/blender-2.63a/source/blender/bmesh/operators/bmo_create.c

#
C | 1487 lines | 1077 code | 291 blank | 119 comment | 248 complexity | 7e97211f23fe200d2757cfaa91d3bcdd 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
  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.
  19. *
  20. * ***** END GPL LICENSE BLOCK *****
  21. */
  22. /** \file blender/bmesh/operators/bmo_create.c
  23. * \ingroup bmesh
  24. */
  25. #include "MEM_guardedalloc.h"
  26. #include "BLI_heap.h"
  27. #include "BLI_listbase.h"
  28. #include "BLI_math.h"
  29. #include "BLI_array.h"
  30. #include "BLI_smallhash.h"
  31. #include "BLI_rand.h"
  32. #include "bmesh.h"
  33. #include "intern/bmesh_operators_private.h" /* own include */
  34. #define EDGE_MARK 1
  35. #define EDGE_VIS 2
  36. #define FACE_NEW 1
  37. #define ELE_NEW 1
  38. #define ELE_OUT 2
  39. #define ELE_ORIG 4
  40. #define FACE_IGNORE 16
  41. typedef struct EPathNode {
  42. struct EPathNode *next, *prev;
  43. BMVert *v;
  44. BMEdge *e;
  45. BMEdge *cure;
  46. } EPathNode;
  47. typedef struct EPath {
  48. ListBase nodes;
  49. float weight;
  50. int group;
  51. } EPath;
  52. typedef struct PathBase {
  53. BLI_mempool *nodepool, *pathpool;
  54. } PathBase;
  55. typedef struct EdgeData {
  56. int tag;
  57. int ftag;
  58. BMDiskLink v1_disk_link, v2_disk_link;
  59. } EdgeData;
  60. typedef struct VertData {
  61. BMEdge *e;
  62. float no[3], offco[3], sco[3]; /* offco is vertex coordinate slightly offset randomly */
  63. int tag;
  64. } VertData;
  65. static int count_edge_faces(BMesh *bm, BMEdge *e);
  66. /**** rotation system code * */
  67. BLI_INLINE BMDiskLink *rs_edge_link_get(BMEdge *e, BMVert *v, EdgeData *e_data)
  68. {
  69. return v == ((BMEdge *)e)->v1 ? &(((EdgeData *)e_data)->v1_disk_link) :
  70. &(((EdgeData *)e_data)->v2_disk_link) ;
  71. }
  72. static int rotsys_append_edge(BMEdge *e, BMVert *v,
  73. EdgeData *edata, VertData *vdata)
  74. {
  75. EdgeData *ed = &edata[BM_elem_index_get(e)];
  76. VertData *vd = &vdata[BM_elem_index_get(v)];
  77. if (!vd->e) {
  78. Link *e1 = (Link *)rs_edge_link_get(e, v, ed);
  79. vd->e = e;
  80. e1->next = e1->prev = (Link *)e;
  81. }
  82. else {
  83. BMDiskLink *dl1, *dl2, *dl3;
  84. EdgeData *ved = &edata[BM_elem_index_get(vd->e)];
  85. dl1 = rs_edge_link_get(e, v, ed);
  86. dl2 = rs_edge_link_get(vd->e, v, ved);
  87. dl3 = dl2->prev ? rs_edge_link_get(dl2->prev, v, &edata[BM_elem_index_get(dl2->prev)]) : NULL;
  88. dl1->next = vd->e;
  89. dl1->prev = dl2->prev;
  90. dl2->prev = e;
  91. if (dl3) {
  92. dl3->next = e;
  93. }
  94. }
  95. return TRUE;
  96. }
  97. static void UNUSED_FUNCTION(rotsys_remove_edge)(BMEdge *e, BMVert *v,
  98. EdgeData *edata, VertData *vdata)
  99. {
  100. EdgeData *ed = edata + BM_elem_index_get(e);
  101. VertData *vd = vdata + BM_elem_index_get(v);
  102. BMDiskLink *e1, *e2;
  103. e1 = rs_edge_link_get(e, v, ed);
  104. if (e1->prev) {
  105. e2 = rs_edge_link_get(e1->prev, v, ed);
  106. e2->next = e1->next;
  107. }
  108. if (e1->next) {
  109. e2 = rs_edge_link_get(e1->next, v, ed);
  110. e2->prev = e1->prev;
  111. }
  112. if (vd->e == e)
  113. vd->e = (e != e1->next) ? e1->next : NULL;
  114. e1->next = e1->prev = NULL;
  115. }
  116. static BMEdge *rotsys_nextedge(BMEdge *e, BMVert *v,
  117. EdgeData *edata, VertData *UNUSED(vdata))
  118. {
  119. if (v == e->v1)
  120. return edata[BM_elem_index_get(e)].v1_disk_link.next;
  121. if (v == e->v2)
  122. return edata[BM_elem_index_get(e)].v2_disk_link.next;
  123. return NULL;
  124. }
  125. static BMEdge *rotsys_prevedge(BMEdge *e, BMVert *v,
  126. EdgeData *edata, VertData *UNUSED(vdata))
  127. {
  128. if (v == e->v1)
  129. return edata[BM_elem_index_get(e)].v1_disk_link.prev;
  130. if (v == e->v2)
  131. return edata[BM_elem_index_get(e)].v2_disk_link.prev;
  132. return NULL;
  133. }
  134. static void rotsys_reverse(BMEdge *UNUSED(e), BMVert *v, EdgeData *edata, VertData *vdata)
  135. {
  136. BMEdge **edges = NULL;
  137. BMEdge *e_first;
  138. BMEdge *e;
  139. BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE);
  140. int i, totedge;
  141. e = e_first = vdata[BM_elem_index_get(v)].e;
  142. do {
  143. BLI_array_append(edges, e);
  144. e = rotsys_nextedge(e, v, edata, vdata);
  145. } while (e != e_first);
  146. totedge = BLI_array_count(edges);
  147. for (i = 0; i < totedge / 2; i++) {
  148. SWAP(BMEdge *, edges[i], edges[totedge - 1 - i]);
  149. }
  150. vdata[BM_elem_index_get(v)].e = NULL;
  151. for (i = 0; i < totedge; i++) {
  152. rotsys_append_edge(edges[i], v, edata, vdata);
  153. }
  154. BLI_array_free(edges);
  155. }
  156. static int UNUSED_FUNCTION(rotsys_count)(BMVert *v, EdgeData *edata, VertData *vdata)
  157. {
  158. BMEdge *e = vdata[BM_elem_index_get(v)].e;
  159. int i = 0;
  160. if (!e)
  161. return 0;
  162. do {
  163. if (!e)
  164. return 0;
  165. e = rotsys_nextedge(e, v, edata, vdata);
  166. if (i >= (1 << 20)) {
  167. printf("bmesh error: infinite loop in disk cycle!\n");
  168. return 0;
  169. }
  170. i += 1;
  171. } while (e != vdata[BM_elem_index_get(v)].e);
  172. return i;
  173. }
  174. static int UNUSED_FUNCTION(rotsys_fill_faces)(BMesh *bm, EdgeData *edata, VertData *vdata)
  175. {
  176. BMIter iter;
  177. BMEdge *e, **edges = NULL;
  178. BLI_array_declare(edges);
  179. BMVert *v, **verts = NULL;
  180. BMFace *f;
  181. BLI_array_declare(verts);
  182. SmallHash visithash, *hash = &visithash;
  183. int i;
  184. BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
  185. BMEdge *e2, *starte;
  186. BMVert *startv;
  187. int rad, ok;
  188. rad = count_edge_faces(bm, e);
  189. if (rad < 2) {
  190. starte = e;
  191. }
  192. else {
  193. continue;
  194. }
  195. /* do two passes, going forward then backward */
  196. for (i = 0; i < 2; i++) {
  197. BLI_smallhash_init(hash);
  198. BLI_array_empty(verts);
  199. BLI_array_empty(edges);
  200. startv = v = starte->v1;
  201. e2 = starte;
  202. ok = 1;
  203. if (!v || !e2)
  204. continue;
  205. do {
  206. if (BLI_smallhash_haskey(hash, (intptr_t)e2) ||
  207. BLI_smallhash_haskey(hash, (intptr_t)v))
  208. {
  209. ok = 0;
  210. break;
  211. }
  212. BLI_array_append(verts, v);
  213. BLI_array_append(edges, e2);
  214. BLI_smallhash_insert(hash, (intptr_t)e2, NULL);
  215. v = BM_edge_other_vert(e2, v);
  216. e2 = i ? rotsys_prevedge(e2, v, edata, vdata) : rotsys_nextedge(e2, v, edata, vdata);
  217. } while (e2 != starte && v != startv);
  218. BLI_smallhash_release(hash);
  219. if (!ok || BLI_array_count(edges) < 3)
  220. continue;
  221. f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), TRUE);
  222. if (!f)
  223. continue;
  224. }
  225. }
  226. return 0;
  227. }
  228. static void rotsys_make_consistent(BMesh *bm, EdgeData *edata, VertData *vdata)
  229. {
  230. BMIter iter;
  231. BMEdge *e;
  232. BMVert *v, **stack = NULL;
  233. BLI_array_declare(stack);
  234. int i;
  235. for (i = 0; i < bm->totvert; i++) {
  236. vdata[i].tag = 0;
  237. }
  238. while (1) {
  239. VertData *vd;
  240. BMVert *startv = NULL;
  241. float dis;
  242. v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL);
  243. for (i = 0; i < bm->totvert; i++, BM_iter_step(&iter)) {
  244. vd = vdata + BM_elem_index_get(v);
  245. if (vd->tag)
  246. continue;
  247. if (!startv || dot_v3v3(vd->offco, vd->offco) > dis) {
  248. dis = dot_v3v3(vd->offco, vd->offco);
  249. startv = v;
  250. }
  251. }
  252. if (!startv)
  253. break;
  254. vd = vdata + BM_elem_index_get(startv);
  255. BLI_array_empty(stack);
  256. BLI_array_append(stack, startv);
  257. vd->tag = 1;
  258. while (BLI_array_count(stack)) {
  259. v = BLI_array_pop(stack);
  260. vd = vdata + BM_elem_index_get(v);
  261. if (!vd->e)
  262. continue;
  263. e = vd->e;
  264. do {
  265. BMVert *v2 = BM_edge_other_vert(e, v);
  266. VertData *vd2 = vdata + BM_elem_index_get(v2);
  267. if (dot_v3v3(vd->no, vd2->no) < 0.0f + FLT_EPSILON * 2) {
  268. rotsys_reverse(e, v2, edata, vdata);
  269. mul_v3_fl(vd2->no, -1.0f);
  270. }
  271. if (!vd2->tag) {
  272. BLI_array_append(stack, v2);
  273. vd2->tag = 1;
  274. }
  275. e = rotsys_nextedge(e, v, edata, vdata);
  276. } while (e != vd->e);
  277. }
  278. }
  279. BLI_array_free(stack);
  280. }
  281. static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata)
  282. {
  283. BMIter iter;
  284. BMEdge *e;
  285. BMEdge **edges = NULL;
  286. BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE);
  287. BMVert *v;
  288. /* BMVert **verts = NULL; */
  289. /* BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); */ /* UNUSE */
  290. int i;
  291. #define SIGN(n) ((n)<0.0f)
  292. BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
  293. BMIter eiter;
  294. float no[3], cent[3];
  295. int j, k = 0, totedge = 0;
  296. if (BM_elem_index_get(v) == -1)
  297. continue;
  298. BLI_array_empty(edges);
  299. BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
  300. if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
  301. BLI_array_append(edges, e);
  302. totedge++;
  303. }
  304. }
  305. copy_v3_v3(cent, v->co);
  306. zero_v3(no);
  307. for (i = 0; i < totedge; i++) {
  308. BMEdge *e1, *e2;
  309. float cno[3], vec1[3], vec2[3];
  310. e1 = edges[i];
  311. e2 = edges[(i + 1) % totedge];
  312. sub_v3_v3v3(vec1, (BM_edge_other_vert(e1, v))->co, v->co);
  313. sub_v3_v3v3(vec2, (BM_edge_other_vert(e2, v))->co, v->co);
  314. cross_v3_v3v3(cno, vec1, vec2);
  315. normalize_v3(cno);
  316. if (i && dot_v3v3(cno, no) < 0.0f + FLT_EPSILON * 10)
  317. mul_v3_fl(cno, -1.0f);
  318. add_v3_v3(no, cno);
  319. normalize_v3(no);
  320. }
  321. /* generate plane-flattened coordinates */
  322. for (i = 0; i < totedge; i++) {
  323. BMEdge *e1;
  324. BMVert *v2;
  325. float cvec[3], vec1[3];
  326. e1 = edges[i];
  327. v2 = BM_edge_other_vert(e1, v);
  328. sub_v3_v3v3(vec1, v2->co, v->co);
  329. cross_v3_v3v3(cvec, vec1, no);
  330. cross_v3_v3v3(vec1, cvec, no);
  331. normalize_v3(vec1);
  332. mul_v3_fl(vec1, len_v3v3(v2->co, v->co));
  333. add_v3_v3(vec1, v->co);
  334. copy_v3_v3(vdata[BM_elem_index_get(v2)].sco, vec1);
  335. }
  336. BLI_srandom(0);
  337. /* first, ensure no 0 or 180 angles between adjacent
  338. * (and that adjacent's adjacent) edges */
  339. for (i = 0, k = 0; i < totedge; i++) {
  340. BMEdge *e1, *e2, *e3 = NULL;
  341. BMVert *v1, *v2, *v3;
  342. VertData *vd1, *vd2, *vd3;
  343. float vec1[3], vec2[3], vec3[3], size;
  344. int s1, s2, s3;
  345. if (totedge < 3)
  346. continue;
  347. e1 = edges[(i + totedge - 1) % totedge];
  348. e2 = edges[i];
  349. e3 = edges[(i + 1) % totedge];
  350. v1 = BM_edge_other_vert(e1, v);
  351. v2 = BM_edge_other_vert(e2, v);
  352. v3 = BM_edge_other_vert(e3, v);
  353. vd1 = vdata + BM_elem_index_get(v1);
  354. vd2 = vdata + BM_elem_index_get(v2);
  355. vd3 = vdata + BM_elem_index_get(v3);
  356. sub_v3_v3v3(vec1, vd1->sco, cent);
  357. sub_v3_v3v3(vec2, vd2->sco, cent);
  358. sub_v3_v3v3(vec3, vd3->sco, cent);
  359. size = (len_v3(vec1) + len_v3(vec3)) * 0.01f;
  360. normalize_v3(vec1); normalize_v3(vec2); normalize_v3(vec3);
  361. #ifdef STRAIGHT
  362. #undef STRAIGHT
  363. #endif
  364. #define STRAIGHT(vec11, vec22) (fabsf(dot_v3v3((vec11), (vec22))) > 1.0f - ((float)FLT_EPSILON * 1000.0f))
  365. s1 = STRAIGHT(vec1, vec2); s2 = STRAIGHT(vec2, vec3); s3 = STRAIGHT(vec1, vec3);
  366. if (s1 || s2 || s3) {
  367. copy_v3_v3(cent, v->co);
  368. for (j = 0; j < 3; j++) {
  369. float fac = (BLI_frand() - 0.5f) * size;
  370. cent[j] += fac;
  371. }
  372. if (k < 2000) {
  373. i = 0;
  374. k++;
  375. continue;
  376. }
  377. else {
  378. k++;
  379. continue;
  380. }
  381. }
  382. }
  383. copy_v3_v3(vdata[BM_elem_index_get(v)].offco, cent);
  384. //copy_v3_v3(v->co, cent);
  385. /* now, sort edges so the triangle fan of all edges
  386. * has a consistent normal. this is the same as
  387. * sorting by polar coordinates along a group normal */
  388. for (j = 0; j < totedge; j++) {
  389. for (i = 0; i < totedge; i++) {
  390. BMEdge *e1, *e2, *e3 = NULL;
  391. BMVert *v1, *v2, *v3;
  392. VertData *vd1, *vd2, *vd3;
  393. float vec1[3], vec2[3], vec3[3], n1[3], n2[3], n3[3];
  394. e1 = edges[(i + totedge - 1) % totedge];
  395. e2 = edges[i];
  396. e3 = edges[(i + 1) % totedge];
  397. v1 = BM_edge_other_vert(e1, v);
  398. v2 = BM_edge_other_vert(e2, v);
  399. v3 = BM_edge_other_vert(e3, v);
  400. vd1 = vdata + BM_elem_index_get(v1);
  401. vd2 = vdata + BM_elem_index_get(v2);
  402. vd3 = vdata + BM_elem_index_get(v3);
  403. sub_v3_v3v3(vec1, vd1->sco, cent);
  404. sub_v3_v3v3(vec2, vd2->sco, cent);
  405. sub_v3_v3v3(vec3, vd3->sco, cent);
  406. cross_v3_v3v3(n1, vec1, vec2);
  407. cross_v3_v3v3(n2, vec2, vec3);
  408. cross_v3_v3v3(n3, vec1, vec3);
  409. /* this case happens often enough and probably not worth bothering users with,
  410. * maybe enable for debugging code but not for everyday use - campbell */
  411. #if 0
  412. /* Other way to determine if two vectors approach are (nearly) parallel: the
  413. * cross product of the two vectors will approach zero */
  414. {
  415. int s1, s2, s3;
  416. s1 = (dot_v3v3(n1, n1) < (0.0f + FLT_EPSILON * 10));
  417. s2 = (dot_v3v3(n2, n2) < (0.0f + FLT_EPSILON * 10));
  418. s3 = (totedge < 3) ? 0 : (dot_v3v3(n3, n3) < (0.0f + FLT_EPSILON * 10));
  419. if (s1 || s2 || s3) {
  420. fprintf(stderr, "%s: s1: %d, s2: %d, s3: %dx (bmesh internal error)\n", __func__, s1, s2, s3);
  421. }
  422. }
  423. #endif
  424. normalize_v3(n1); normalize_v3(n2); normalize_v3(n3);
  425. if (dot_v3v3(n1, n2) < 0.0f) {
  426. if (dot_v3v3(n1, n3) >= 0.0f + FLT_EPSILON * 10) {
  427. SWAP(BMEdge *, edges[i], edges[(i + 1) % totedge]);
  428. }
  429. else {
  430. SWAP(BMEdge *, edges[(i + totedge - 1) % totedge], edges[(i + 1) % totedge]);
  431. SWAP(BMEdge *, edges[i], edges[(i + 1) % totedge]);
  432. }
  433. }
  434. }
  435. }
  436. #undef STRAIGHT
  437. zero_v3(no);
  438. /* yay, edges are sorted */
  439. for (i = 0; i < totedge; i++) {
  440. BMEdge *e1 = edges[i], *e2 = edges[(i + 1) % totedge];
  441. float eno[3];
  442. normal_tri_v3(eno, BM_edge_other_vert(e1, v)->co, v->co, BM_edge_other_vert(e2, v)->co);
  443. add_v3_v3(no, eno);
  444. rotsys_append_edge(edges[i], v, edata, vdata);
  445. }
  446. normalize_v3(no);
  447. copy_v3_v3(vdata[BM_elem_index_get(v)].no, no);
  448. }
  449. /* now, make sure rotation system is topologically consistent
  450. * (e.g. vert normals consistently point either inside or outside) */
  451. rotsys_make_consistent(bm, edata, vdata);
  452. //rotsys_fill_faces(bm, edata, vdata);
  453. #if 0
  454. /* create visualizing geometr */
  455. BMVert *lastv;
  456. BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
  457. BMVert *v2;
  458. BMFace *f;
  459. int totedge = BM_vert_edge_count(v);
  460. if (BM_elem_index_get(v) == -1)
  461. continue;
  462. //cv = BM_vert_create(bm, cent, v);
  463. //BM_elem_index_set(cv, -1); /* set_dirty! */
  464. i = 0;
  465. e = vdata[BM_elem_index_get(v)].e;
  466. lastv = NULL;
  467. do {
  468. BMEdge *e2;
  469. BMVert *v2;
  470. float f = ((float)i / (float)totedge) * 0.35 + 0.05;
  471. float co[3];
  472. if (!e)
  473. break;
  474. if (!BM_edge_other_vert(e, v))
  475. continue;
  476. sub_v3_v3v3(co, (BM_edge_other_vert(e, v))->co, vdata[BM_elem_index_get(v)].offco);
  477. mul_v3_fl(co, f);
  478. add_v3_v3(co, vdata[BM_elem_index_get(v)].offco);
  479. v2 = BM_vert_create(bm, co, NULL);
  480. BM_elem_index_set(v2, -1); /* set_dirty! */
  481. //BM_edge_create(bm, cv, v2, NULL, FALSE);
  482. BM_vert_select_set(bm, v2, TRUE);
  483. if (lastv) {
  484. e2 = BM_edge_create(bm, lastv, v2, NULL, FALSE);
  485. BM_edge_select_set(bm, e2, TRUE);
  486. }
  487. lastv = v2;
  488. e = rotsys_nextedge(e, v, edata, vdata);
  489. i++;
  490. } while (e != vdata[BM_elem_index_get(v)].e);
  491. }
  492. #endif
  493. BLI_array_free(edges);
  494. }
  495. static PathBase *edge_pathbase_new(void)
  496. {
  497. PathBase *pb = MEM_callocN(sizeof(PathBase), "PathBase");
  498. pb->nodepool = BLI_mempool_create(sizeof(EPathNode), 1, 512, BLI_MEMPOOL_SYSMALLOC);
  499. pb->pathpool = BLI_mempool_create(sizeof(EPath), 1, 512, BLI_MEMPOOL_SYSMALLOC);
  500. return pb;
  501. }
  502. static void edge_pathbase_free(PathBase *pathbase)
  503. {
  504. BLI_mempool_destroy(pathbase->nodepool);
  505. BLI_mempool_destroy(pathbase->pathpool);
  506. MEM_freeN(pathbase);
  507. }
  508. static EPath *edge_copy_add_path(PathBase *pb, EPath *path, BMVert *appendv, BMEdge *e)
  509. {
  510. EPath *path2;
  511. EPathNode *node, *node2;
  512. path2 = BLI_mempool_alloc(pb->pathpool);
  513. path2->nodes.first = path2->nodes.last = NULL;
  514. path2->weight = 0.0f;
  515. path2->group = path->group;
  516. for (node = path->nodes.first; node; node = node->next) {
  517. node2 = BLI_mempool_alloc(pb->nodepool);
  518. *node2 = *node;
  519. BLI_addtail(&path2->nodes, node2);
  520. }
  521. node2 = BLI_mempool_alloc(pb->nodepool);
  522. node2->v = appendv;
  523. node2->e = e;
  524. node2->cure = NULL;
  525. BLI_addtail(&path2->nodes, node2);
  526. return path2;
  527. }
  528. static EPath *edge_path_new(PathBase *pb, BMVert *start, BMEdge *starte)
  529. {
  530. EPath *path;
  531. EPathNode *node;
  532. path = BLI_mempool_alloc(pb->pathpool);
  533. node = BLI_mempool_alloc(pb->nodepool);
  534. path->nodes.first = path->nodes.last = NULL;
  535. node->v = start;
  536. node->e = starte;
  537. node->cure = NULL;
  538. BLI_addtail(&path->nodes, node);
  539. path->weight = 0.0f;
  540. return path;
  541. }
  542. static float edge_weight_path(EPath *path, EdgeData *edata, VertData *UNUSED(vdata))
  543. {
  544. EPathNode *node, *first = path->nodes.first;
  545. float w = 0.0;
  546. for (node = path->nodes.first; node; node = node->next) {
  547. if (node->e && node != path->nodes.first) {
  548. w += edata[BM_elem_index_get(node->e)].ftag;
  549. if (node->prev) {
  550. /* BMESH_TOD */
  551. (void)first;
  552. //w += len_v3v3(node->v->co, first->e->v1->co) * 0.0001f;
  553. //w += len_v3v3(node->v->co, first->e->v2->co) * 0.0001f;
  554. }
  555. }
  556. w += 1.0f;
  557. }
  558. return w;
  559. }
  560. static void edge_free_path(PathBase *pathbase, EPath *path)
  561. {
  562. EPathNode *node, *next;
  563. for (node = path->nodes.first; node; node = next) {
  564. next = node->next;
  565. BLI_mempool_free(pathbase->nodepool, node);
  566. }
  567. BLI_mempool_free(pathbase->pathpool, path);
  568. }
  569. static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, EdgeData *edata,
  570. VertData *vdata, PathBase *pathbase, int group)
  571. {
  572. BMEdge *e;
  573. GHash *gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createops find shortest path");
  574. BMVert *v1, *v2;
  575. BMVert **verts = NULL;
  576. BLI_array_staticdeclare(verts, 1024);
  577. Heap *heap = BLI_heap_new();
  578. EPath *path = NULL, *path2;
  579. BMVert *startv;
  580. BMVert *endv;
  581. EPathNode *node;
  582. int i, use_restrict = BMO_slot_bool_get(op, "use_restrict");
  583. startv = edata[BM_elem_index_get(edge)].ftag ? edge->v2 : edge->v1;
  584. endv = edata[BM_elem_index_get(edge)].ftag ? edge->v1 : edge->v2;
  585. path = edge_path_new(pathbase, startv, edge);
  586. BLI_ghash_insert(gh, startv, NULL);
  587. BLI_heap_insert(heap, path->weight, path);
  588. path->group = group;
  589. while (BLI_heap_size(heap)) {
  590. VertData *vd;
  591. EPathNode *last;
  592. BMFace *f = NULL;
  593. path = BLI_heap_popmin(heap);
  594. last = path->nodes.last;
  595. v1 = last->v;
  596. if (v1 == endv) {
  597. /* make sure this path loop doesn't already exists */
  598. i = 0;
  599. BLI_array_empty(verts);
  600. for (i = 0, node = path->nodes.first; node; node = node->next, i++) {
  601. BLI_array_growone(verts);
  602. verts[i] = node->v;
  603. }
  604. if (BM_face_exists(bm, verts, i, &f)) {
  605. if (!BMO_elem_flag_test(bm, f, FACE_IGNORE)) {
  606. BLI_ghash_remove(gh, endv, NULL, NULL);
  607. continue;
  608. }
  609. }
  610. break;
  611. }
  612. vd = vdata + BM_elem_index_get(v1);
  613. if (!vd->e)
  614. continue;
  615. v2 = NULL;
  616. while (1) {
  617. if (!last->cure) {
  618. last->cure = e = vdata[BM_elem_index_get(last->v)].e;
  619. }
  620. else {
  621. last->cure = e = rotsys_nextedge(last->cure, last->v, edata, vdata);
  622. if (last->cure == vdata[BM_elem_index_get(last->v)].e) {
  623. v2 = NULL;
  624. break;
  625. }
  626. }
  627. if (e == edge || !BMO_elem_flag_test(bm, e, EDGE_MARK)) {
  628. continue;
  629. }
  630. v2 = BM_edge_other_vert(e, last->v);
  631. if (BLI_ghash_haskey(gh, v2)) {
  632. v2 = NULL;
  633. continue;
  634. }
  635. if (use_restrict && BMO_slot_map_contains(bm, op, "restrict", e)) {
  636. int group = BMO_slot_map_int_get(bm, op, "restrict", e);
  637. if (!(group & path->group)) {
  638. v2 = NULL;
  639. continue;
  640. }
  641. }
  642. break;
  643. }
  644. if (!v2) {
  645. if (path) {
  646. edge_free_path(pathbase, path);
  647. path = NULL;
  648. }
  649. continue;
  650. }
  651. /* add path back into heap */
  652. BLI_heap_insert(heap, path->weight, path);
  653. /* put v2 in gh ma */
  654. BLI_ghash_insert(gh, v2, NULL);
  655. path2 = edge_copy_add_path(pathbase, path, v2, e);
  656. path2->weight = edge_weight_path(path2, edata, vdata);
  657. BLI_heap_insert(heap, path2->weight, path2);
  658. }
  659. if (path && ((EPathNode *)path->nodes.last)->v != endv) {
  660. edge_free_path(pathbase, path);
  661. path = NULL;
  662. }
  663. BLI_array_free(verts);
  664. BLI_heap_free(heap, NULL);
  665. BLI_ghash_free(gh, NULL, NULL);
  666. return path;
  667. }
  668. static int count_edge_faces(BMesh *bm, BMEdge *e)
  669. {
  670. int i = 0;
  671. BMLoop *l = e->l;
  672. if (!l) {
  673. return 0;
  674. }
  675. do {
  676. if (!BMO_elem_flag_test(bm, l->f, FACE_IGNORE)) {
  677. i++;
  678. }
  679. l = l->radial_next;
  680. } while (l != e->l);
  681. return i;
  682. }
  683. BLI_INLINE void vote_on_winding(BMEdge *edge, EPathNode *node, unsigned int winding[2])
  684. {
  685. BMVert *test_v1, *test_v2;
  686. /* we want to use the reverse winding to the existing order */
  687. BM_edge_ordered_verts(edge, &test_v2, &test_v1);
  688. /* edges vote on which winding wins out */
  689. winding[(test_v1 == node->v)]++;
  690. }
  691. void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
  692. {
  693. BMIter iter;
  694. BMOIter siter;
  695. BMFace *f;
  696. BMEdge *e, *edge;
  697. BMVert **verts = NULL;
  698. BLI_array_declare(verts);
  699. EPath *path;
  700. EPathNode *node;
  701. EdgeData *edata;
  702. VertData *vdata;
  703. BMEdge **edges = NULL;
  704. PathBase *pathbase;
  705. BLI_array_declare(edges);
  706. int use_restrict = BMO_slot_bool_get(op, "use_restrict");
  707. int use_fill_check = BMO_slot_bool_get(op, "use_fill_check");
  708. const short mat_nr = BMO_slot_int_get(op, "mat_nr");
  709. const short use_smooth = BMO_slot_bool_get(op, "use_smooth");
  710. int i, j, group = 0;
  711. unsigned int winding[2]; /* accumulte winding directions for each edge which has a face */
  712. if (!bm->totvert || !bm->totedge)
  713. return;
  714. pathbase = edge_pathbase_new();
  715. edata = MEM_callocN(sizeof(EdgeData) * bm->totedge, "EdgeData");
  716. vdata = MEM_callocN(sizeof(VertData) * bm->totvert, "VertData");
  717. BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK);
  718. BMO_slot_buffer_flag_enable(bm, op, "excludefaces", BM_FACE, FACE_IGNORE);
  719. BM_mesh_elem_index_ensure(bm, BM_VERT);
  720. BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
  721. BMO_elem_flag_enable(bm, f, ELE_ORIG);
  722. }
  723. i = 0;
  724. BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
  725. BM_elem_index_set(e, i); /* set_inline */
  726. if (!BMO_elem_flag_test(bm, e, EDGE_MARK)) {
  727. edata[i].tag = 2;
  728. }
  729. i++;
  730. }
  731. bm->elem_index_dirty &= ~BM_EDGE;
  732. init_rotsys(bm, edata, vdata);
  733. while (1) {
  734. edge = NULL;
  735. group = 0;
  736. BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) {
  737. /* if restrict is on, only start on faces in the restrict map */
  738. if (use_restrict && !BMO_slot_map_contains(bm, op, "restrict", e))
  739. continue;
  740. if (edata[BM_elem_index_get(e)].tag < 2) {
  741. edge = e;
  742. if (use_restrict) {
  743. int i = 0, j = 0, gi = 0;
  744. group = BMO_slot_map_int_get(bm, op, "restrict", e);
  745. for (i = 0; i < 30; i++) {
  746. if (group & (1 << i)) {
  747. j++;
  748. gi = i;
  749. if (j - 1 == edata[BM_elem_index_get(e)].tag) {
  750. break;
  751. }
  752. }
  753. }
  754. group = (1 << gi);
  755. }
  756. break;
  757. }
  758. }
  759. if (!edge)
  760. break;
  761. edata[BM_elem_index_get(edge)].tag += 1;
  762. path = edge_find_shortest_path(bm, op, edge, edata, vdata, pathbase, group);
  763. if (!path)
  764. continue;
  765. winding[0] = winding[1] = 0;
  766. BLI_array_empty(edges);
  767. BLI_array_empty(verts);
  768. i = 0;
  769. for (node = path->nodes.first; node; node = node->next) {
  770. if (!node->next)
  771. continue;
  772. e = BM_edge_exists(node->v, node->next->v);
  773. /* this should never happe */
  774. if (!e)
  775. break;
  776. /* check on the winding */
  777. if (e->l) {
  778. vote_on_winding(e, node, winding);
  779. }
  780. edata[BM_elem_index_get(e)].ftag++;
  781. BLI_array_growone(edges);
  782. edges[i++] = e;
  783. BLI_array_append(verts, node->v);
  784. }
  785. if (edge->l) {
  786. vote_on_winding(edge, path->nodes.last, winding);
  787. }
  788. BLI_array_growone(edges);
  789. edges[i++] = edge;
  790. edata[BM_elem_index_get(edge)].ftag++;
  791. for (j = 0; j < i; j++) {
  792. if (count_edge_faces(bm, edges[j]) >= 2) {
  793. edge_free_path(pathbase, path);
  794. break;
  795. }
  796. }
  797. if (j != i) {
  798. continue;
  799. }
  800. if (i) {
  801. BMVert *v1, *v2;
  802. /* to define the winding order must select first edge,
  803. * otherwise we could leave this as-is */
  804. edge = edges[0];
  805. /* if these are even it doesn't really matter what to do,
  806. * with consistent geometry one will be zero, the choice is clear */
  807. if (winding[0] < winding[1]) {
  808. v1 = verts[0];
  809. v2 = verts[1];
  810. }
  811. else {
  812. v1 = verts[1];
  813. v2 = verts[0];
  814. }
  815. if ((use_fill_check == FALSE) ||
  816. /* fairly expensive check - see if there are already faces filling this area */
  817. (BM_face_exists_multi_edge(edges, i) == FALSE))
  818. {
  819. f = BM_face_create_ngon(bm, v1, v2, edges, i, TRUE);
  820. if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) {
  821. BMO_elem_flag_enable(bm, f, FACE_NEW);
  822. f->mat_nr = mat_nr;
  823. if (use_smooth) {
  824. BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
  825. }
  826. }
  827. if (use_restrict) {
  828. BMO_slot_map_int_insert(bm, op, "faceout_groupmap", f, path->group);
  829. }
  830. }
  831. }
  832. edge_free_path(pathbase, path);
  833. }
  834. BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_NEW);
  835. BLI_array_free(edges);
  836. BLI_array_free(verts);
  837. edge_pathbase_free(pathbase);
  838. MEM_freeN(edata);
  839. MEM_freeN(vdata);
  840. }
  841. static BMEdge *edge_next(BMesh *bm, BMEdge *e)
  842. {
  843. BMIter iter;
  844. BMEdge *e2;
  845. int i;
  846. for (i = 0; i < 2; i++) {
  847. BM_ITER_ELEM (e2, &iter, i ? e->v2 : e->v1, BM_EDGES_OF_VERT) {
  848. if ((BMO_elem_flag_test(bm, e2, EDGE_MARK)) &&
  849. (!BMO_elem_flag_test(bm, e2, EDGE_VIS)) &&
  850. (e2 != e))
  851. {
  852. return e2;
  853. }
  854. }
  855. }
  856. return NULL;
  857. }
  858. void bmo_edgenet_prepare(BMesh *bm, BMOperator *op)
  859. {
  860. BMOIter siter;
  861. BMEdge *e;
  862. BMEdge **edges1 = NULL, **edges2 = NULL, **edges;
  863. BLI_array_declare(edges1);
  864. BLI_array_declare(edges2);
  865. BLI_array_declare(edges);
  866. int ok = 1;
  867. int i, count;
  868. BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK);
  869. /* validate that each edge has at most one other tagged edge in the
  870. * disk cycle around each of it's vertices */
  871. BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) {
  872. for (i = 0; i < 2; i++) {
  873. count = BMO_vert_edge_flags_count(bm, i ? e->v2 : e->v1, EDGE_MARK);
  874. if (count > 2) {
  875. ok = 0;
  876. break;
  877. }
  878. }
  879. if (!ok) {
  880. break;
  881. }
  882. }
  883. /* we don't have valid edge layouts, retur */
  884. if (!ok) {
  885. return;
  886. }
  887. /* find connected loops within the input edge */
  888. count = 0;
  889. while (1) {
  890. BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) {
  891. if (!BMO_elem_flag_test(bm, e, EDGE_VIS)) {
  892. if (BMO_vert_edge_flags_count(bm, e->v1, EDGE_MARK) == 1 ||
  893. BMO_vert_edge_flags_count(bm, e->v2, EDGE_MARK) == 1)
  894. {
  895. break;
  896. }
  897. }
  898. }
  899. if (!e) {
  900. break;
  901. }
  902. if (!count) {
  903. edges = edges1;
  904. }
  905. else if (count == 1) {
  906. edges = edges2;
  907. }
  908. else {
  909. break;
  910. }
  911. i = 0;
  912. while (e) {
  913. BMO_elem_flag_enable(bm, e, EDGE_VIS);
  914. BLI_array_growone(edges);
  915. edges[i] = e;
  916. e = edge_next(bm, e);
  917. i++;
  918. }
  919. if (!count) {
  920. edges1 = edges;
  921. BLI_array_set_length(edges1, BLI_array_count(edges));
  922. }
  923. else {
  924. edges2 = edges;
  925. BLI_array_set_length(edges2, BLI_array_count(edges));
  926. }
  927. BLI_array_empty(edges);
  928. count++;
  929. }
  930. if (edges1 && BLI_array_count(edges1) > 2 &&
  931. BM_edge_share_vert_count(edges1[0], edges1[BLI_array_count(edges1) - 1]))
  932. {
  933. if (edges2 && BLI_array_count(edges2) > 2 &&
  934. BM_edge_share_vert_count(edges2[0], edges2[BLI_array_count(edges2) - 1]))
  935. {
  936. BLI_array_free(edges1);
  937. BLI_array_free(edges2);
  938. return;
  939. }
  940. else {
  941. edges1 = edges2;
  942. edges2 = NULL;
  943. }
  944. }
  945. if (edges2 && BLI_array_count(edges2) > 2 &&
  946. BM_edge_share_vert_count(edges2[0], edges2[BLI_array_count(edges2) - 1]))
  947. {
  948. edges2 = NULL;
  949. }
  950. /* two unconnected loops, connect the */
  951. if (edges1 && edges2) {
  952. BMVert *v1, *v2, *v3, *v4;
  953. float dvec1[3];
  954. float dvec2[3];
  955. if (BLI_array_count(edges1) == 1) {
  956. v1 = edges1[0]->v1;
  957. v2 = edges1[0]->v2;
  958. }
  959. else {
  960. v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
  961. i = BLI_array_count(edges1) - 1;
  962. v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
  963. }
  964. if (BLI_array_count(edges2) == 1) {
  965. v3 = edges2[0]->v1;
  966. v4 = edges2[0]->v2;
  967. }
  968. else {
  969. v3 = BM_vert_in_edge(edges2[1], edges2[0]->v1) ? edges2[0]->v2 : edges2[0]->v1;
  970. i = BLI_array_count(edges2) - 1;
  971. v4 = BM_vert_in_edge(edges2[i - 1], edges2[i]->v1) ? edges2[i]->v2 : edges2[i]->v1;
  972. }
  973. /* if there is ever bowtie quads between two edges the problem is here! [#30367] */
  974. #if 0
  975. normal_tri_v3(dvec1, v1->co, v2->co, v4->co);
  976. normal_tri_v3(dvec2, v1->co, v4->co, v3->co);
  977. #else
  978. {
  979. /* save some CPU cycles and skip the sqrt and 1 subtraction */
  980. float a1[3], a2[3], a3[3];
  981. sub_v3_v3v3(a1, v1->co, v2->co);
  982. sub_v3_v3v3(a2, v1->co, v4->co);
  983. sub_v3_v3v3(a3, v1->co, v3->co);
  984. cross_v3_v3v3(dvec1, a1, a2);
  985. cross_v3_v3v3(dvec2, a2, a3);
  986. }
  987. #endif
  988. if (dot_v3v3(dvec1, dvec2) < 0.0f) {
  989. SWAP(BMVert *, v3, v4);
  990. }
  991. e = BM_edge_create(bm, v1, v3, NULL, TRUE);
  992. BMO_elem_flag_enable(bm, e, ELE_NEW);
  993. e = BM_edge_create(bm, v2, v4, NULL, TRUE);
  994. BMO_elem_flag_enable(bm, e, ELE_NEW);
  995. }
  996. else if (edges1) {
  997. BMVert *v1, *v2;
  998. if (BLI_array_count(edges1) > 1) {
  999. v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
  1000. i = BLI_array_count(edges1) - 1;
  1001. v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
  1002. e = BM_edge_create(bm, v1, v2, NULL, TRUE);
  1003. BMO_elem_flag_enable(bm, e, ELE_NEW);
  1004. }
  1005. }
  1006. BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, ELE_NEW);
  1007. BLI_array_free(edges1);
  1008. BLI_array_free(edges2);
  1009. }
  1010. /* This is what runs when pressing the F key
  1011. * doing the best thing here isn't always easy create vs dissolve, its nice to support
  1012. * but it it _really_ gives issues we might have to not call dissolve. - campbell
  1013. */
  1014. void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
  1015. {
  1016. BMOperator op2;
  1017. BMOIter oiter;
  1018. BMIter iter;
  1019. BMHeader *h;
  1020. BMVert *v, *verts[4];
  1021. BMEdge *e;
  1022. BMFace *f;
  1023. int totv = 0, tote = 0, totf = 0, amount;
  1024. const short mat_nr = BMO_slot_int_get(op, "mat_nr");
  1025. const short use_smooth = BMO_slot_bool_get(op, "use_smooth");
  1026. /* count number of each element type we were passe */
  1027. BMO_ITER (h, &oiter, bm, op, "geom", BM_VERT|BM_EDGE|BM_FACE) {
  1028. switch (h->htype) {
  1029. case BM_VERT: totv++; break;
  1030. case BM_EDGE: tote++; break;
  1031. case BM_FACE: totf++; break;
  1032. }
  1033. BMO_elem_flag_enable(bm, (BMElemF *)h, ELE_NEW);
  1034. }
  1035. /* --- Support for Special Case ---
  1036. * where there is a contiguous edge ring with one isolated vertex.
  1037. *
  1038. * This example shows 2 edges created from 3 verts
  1039. * with 1 free standing vertex. Dotted lines denote the 2 edges that are created.
  1040. *
  1041. * note that this works for any sided shape.
  1042. *
  1043. * +--------+
  1044. * | .
  1045. * | .
  1046. * | .
  1047. * | .
  1048. * +........+ <-- starts out free standing.
  1049. *
  1050. */
  1051. /* Here we check for consistancy and create 2 edges */
  1052. if (totf == 0 && totv >= 4 && totv == tote + 2) {
  1053. /* find a free standing vertex and 2 endpoint verts */
  1054. BMVert *v_free = NULL, *v_a = NULL, *v_b = NULL;
  1055. int ok = TRUE;
  1056. BMO_ITER (v, &oiter, bm, op, "geom", BM_VERT) {
  1057. /* count how many flagged edges this vertex uses */
  1058. int tot_edges = 0;
  1059. BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
  1060. if (BMO_elem_flag_test(bm, e, ELE_NEW)) {
  1061. tot_edges++;
  1062. if (tot_edges > 2) {
  1063. break;
  1064. }
  1065. }
  1066. }
  1067. if (tot_edges == 0) {
  1068. /* only accept 1 free vert */
  1069. if (v_free == NULL) v_free = v;
  1070. else ok = FALSE; /* only ever want one of these */
  1071. }
  1072. else if (tot_edges == 1) {
  1073. if (v_a == NULL) v_a = v;
  1074. else if (v_b == NULL) v_b = v;
  1075. else ok = FALSE; /* only ever want 2 of these */
  1076. }
  1077. else if (tot_edges == 2) {
  1078. /* do nothing, regular case */
  1079. }
  1080. else {
  1081. ok = FALSE; /* if a vertex has 3+ edge users then cancel - this is only simple cases */
  1082. }
  1083. if (ok == FALSE) {
  1084. break;
  1085. }
  1086. }
  1087. if (ok == TRUE && v_free && v_a && v_b) {
  1088. e = BM_edge_create(bm, v_free, v_a, NULL, TRUE);
  1089. BMO_elem_flag_enable(bm, e, ELE_NEW);
  1090. e = BM_edge_create(bm, v_free, v_b, NULL, TRUE);
  1091. BMO_elem_flag_enable(bm, e, ELE_NEW);
  1092. }
  1093. }
  1094. /* --- end special case support, continue as normal --- */
  1095. /* call edgenet create */
  1096. /* call edgenet prepare op so additional face creation cases wore */
  1097. BMO_op_initf(bm, &op2, "edgenet_prepare edges=%fe", ELE_NEW);
  1098. BMO_op_exec(bm, &op2);
  1099. BMO_slot_buffer_flag_enable(bm, &op2, "edgeout", BM_EDGE, ELE_NEW);
  1100. BMO_op_finish(bm, &op2);
  1101. BMO_op_initf(bm, &op2,
  1102. "edgenet_fill edges=%fe use_fill_check=%b mat_nr=%i use_smooth=%b",
  1103. ELE_NEW, TRUE, mat_nr, use_smooth);
  1104. BMO_op_exec(bm, &op2);
  1105. /* return if edge net create did something */
  1106. if (BMO_slot_buffer_count(bm, &op2, "faceout")) {
  1107. BMO_slot_copy(&op2, op, "faceout", "faceout");
  1108. BMO_op_finish(bm, &op2);
  1109. return;
  1110. }
  1111. BMO_op_finish(bm, &op2);
  1112. /* now call dissolve face */
  1113. BMO_op_initf(bm, &op2, "dissolve_faces faces=%ff", ELE_NEW);
  1114. BMO_op_exec(bm, &op2);
  1115. /* if we dissolved anything, then return */
  1116. if (BMO_slot_buffer_count(bm, &op2, "regionout")) {
  1117. BMO_slot_copy(&op2, op, "regionout", "faceout");
  1118. BMO_op_finish(bm, &op2);
  1119. return;
  1120. }
  1121. BMO_op_finish(bm, &op2);
  1122. /* now, count how many verts we have */
  1123. amount = 0;
  1124. BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
  1125. if (BMO_elem_flag_test(bm, v, ELE_NEW)) {
  1126. verts[amount] = v;
  1127. amount++;
  1128. if (amount > 4) break;
  1129. }
  1130. }
  1131. if (amount == 2) {
  1132. /* create edge */
  1133. e = BM_edge_create(bm, verts[0], verts[1], NULL, TRUE);
  1134. BMO_elem_flag_enable(bm, e, ELE_OUT);
  1135. }
  1136. else if (0) { /* nice feature but perhaps it should be a different tool? */
  1137. /* tricky feature for making a line/edge from selection history...
  1138. *
  1139. * Rather then do nothing, when 5+ verts are selected, check if they are in our history,
  1140. * when this is so, we can make edges from them, but _not_ a face,
  1141. * if it is the intention to make a face the user can just hit F again since there will be edges next
  1142. * time around.
  1143. *
  1144. * if all history verts have ELE_NEW flagged and the total number of history verts == totv,
  1145. * then we know the history contains all verts here and we can continue...
  1146. */
  1147. BMEditSelection *ese;
  1148. int tot_ese_v = 0;
  1149. for (ese = bm->selected.first; ese; ese = ese->next) {
  1150. if (ese->htype == BM_VERT) {
  1151. if (BMO_elem_flag_test(bm, (BMElemF *)ese->ele, ELE_NEW)) {
  1152. tot_ese_v++;
  1153. }
  1154. else {
  1155. /* unflagged vert means we are not in sync */
  1156. tot_ese_v = -1;
  1157. break;
  1158. }
  1159. }
  1160. }
  1161. if (tot_ese_v == totv) {
  1162. BMVert *v_prev = NULL;
  1163. /* yes, all select-history verts are accounted for, now make edges */
  1164. for (ese = bm->selected.first; ese; ese = ese->next) {
  1165. if (ese->htype == BM_VERT) {
  1166. v = (BMVert *)ese->ele;
  1167. if (v_prev) {
  1168. e = BM_edge_create(bm, v, v_prev, NULL, TRUE);
  1169. BMO_elem_flag_enable(bm, e, ELE_OUT);
  1170. }
  1171. v_prev = v;
  1172. }
  1173. }
  1174. }
  1175. /* done creating edges */
  1176. }
  1177. else if (amount > 2) {
  1178. /* TODO, all these verts may be connected by edges.
  1179. * we should check on this before assuming they are a random set of verts */
  1180. BMVert **vert_arr = MEM_mallocN(sizeof(BMVert **) * totv, __func__);
  1181. int i = 0;
  1182. BMO_ITER (v, &oiter, bm, op, "geom", BM_VERT) {
  1183. vert_arr[i] = v;
  1184. i++;
  1185. }
  1186. f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, TRUE);
  1187. if (f) {
  1188. BMO_elem_flag_enable(bm, f, ELE_OUT);
  1189. f->mat_nr = mat_nr;
  1190. if (use_smooth) {
  1191. BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
  1192. }
  1193. }
  1194. MEM_freeN(vert_arr);
  1195. }
  1196. }