84
84
BLI_INLINE BMDiskLink *rs_edge_link_get(BMEdge *e, BMVert *v, EdgeData *e_data)
86
return v == ((BMEdge *)e)->v1 ? &(((EdgeData *)e_data)->v1_disk_link) :
87
&(((EdgeData *)e_data)->v2_disk_link) ;
86
return v == ((BMEdge *)e)->v1 ? &(((EdgeData *)e_data)->v1_disk_link) :
87
&(((EdgeData *)e_data)->v2_disk_link);
90
static int rotsys_append_edge(BMEdge *e, BMVert *v,
91
EdgeData *edata, VertData *vdata)
90
static bool rotsys_append_edge(BMEdge *e, BMVert *v,
91
EdgeData *edata, VertData *vdata)
93
93
EdgeData *ed = &edata[BM_elem_index_get(e)];
94
94
VertData *vd = &vdata[BM_elem_index_get(v)];
274
274
if (!ok || BLI_array_count(edges) < 3)
277
f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), TRUE);
277
f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), BM_CREATE_NO_DOUBLE);
278
if (UNLIKELY(f == NULL)) {
360
361
BMEdge **edges = NULL;
361
BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE);
362
BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
363
364
/* BMVert **verts = NULL; */
364
/* BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); */ /* UNUSE */
365
/* BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); */ /* UNUSE */
367
#define SIGN(n) ((n)<0.0f)
369
368
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
371
370
float no[3], cent[3];
579
578
//rotsys_fill_faces(bm, edata, vdata);
582
/* create visualizing geometr */
581
/* create visualizing geometry */
584
583
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
613
612
v2 = BM_vert_create(bm, co, NULL);
614
613
BM_elem_index_set(v2, -1); /* set_dirty! */
615
//BM_edge_create(bm, cv, v2, NULL, FALSE);
614
//BM_edge_create(bm, cv, v2, NULL, 0);
617
BM_vert_select_set(bm, v2, TRUE);
616
BM_vert_select_set(bm, v2, true);
619
e2 = BM_edge_create(bm, lastv, v2, NULL, FALSE);
620
BM_edge_select_set(bm, e2, TRUE);
618
e2 = BM_edge_create(bm, lastv, v2, NULL, 0);
619
BM_edge_select_set(bm, e2, true);
733
732
VertData *vdata, PathBase *pathbase, int group)
736
GHash *gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "createops find shortest path");
735
GHash *gh = BLI_ghash_ptr_new("createops find shortest path");
738
737
BMVert **verts = NULL;
739
738
BLI_array_staticdeclare(verts, 1024);
745
int i, use_restrict = BMO_slot_bool_get(op, "use_restrict");
745
const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
746
BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict");
747
749
startv = edata[BM_elem_index_get(edge)].ftag ? edge->v2 : edge->v1;
748
750
endv = edata[BM_elem_index_get(edge)].ftag ? edge->v1 : edge->v2;
767
769
BLI_array_empty(verts);
768
770
for (i = 0, node = path->nodes.first; node; node = node->next, i++) {
769
BLI_array_growone(verts);
771
BLI_array_grow_one(verts);
770
772
verts[i] = node->v;
773
if (BM_face_exists(bm, verts, i, &f)) {
775
if (BM_face_exists(verts, i, &f)) {
774
776
if (!BMO_elem_flag_test(bm, f, FACE_IGNORE)) {
775
777
BLI_ghash_remove(gh, endv, NULL, NULL);
810
if (use_restrict && BMO_slot_map_contains(bm, op, "restrict", e)) {
811
int group = BMO_slot_map_int_get(bm, op, "restrict", e);
813
if (!(group & path->group)) {
813
int *group = (int *)BMO_slot_map_data_get(slot_restrict, e);
815
if (!(*group & path->group)) {
896
899
BMEdge **edges = NULL;
897
900
PathBase *pathbase;
898
901
BLI_array_declare(edges);
899
int use_restrict = BMO_slot_bool_get(op, "use_restrict");
900
int use_fill_check = BMO_slot_bool_get(op, "use_fill_check");
901
const short mat_nr = BMO_slot_int_get(op, "mat_nr");
902
const short use_smooth = BMO_slot_bool_get(op, "use_smooth");
902
const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict");
903
const bool use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check");
904
const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
905
const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
903
906
int i, j, group = 0;
904
907
unsigned int winding[2]; /* accumulte winding directions for each edge which has a face */
908
BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict");
909
BMOpSlot *slot_face_groupmap_out = BMO_slot_get(op->slots_out, "face_groupmap.out");
906
911
if (!bm->totvert || !bm->totedge)
911
916
edata = MEM_callocN(sizeof(EdgeData) * bm->totedge, "EdgeData");
912
917
vdata = MEM_callocN(sizeof(VertData) * bm->totvert, "VertData");
914
BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK);
915
BMO_slot_buffer_flag_enable(bm, op, "excludefaces", BM_FACE, FACE_IGNORE);
919
BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
920
BMO_slot_buffer_flag_enable(bm, op->slots_in, "exclude_faces", BM_FACE, FACE_IGNORE);
917
922
BM_mesh_elem_index_ensure(bm, BM_VERT);
933
938
bm->elem_index_dirty &= ~BM_EDGE;
935
940
init_rotsys(bm, edata, vdata);
941
BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) {
946
BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
942
947
/* if restrict is on, only start on faces in the restrict map */
943
if (use_restrict && !BMO_slot_map_contains(bm, op, "restrict", e))
948
if (use_restrict && !BMO_slot_map_contains(slot_restrict, e))
946
951
if (edata[BM_elem_index_get(e)].tag < 2) {
949
954
if (use_restrict) {
950
955
int i = 0, j = 0, gi = 0;
952
group = BMO_slot_map_int_get(bm, op, "restrict", e);
957
group = BMO_slot_map_int_get(slot_restrict, e);
954
959
for (i = 0; i < 30; i++) {
955
960
if (group & (1 << i)) {
1001
1006
edata[BM_elem_index_get(e)].ftag++;
1002
BLI_array_growone(edges);
1007
BLI_array_grow_one(edges);
1003
1008
edges[i++] = e;
1005
1010
BLI_array_append(verts, node->v);
1009
1014
vote_on_winding(edge, path->nodes.last, winding);
1012
BLI_array_growone(edges);
1017
BLI_array_grow_one(edges);
1013
1018
edges[i++] = edge;
1014
1019
edata[BM_elem_index_get(edge)].ftag++;
1045
if ((use_fill_check == FALSE) ||
1050
if ((use_fill_check == false) ||
1046
1051
/* fairly expensive check - see if there are already faces filling this area */
1047
(BM_face_exists_multi_edge(edges, i) == FALSE))
1052
(BM_face_exists_multi_edge(edges, i) == false))
1049
f = BM_face_create_ngon(bm, v1, v2, edges, i, TRUE);
1054
f = BM_face_create_ngon(bm, v1, v2, edges, i, BM_CREATE_NO_DOUBLE);
1050
1055
if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) {
1051
1056
BMO_elem_flag_enable(bm, f, FACE_NEW);
1052
1057
f->mat_nr = mat_nr;
1058
1063
if (use_restrict) {
1059
BMO_slot_map_int_insert(bm, op, "faceout_groupmap", f, path->group);
1064
BMO_slot_map_int_insert(op, slot_face_groupmap_out, f, path->group);
1064
1069
edge_free_path(pathbase, path);
1067
BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_NEW);
1072
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW);
1069
1074
BLI_array_free(edges);
1070
1075
BLI_array_free(verts);
1107
BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK);
1112
BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
1109
1114
/* validate that each edge has at most one other tagged edge in the
1110
1115
* disk cycle around each of it's vertices */
1111
BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) {
1116
BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
1112
1117
for (i = 0; i < 2; i++) {
1113
1118
count = BMO_vert_edge_flags_count(bm, i ? e->v2 : e->v1, EDGE_MARK);
1114
1119
if (count > 2) {
1130
1135
/* find connected loops within the input edge */
1133
BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) {
1138
BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
1134
1139
if (!BMO_elem_flag_test(bm, e, EDGE_VIS)) {
1135
1140
if (BMO_vert_edge_flags_count(bm, e->v1, EDGE_MARK) == 1 ||
1136
1141
BMO_vert_edge_flags_count(bm, e->v2, EDGE_MARK) == 1)
1168
1173
edges1 = edges;
1169
BLI_array_set_length(edges1, BLI_array_count(edges));
1174
BLI_array_length_set(edges1, BLI_array_count(edges));
1172
1177
edges2 = edges;
1173
BLI_array_set_length(edges2, BLI_array_count(edges));
1178
BLI_array_length_set(edges2, BLI_array_count(edges));
1176
1181
BLI_array_empty(edges);
1180
1185
if (edges1 && BLI_array_count(edges1) > 2 &&
1181
BM_edge_share_vert_count(edges1[0], edges1[BLI_array_count(edges1) - 1]))
1186
BM_edge_share_vert_check(edges1[0], edges1[BLI_array_count(edges1) - 1]))
1183
1188
if (edges2 && BLI_array_count(edges2) > 2 &&
1184
BM_edge_share_vert_count(edges2[0], edges2[BLI_array_count(edges2) - 1]))
1189
BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1]))
1186
1191
BLI_array_free(edges1);
1187
1192
BLI_array_free(edges2);
1225
1230
v4 = BM_vert_in_edge(edges2[i - 1], edges2[i]->v1) ? edges2[i]->v2 : edges2[i]->v1;
1228
/* if there is ever bowtie quads between two edges the problem is here! [#30367] */
1233
/* if there is ever bow-tie quads between two edges the problem is here! [#30367] */
1230
1235
normal_tri_v3(dvec1, v1->co, v2->co, v4->co);
1231
1236
normal_tri_v3(dvec2, v1->co, v4->co, v3->co);
1244
1249
SWAP(BMVert *, v3, v4);
1247
e = BM_edge_create(bm, v1, v3, NULL, TRUE);
1252
e = BM_edge_create(bm, v1, v3, NULL, BM_CREATE_NO_DOUBLE);
1248
1253
BMO_elem_flag_enable(bm, e, ELE_NEW);
1249
e = BM_edge_create(bm, v2, v4, NULL, TRUE);
1254
e = BM_edge_create(bm, v2, v4, NULL, BM_CREATE_NO_DOUBLE);
1250
1255
BMO_elem_flag_enable(bm, e, ELE_NEW);
1252
1257
else if (edges1) {
1256
1261
v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
1257
1262
i = BLI_array_count(edges1) - 1;
1258
1263
v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
1259
e = BM_edge_create(bm, v1, v2, NULL, TRUE);
1264
e = BM_edge_create(bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE);
1260
1265
BMO_elem_flag_enable(bm, e, ELE_NEW);
1264
BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, ELE_NEW);
1269
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_NEW);
1266
1271
BLI_array_free(edges1);
1267
1272
BLI_array_free(edges2);
1283
1288
int totv = 0, tote = 0, totf = 0, amount;
1284
const short mat_nr = BMO_slot_int_get(op, "mat_nr");
1285
const short use_smooth = BMO_slot_bool_get(op, "use_smooth");
1289
const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
1290
const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
1287
1292
/* count number of each element type we were passe */
1288
BMO_ITER (h, &oiter, bm, op, "geom", BM_VERT|BM_EDGE|BM_FACE) {
1293
BMO_ITER (h, &oiter, op->slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE) {
1289
1294
switch (h->htype) {
1290
1295
case BM_VERT: totv++; break;
1291
1296
case BM_EDGE: tote++; break;
1315
/* Here we check for consistancy and create 2 edges */
1320
/* Here we check for consistency and create 2 edges */
1316
1321
if (totf == 0 && totv >= 4 && totv == tote + 2) {
1317
1322
/* find a free standing vertex and 2 endpoint verts */
1318
1323
BMVert *v_free = NULL, *v_a = NULL, *v_b = NULL;
1322
BMO_ITER (v, &oiter, bm, op, "geom", BM_VERT) {
1327
BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) {
1323
1328
/* count how many flagged edges this vertex uses */
1324
1329
int tot_edges = 0;
1325
1330
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
1334
1339
if (tot_edges == 0) {
1335
1340
/* only accept 1 free vert */
1336
1341
if (v_free == NULL) v_free = v;
1337
else ok = FALSE; /* only ever want one of these */
1342
else ok = false; /* only ever want one of these */
1339
1344
else if (tot_edges == 1) {
1340
1345
if (v_a == NULL) v_a = v;
1341
1346
else if (v_b == NULL) v_b = v;
1342
else ok = FALSE; /* only ever want 2 of these */
1347
else ok = false; /* only ever want 2 of these */
1344
1349
else if (tot_edges == 2) {
1345
1350
/* do nothing, regular case */
1348
ok = FALSE; /* if a vertex has 3+ edge users then cancel - this is only simple cases */
1353
ok = false; /* if a vertex has 3+ edge users then cancel - this is only simple cases */
1356
if (ok == TRUE && v_free && v_a && v_b) {
1357
e = BM_edge_create(bm, v_free, v_a, NULL, TRUE);
1361
if (ok == true && v_free && v_a && v_b) {
1362
e = BM_edge_create(bm, v_free, v_a, NULL, BM_CREATE_NO_DOUBLE);
1358
1363
BMO_elem_flag_enable(bm, e, ELE_NEW);
1360
e = BM_edge_create(bm, v_free, v_b, NULL, TRUE);
1365
e = BM_edge_create(bm, v_free, v_b, NULL, BM_CREATE_NO_DOUBLE);
1361
1366
BMO_elem_flag_enable(bm, e, ELE_NEW);
1366
1371
/* call edgenet create */
1367
1372
/* call edgenet prepare op so additional face creation cases wore */
1368
BMO_op_initf(bm, &op2, "edgenet_prepare edges=%fe", ELE_NEW);
1373
BMO_op_initf(bm, &op2, op->flag, "edgenet_prepare edges=%fe", ELE_NEW);
1369
1374
BMO_op_exec(bm, &op2);
1370
BMO_slot_buffer_flag_enable(bm, &op2, "edgeout", BM_EDGE, ELE_NEW);
1375
BMO_slot_buffer_flag_enable(bm, op2.slots_out, "edges.out", BM_EDGE, ELE_NEW);
1371
1376
BMO_op_finish(bm, &op2);
1373
BMO_op_initf(bm, &op2,
1378
BMO_op_initf(bm, &op2, op->flag,
1374
1379
"edgenet_fill edges=%fe use_fill_check=%b mat_nr=%i use_smooth=%b",
1375
ELE_NEW, TRUE, mat_nr, use_smooth);
1380
ELE_NEW, true, mat_nr, use_smooth);
1377
1382
BMO_op_exec(bm, &op2);
1379
1384
/* return if edge net create did something */
1380
if (BMO_slot_buffer_count(bm, &op2, "faceout")) {
1381
BMO_slot_copy(&op2, op, "faceout", "faceout");
1385
if (BMO_slot_buffer_count(op2.slots_out, "faces.out")) {
1386
BMO_slot_copy(&op2, slots_out, "faces.out",
1387
op, slots_out, "faces.out");
1382
1388
BMO_op_finish(bm, &op2);
1386
1392
BMO_op_finish(bm, &op2);
1388
1394
/* now call dissolve face */
1389
BMO_op_initf(bm, &op2, "dissolve_faces faces=%ff", ELE_NEW);
1395
BMO_op_initf(bm, &op2, op->flag, "dissolve_faces faces=%ff", ELE_NEW);
1390
1396
BMO_op_exec(bm, &op2);
1392
1398
/* if we dissolved anything, then return */
1393
if (BMO_slot_buffer_count(bm, &op2, "regionout")) {
1394
BMO_slot_copy(&op2, op, "regionout", "faceout");
1399
if (BMO_slot_buffer_count(op2.slots_out, "region.out")) {
1400
BMO_slot_copy(&op2, slots_out, "region.out",
1401
op, slots_out, "faces.out");
1395
1402
BMO_op_finish(bm, &op2);
1403
1410
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
1404
1411
if (BMO_elem_flag_test(bm, v, ELE_NEW)) {
1405
1412
verts[amount] = v;
1408
if (amount > 4) break;
1412
1421
if (amount == 2) {
1413
1422
/* create edge */
1414
e = BM_edge_create(bm, verts[0], verts[1], NULL, TRUE);
1423
e = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE);
1415
1424
BMO_elem_flag_enable(bm, e, ELE_OUT);
1425
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT);
1417
1427
else if (0) { /* nice feature but perhaps it should be a different tool? */
1451
1461
if (ese->htype == BM_VERT) {
1452
1462
v = (BMVert *)ese->ele;
1454
e = BM_edge_create(bm, v, v_prev, NULL, TRUE);
1464
e = BM_edge_create(bm, v, v_prev, NULL, BM_CREATE_NO_DOUBLE);
1455
1465
BMO_elem_flag_enable(bm, e, ELE_OUT);
1471
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT);
1461
1472
/* done creating edges */
1463
1474
else if (amount > 2) {
1467
1478
BMVert **vert_arr = MEM_mallocN(sizeof(BMVert **) * totv, __func__);
1470
BMO_ITER (v, &oiter, bm, op, "geom", BM_VERT) {
1481
BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) {
1471
1482
vert_arr[i] = v;
1475
f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, TRUE);
1486
f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, BM_CREATE_NO_DOUBLE);
1478
1489
BMO_elem_flag_enable(bm, f, ELE_OUT);