147 if (faces_num == 0 && verts_num != 0) {
153 const short mat_nr_max = mat_nrs - 1;
154 const short mat_ofs = mat_nrs > 1 ? smd->
mat_ofs : 0;
155 const short mat_ofs_rim = mat_nrs > 1 ? smd->
mat_ofs_rim : 0;
164 const float ofs_front_clamped =
clamp_nonzero(ofs_front, 1e-5f);
165 const float ofs_back_clamped =
clamp_nonzero(ofs_back, 1e-5f);
197 const float *orig_vert_bweight =
static_cast<const float *
>(
199 const float *orig_edge_bweight =
static_cast<const float *
>(
201 const float *orig_edge_crease =
static_cast<const float *
>(
204 uint new_verts_num = 0;
205 uint new_edges_num = 0;
206 uint new_loops_num = 0;
207 uint new_faces_num = 0;
209#define MOD_SOLIDIFY_EMPTY_TAG uint(-1)
219 uint largest_ngon = 3;
226 const int2 &edge = orig_edges[orig_corner_edges[face.
start()]];
228 sub_v3_v3v3(edgedir, orig_vert_positions[edge[1]], orig_vert_positions[edge[0]]);
230 face_nors[
i][2] = 1.0f;
233 face_nors[
i][1] = 1.0f;
236 null_faces[
i] =
true;
243 new_face_ref_a.
face = face;
247 face_sides_arr[
i * 2] = std::move(new_face_ref_a);
252 new_face_ref_b.
face = face;
256 face_sides_arr[
i * 2 + 1] = std::move(new_face_ref_b);
258 if (face.
size() > largest_ngon) {
264 new_loops_num +=
uint(face.
size() * 2);
273 for (
const int64_t edge : orig_corner_edges.
slice(orig_faces[
i])) {
274 edge_adj_faces_len[edge]++;
287 for (
uint i = 0;
i < verts_num;
i++) {
295 bool has_singularities =
false;
302 for (
uint i = 0;
i < verts_num;
i++) {
303 orig_mvert_co[
i][0] = orig_vert_positions[
i][0];
304 orig_mvert_co[
i][1] = orig_vert_positions[
i][1];
305 orig_mvert_co[
i][2] = orig_vert_positions[
i][2];
315 for (
const int64_t corner : orig_faces[
i]) {
316 const int vert = orig_corner_verts[corner];
317 const int edge = orig_corner_edges[corner];
318 const bool reversed = orig_edges[edge][1] != vert;
320 if (old_face_edge_ref ==
nullptr) {
321 const uint len = edge_adj_faces_len[edge];
325 adj_faces[0] =
uint(
i);
326 for (
uint k = 1; k <
len; k++) {
329 adj_faces_reversed[0] = reversed;
332 edge_adj_faces[edge] = ref;
347 float edgedir[3] = {0, 0, 0};
357 for (
uint i = 0;
i < edges_num;
i++) {
358 const int2 &edge = orig_edges[
i];
359 if (edge_adj_faces_len[
i] > 0) {
360 uint v1 = vm[edge[0]];
372 if (orig_edge_lengths[
i] <= merge_tolerance_sqr) {
376 bool can_merge =
true;
377 for (
uint k = 0; k < edges_num && can_merge; k++) {
378 if (k !=
i && edge_adj_faces_len[k] > 0 &&
379 (
ELEM(vm[orig_edges[k][0]], v1,
v2) !=
ELEM(vm[orig_edges[k][1]], v1,
v2)))
381 for (
uint j = 0; j < edge_adj_faces[k]->
faces_len && can_merge; j++) {
384 int cur = face.
size() - 1;
386 uint cur_v = vm[orig_corner_verts[face[cur]]];
387 uint next_v = vm[orig_corner_verts[face[
next]]];
388 changes += (
ELEM(cur_v, v1,
v2) !=
ELEM(next_v, v1,
v2));
391 can_merge = can_merge && changes <= 2;
397 orig_edge_lengths[
i] = 0.0f;
398 vert_adj_edges_len[v1]++;
399 vert_adj_edges_len[
v2]++;
404 (combined_verts[
v2] + 1) /
405 float(combined_verts[v1] + combined_verts[
v2] + 2));
407 for (
uint j =
v2; j < verts_num; j++) {
412 vert_adj_edges_len[v1] += vert_adj_edges_len[
v2];
413 vert_adj_edges_len[
v2] = 0;
414 combined_verts[v1] += combined_verts[
v2] + 1;
417 new_loops_num -= edge_adj_faces_len[
i] * 2;
420 edge_adj_faces_len[
i] = 0;
424 edge_adj_faces[
i] =
nullptr;
427 orig_edge_lengths[
i] =
sqrtf(orig_edge_lengths[
i]);
428 vert_adj_edges_len[v1]++;
429 vert_adj_edges_len[
v2]++;
434 for (
uint i = 0;
i < edges_num;
i++) {
435 const int2 &edge = orig_edges[
i];
436 const uint v1 = vm[edge[0]];
437 const uint v2 = vm[edge[1]];
438 if (v1 ==
v2 && edge_adj_faces[
i]) {
441 const uint face = edge_adj_faces[
i]->
faces[j];
442 if (!face_singularity[face]) {
443 bool is_singularity =
true;
444 for (
const int vert : orig_corner_verts.
slice(orig_faces[face])) {
445 if (vm[vert] != v1) {
446 is_singularity =
false;
450 if (is_singularity) {
451 face_singularity[face] =
true;
461 new_loops_num -= edge_adj_faces_len[
i] * 2;
464 edge_adj_faces_len[
i] = 0;
468 edge_adj_faces[
i] =
nullptr;
478 for (
uint i = 0;
i < edges_num;
i++) {
479 const int2 &edge = orig_edges[
i];
480 if (edge_adj_faces_len[
i] > 0) {
481 const int vs[2] = {int(vm[edge[0]]), int(vm[edge[1]])};
482 uint invalid_edge_index = 0;
483 bool invalid_edge_reversed =
false;
484 for (
uint j = 0; j < 2; j++) {
485 const int vert = vs[j];
486 const uint len = vert_adj_edges_len[vert];
489 if (old_edge_vert_ref ==
nullptr) {
492 for (
uint k = 1; k <
len; k++) {
497 vert_adj_edges[vert] = ref;
500 const uint *f = old_edge_vert_ref->
edges;
502 const uint edge = old_edge_vert_ref->
edges[k];
504 old_edge_vert_ref->
edges[k] =
i;
508 if (vm[orig_edges[edge][0]] == vs[1 - j]) {
509 invalid_edge_index = edge + 1;
510 invalid_edge_reversed = (j == 0);
513 if (vm[orig_edges[edge][1]] == vs[1 - j]) {
514 invalid_edge_index = edge + 1;
515 invalid_edge_reversed = (j == 1);
519 if (invalid_edge_index) {
530 if (invalid_edge_index) {
531 const uint tmp = invalid_edge_index - 1;
532 invalid_edge_index =
i;
535 OldEdgeFaceRef *invalid_adj_faces = edge_adj_faces[invalid_edge_index];
539 if (i_adj_faces->
faces[k] == invalid_adj_faces->
faces[
l] &&
550 new_faces_num -= 2 * j;
551 new_loops_num -= 4 * j;
560 adj_faces[j] = i_adj_faces->
faces[k];
566 adj_faces[j] = invalid_adj_faces->
faces[k];
567 adj_faces_loops_reversed[j++] = (invalid_edge_reversed !=
572 edge_adj_faces_len[invalid_edge_index] = 0;
573 edge_adj_faces_len[
i] =
len;
577 i_adj_faces->
faces = adj_faces;
579 i_adj_faces->
used += invalid_adj_faces->
used;
583 edge_adj_faces[invalid_edge_index] = i_adj_faces;
585 i = invalid_edge_index;
595 const int2 *edge = orig_edges.
data();
598 for (
uint i = 0;
i < edges_num;
i++, edge++) {
599 if (edge_adj_faces_len[
i] > 0) {
606 for (
uint j = 0; j < adj_len; j++) {
608 const int j_loopstart = orig_faces[face].start();
609 const int totloop = orig_faces[face].
size();
610 const uint j_first_v = vm[orig_corner_verts[j_loopstart]];
611 for (
uint k = j + 1; k < adj_len; k++) {
612 if (orig_faces[adj_faces->
faces[k]].
size() != totloop) {
616 const int k_loopstart = orig_faces[adj_faces->
faces[k]].start();
619 const int *corner_vert = &orig_corner_verts[k_loopstart];
620 for (
l = 0;
l < totloop && vm[*corner_vert] != j_first_v;
l++, corner_vert++) {
629 const int count_dir = reversed ? -1 : 1;
630 bool has_diff =
false;
631 for (
int m = 0, n =
l + totloop; m < totloop && !has_diff; m++, n += count_dir) {
632 const int vert = orig_corner_verts[j_loopstart + m];
633 has_diff = has_diff ||
634 vm[vert] != vm[orig_corner_verts[k_loopstart + n % totloop]];
639 for (
uint m = 0; m < totloop; m++) {
640 const int e = orig_corner_edges[j_loopstart + m];
644 uint *e_adj_faces_faces = e_adj_faces->
faces;
647 if (e_adj_faces_faces != adj_faces->
faces) {
650 face_index < faces_len && e_adj_faces_faces[face_index] != face;
656 if (face_index == faces_len) {
664 memmove(e_adj_faces_faces + face_index,
665 e_adj_faces_faces + face_index + 1,
666 (faces_len - face_index - 1) *
sizeof(*e_adj_faces_faces));
667 memmove(e_adj_faces_reversed + face_index,
668 e_adj_faces_reversed + face_index + 1,
669 (faces_len - face_index - 1) *
sizeof(*e_adj_faces_reversed));
671 if (edge_adj_faces_len[
e] > 0) {
672 edge_adj_faces_len[
e]--;
673 if (edge_adj_faces_len[
e] == 0) {
675 edge_adj_faces[
e] =
nullptr;
678 else if (e_adj_faces->
used > 1) {
679 for (
uint n = 0; n < edges_num; n++) {
680 if (edge_adj_faces[n] == e_adj_faces && edge_adj_faces_len[n] > 0) {
681 edge_adj_faces_len[n]--;
682 if (edge_adj_faces_len[n] == 0) {
683 edge_adj_faces[n]->
used--;
684 edge_adj_faces[n] =
nullptr;
695 new_loops_num -= 2 * del_loops;
708 for (
uint i = 0;
i < edges_num;
i++) {
709 const int2 &edge = orig_edges[
i];
710 const uint v1 = vm[edge[0]];
711 const uint v2 = vm[edge[1]];
712 if (edge_adj_faces_len[
i] > 0) {
713 if (
LIKELY(orig_edge_lengths[
i] > FLT_EPSILON)) {
715 mul_v3_fl(edgedir, 1.0f / orig_edge_lengths[
i]);
727 for (
int j = 0; j < link1->
edges_len; j++) {
729 if (edge_adj_faces_len[
e] > 0 &&
e !=
i) {
731 vm[vm[orig_edges[
e][0]] == v1 ? orig_edges[
e][1] : orig_edges[
e][0]];
739 for (
int j = 0; j < link2->
edges_len; j++) {
741 if (edge_adj_faces_len[
e] > 0 &&
e !=
i) {
743 vm[vm[orig_edges[
e][0]] ==
v2 ? orig_edges[
e][1] : orig_edges[
e][0]];
759 const uint *adj_faces_faces = adj_faces->
faces;
761 uint new_edges_len = 0;
764 new_edges_len = adj_len;
766 float ref_nor[3] = {0, 0, 0};
768 for (
uint j = 0; j < adj_len; j++) {
769 const bool reverse = adj_faces_reversed[j];
770 const uint face_i = adj_faces_faces[j];
778 if (orig_faces[face_i].
size() > 3) {
788 sorted_faces[j].
angle = 0.0f;
792 sorted_faces[j].
angle = 0.0f;
798 sorted_faces[j].
face =
799 &face_sides_arr[adj_faces_faces[j] * 2 + (adj_faces_reversed[j] ? 1 : 0)];
807 sorted_faces[0].
face =
808 &face_sides_arr[adj_faces_faces[0] * 2 + (adj_faces_reversed[0] ? 1 : 0)];
818 new_edges[new_edges_len] =
nullptr;
820 for (
uint j = 0; j < new_edges_len; j++) {
823 const uint next_j = j + 1 == adj_len ? 0 : j + 1;
826 sorted_faces[next_j].
face + 1;
834 sorted_faces[0].
face + j;
840 if (do_shell || (adj_len == 1 && do_rim)) {
841 edge_data_edge_index = 0;
851 new_edge_ref.
new_edge = edge_data_edge_index;
852 *edge_data = new_edge_ref;
854 new_edges[j] = edge_data;
855 for (
uint k = 0; k < 2; k++) {
856 if (
faces[k] !=
nullptr) {
857 for (
int l = 0;
l <
faces[k]->face.size();
l++) {
858 const int edge = orig_corner_edges[
faces[k]->face.start() +
l];
859 if (edge_adj_faces[edge] == edge_adj_faces[
i]) {
860 if (edge !=
i && orig_edge_data_arr[edge] ==
nullptr) {
861 orig_edge_data_arr[edge] = new_edges;
863 faces[k]->link_edges[
l] = edge_data;
871 orig_edge_data_arr[
i] = new_edges;
872 if (do_shell || (adj_len == 1 && do_rim)) {
873 new_edges_num += new_edges_len;
879 for (
uint i = 0;
i < edges_num;
i++) {
880 if (edge_adj_faces[
i]) {
881 if (edge_adj_faces[
i]->used > 1) {
882 edge_adj_faces[
i]->
used--;
897 for (
uint i = 0;
i < verts_num;
i++, adj_edges_ptr++) {
898 if (*adj_edges_ptr !=
nullptr && (*adj_edges_ptr)->
edges_len >= 2) {
902 bool contains_long_groups =
false;
903 uint topo_groups = 0;
907 const uint *adj_edges = (*adj_edges_ptr)->edges;
908 const uint tot_adj_edges = (*adj_edges_ptr)->edges_len;
910 uint unassigned_edges_len = 0;
911 for (
uint j = 0; j < tot_adj_edges; j++) {
912 NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]];
918 unassigned_edges_len++;
925 for (
uint j = 0, k = 0; j < tot_adj_edges; j++) {
926 NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]];
929 unassigned_edges[k++] = *new_edges;
937 uint edge_groups_len = unassigned_edges_len / 2;
940 uint assigned_edges_len = 0;
942 uint found_edge_index = 0;
943 bool insert_at_start =
false;
944 uint eg_capacity = 5;
945 NewFaceRef *eg_track_faces[2] = {
nullptr,
nullptr};
948 while (assigned_edges_len < unassigned_edges_len) {
949 found_edge =
nullptr;
950 insert_at_start =
false;
951 if (eg_index >= 0 && edge_groups[eg_index].edges_len == 0) {
957 while (!edge && j < unassigned_edges_len) {
958 edge = unassigned_edges[j++];
959 if (edge && last_open_edge_track &&
960 (edge->
faces[0] != last_open_edge_track || edge->
faces[1] !=
nullptr))
965 if (!edge && last_open_edge_track) {
967 last_open_edge_track =
nullptr;
970 while (!edge && j < unassigned_edges_len) {
971 edge = unassigned_edges[j++];
974 else if (!last_open_edge_track && eg_index > 0) {
979 found_edge_index = j - 1;
981 if (!last_open_edge_track && vm[orig_edges[edge->
old_edge][0]] ==
i) {
982 eg_track_faces[0] = edge->
faces[0];
983 eg_track_faces[1] = edge->
faces[1];
984 if (edge->
faces[1] ==
nullptr) {
990 eg_track_faces[0] = edge->
faces[1];
991 eg_track_faces[1] = edge->
faces[0];
994 else if (eg_index >= 0) {
996 for (found_edge_index = 0; found_edge_index < unassigned_edges_len;
997 found_edge_index++, edge_ptr++)
1001 if (edge->
faces[0] == eg_track_faces[1]) {
1002 insert_at_start =
false;
1003 eg_track_faces[1] = edge->
faces[1];
1005 if (edge->
faces[1] ==
nullptr) {
1012 if (edge->
faces[0] == eg_track_faces[0]) {
1013 insert_at_start =
true;
1014 eg_track_faces[0] = edge->
faces[1];
1016 if (edge->
faces[1] ==
nullptr) {
1021 if (edge->
faces[1] !=
nullptr) {
1022 if (edge->
faces[1] == eg_track_faces[1]) {
1023 insert_at_start =
false;
1024 eg_track_faces[1] = edge->
faces[0];
1028 if (edge->
faces[1] == eg_track_faces[0]) {
1029 insert_at_start =
true;
1030 eg_track_faces[0] = edge->
faces[0];
1039 unassigned_edges[found_edge_index] =
nullptr;
1040 assigned_edges_len++;
1041 const uint needed_capacity = edge_groups[eg_index].
edges_len + 1;
1042 if (needed_capacity > eg_capacity) {
1043 eg_capacity = needed_capacity + 1;
1045 if (insert_at_start) {
1047 edge_groups[eg_index].edges,
1048 edge_groups[eg_index].edges_len *
sizeof(*new_eg));
1052 edge_groups[eg_index].edges,
1053 edge_groups[eg_index].edges_len *
sizeof(*new_eg));
1056 edge_groups[eg_index].
edges = new_eg;
1058 else if (insert_at_start) {
1059 memmove(edge_groups[eg_index].edges + 1,
1060 edge_groups[eg_index].edges,
1061 edge_groups[eg_index].edges_len *
sizeof(*edge_groups[eg_index].edges));
1063 edge_groups[eg_index].
edges[insert_at_start ? 0 : edge_groups[eg_index].
edges_len] =
1066 if (edge_groups[eg_index].edges[edge_groups[eg_index].edges_len - 1]->
faces[1] !=
1069 last_open_edge_track =
nullptr;
1071 if (edge_groups[eg_index].edges_len > 3) {
1072 contains_long_groups =
true;
1084 edge_group.
valid =
true;
1085 edge_group.
edges = edges;
1090 edge_group.
split = 0;
1096 edge_groups[eg_index] = edge_group;
1098 eg_track_faces[0] =
nullptr;
1099 eg_track_faces[1] =
nullptr;
1116 if (contains_long_groups) {
1118 for (
uint j = 0; j < eg_index; j++) {
1119 const uint edges_len = edge_groups[j + add_index].
edges_len;
1120 if (edges_len > 3) {
1121 bool has_doubles =
false;
1123 EdgeGroup g = edge_groups[j + add_index];
1124 for (
uint k = 0; k < edges_len; k++) {
1125 for (
uint l = k + 1;
l < edges_len;
l++) {
1134 const uint prior_splits = splits;
1135 const uint prior_index = add_index;
1136 int unique_start = -1;
1137 int first_unique_end = -1;
1138 int last_split = -1;
1139 int first_split = -1;
1140 bool first_even_split =
false;
1142 while (real_k < edges_len ||
1145 (first_unique_end == -1 ? 0 : first_unique_end) +
int(edges_len) ||
1146 first_split != last_split)))
1148 const uint k = real_k % edges_len;
1150 if (first_unique_end != -1 && unique_start == -1) {
1151 unique_start = int(real_k);
1154 else if (first_unique_end == -1) {
1155 first_unique_end = int(k);
1157 else if (unique_start != -1) {
1158 const uint split = ((
uint(unique_start) + real_k + 1) / 2) % edges_len;
1159 const bool is_even_split = ((
uint(unique_start) + real_k) & 1);
1160 if (last_split != -1) {
1162 if (prior_splits != splits) {
1163 memmove(edge_groups + j + add_index + 1,
1164 edge_groups + j + add_index,
1165 (
uint(eg_index) - j) *
sizeof(*edge_groups));
1168 if (last_split >
split) {
1169 const uint edges_len_group = (
split + edges_len) -
uint(last_split);
1173 g.
edges + last_split,
1174 (edges_len -
uint(last_split)) *
sizeof(*edges));
1175 memcpy(edges + (edges_len -
uint(last_split)),
1177 split *
sizeof(*edges));
1180 edge_group.
valid =
true;
1181 edge_group.
edges = edges;
1192 edge_groups[j + add_index] = edge_group;
1198 memcpy(edges, g.
edges + last_split, edges_len_group *
sizeof(*edges));
1201 edge_group.
valid =
true;
1202 edge_group.
edges = edges;
1213 edge_groups[j + add_index] = edge_group;
1217 last_split = int(
split);
1218 if (first_split == -1) {
1219 first_split = int(
split);
1220 first_even_split = is_even_split;
1226 if (first_split != -1) {
1228 if (prior_splits != splits) {
1229 memmove(edge_groups + (j + prior_index + 1),
1230 edge_groups + (j + prior_index),
1231 (
uint(eg_index) + add_index - (j + prior_index)) *
1232 sizeof(*edge_groups));
1233 memmove(edge_groups + (j + add_index + 2),
1234 edge_groups + (j + add_index + 1),
1235 (
uint(eg_index) - j) *
sizeof(*edge_groups));
1239 memmove(edge_groups + (j + add_index + 2),
1240 edge_groups + (j + add_index + 1),
1241 (
uint(eg_index) - j - 1) *
sizeof(*edge_groups));
1245 memcpy(edges, g.
edges,
uint(first_split) *
sizeof(*edges));
1248 edge_group_a.
valid =
true;
1249 edge_group_a.
edges = edges;
1254 edge_group_a.
split = 1;
1260 edge_groups[j + prior_index] = edge_group_a;
1267 g.
edges + last_split,
1268 (edges_len -
uint(last_split)) *
sizeof(*edges));
1271 edge_group_b.
valid =
true;
1272 edge_group_b.
edges = edges;
1277 edge_group_b.
split = add_index - prior_index + 1;
1283 edge_groups[j + add_index] = edge_group_b;
1285 if (prior_splits != splits) {
1289 if (first_unique_end != -1 && prior_splits == splits) {
1290 has_singularities =
true;
1300 orig_vert_groups_arr[
i] = edge_groups;
1304 bool contains_open_splits =
false;
1305 uint open_edges = 0;
1306 uint contains_splits = 0;
1307 uint last_added = 0;
1308 uint first_added = 0;
1309 bool first_set =
false;
1312 for (
uint j = 0; j < g->edges_len; j++,
e++) {
1313 const uint flip =
uint(vm[orig_edges[(*e)->old_edge][1]] ==
i);
1314 BLI_assert(flip || vm[orig_edges[(*e)->old_edge][0]] ==
i);
1315 (*e)->link_edge_groups[flip] = g;
1318 if (do_shell || (do_rim && !g->is_orig_closed)) {
1320 g->new_vert = new_verts_num++;
1321 if (do_rim || (do_shell && g->split)) {
1323 contains_splits += (g->split != 0);
1324 contains_open_splits |= g->split && !g->is_orig_closed;
1328 open_edges +=
uint(added < last_added);
1331 first_added = added;
1334 if (!(g + 1)->valid || g->topo_group != (g + 1)->topo_group) {
1335 if (new_verts > 2) {
1337 new_edges_num += new_verts;
1338 open_edges +=
uint(first_added < last_added);
1339 open_edges -=
uint(open_edges && !contains_open_splits);
1340 if (do_shell && do_rim) {
1341 new_loops_num += new_verts * 2;
1343 else if (do_shell) {
1344 new_loops_num += new_verts * 2 - open_edges;
1347 new_loops_num += new_verts * 2 + open_edges - contains_splits;
1350 else if (new_verts == 2) {
1352 new_loops_num += 2u -
uint(!(do_rim && do_shell) && contains_open_splits);
1355 contains_open_splits =
false;
1356 contains_splits = 0;
1387 float *face_weight =
nullptr;
1389 if (do_flat_faces) {
1393 float scalar_vgroup = 1.0f;
1394 for (
const int vert : orig_corner_verts.
slice(orig_faces[
i])) {
1396 if (defgrp_invert) {
1404 scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv);
1405 face_weight[
i] = scalar_vgroup;
1409 gs_ptr = orig_vert_groups_arr;
1410 for (
uint i = 0;
i < verts_num;
i++, gs_ptr++) {
1413 if (!g->is_singularity) {
1419 float move_nor[3] = {0, 0, 0};
1422 (g->is_orig_closed || g->split));
1423 bool approximate_free_direction =
false;
1430 uint queue_index = 0;
1432 float fallback_nor[3];
1433 float fallback_ofs = 0.0f;
1435 const bool cycle = (g->is_orig_closed && !g->split) || g->is_even_split;
1436 for (
uint k = 0; k < g->edges_len; k++, edge_ptr++) {
1437 if (!(k & 1) || (!cycle && k == g->edges_len - 1)) {
1439 for (
uint l = 0;
l < 2;
l++) {
1441 if (face && (first_edge ==
nullptr ||
1442 (first_edge->
faces[0] != face && first_edge->
faces[1] != face)))
1444 float ofs = face->
reversed ? ofs_back_clamped : ofs_front_clamped;
1446 if (do_flat_faces) {
1447 ofs *= face_weight[face->
index];
1450 if (!null_faces[face->
index]) {
1453 face_nors[face->
index],
1455 planes_queue[queue_index++][3] = ofs;
1465 if ((cycle && k == 0) || (!cycle && k + 3 >= g->edges_len)) {
1470 if (queue_index > 2) {
1475 for (
uint k = 0; k < queue_index; k++) {
1476 for (
uint m = k + 1; m < queue_index; m++) {
1477 float p =
dot_v3v3(planes_queue[k], planes_queue[m]);
1487 swap_v4_v4(planes_queue[min_n0], planes_queue[0]);
1488 swap_v4_v4(planes_queue[min_n1], planes_queue[1]);
1491 swap_v4_v4(planes_queue[min_n0], planes_queue[1]);
1496 float max_p = -1.0f;
1497 for (
uint k = 2; k < queue_index; k++) {
1499 dot_v3v3(planes_queue[1], planes_queue[k]));
1500 if (max_p <= min_p) {
1505 swap_v4_v4(planes_queue[min_n1], planes_queue[2]);
1508 while (queue_index > 2) {
1511 float best_p = -1.0f;
1512 float best_ofs_diff = 0.0f;
1513 for (
uint k = 0; k < queue_index; k++) {
1514 for (
uint m = k + 1; m < queue_index; m++) {
1515 float p =
dot_v3v3(planes_queue[m], planes_queue[k]);
1516 float ofs_diff =
fabsf(planes_queue[m][3] - planes_queue[k][3]);
1517 if (p > best_p + FLT_EPSILON || (p >= best_p && ofs_diff < best_ofs_diff)) {
1519 best_ofs_diff = ofs_diff;
1527 if (best_p < 0.98f) {
1530 add_v3_v3(planes_queue[best_n0], planes_queue[best_n1]);
1532 planes_queue[best_n0][3] = (planes_queue[best_n0][3] + planes_queue[best_n1][3]) *
1535 memmove(planes_queue + best_n1,
1536 planes_queue + best_n1 + 1,
1537 (queue_index - best_n1) *
sizeof(*planes_queue));
1547 const float boundary_fix_threshold = 0.7f;
1552 for (
int k = 0; k < 3; k++) {
1553 for (
int m = 0; m <
size; m++) {
1554 madd_v3_v3fl(mat[k], planes_queue[m], planes_queue[m][k]);
1564 for (
int k = 0; k <
size; k++) {
1569 if (!disable_boundary_fix) {
1571 float greatest_angle_cos = 1.0f;
1572 for (
uint k = 0; k < 2; k++) {
1574 float p =
dot_v3v3(planes_queue[m], planes_queue[k]);
1575 greatest_angle_cos = std::min(p, greatest_angle_cos);
1578 if (greatest_angle_cos > boundary_fix_threshold) {
1579 approximate_free_direction =
true;
1582 disable_boundary_fix =
true;
1586 else if (
size > 1) {
1589 const float q =
dot_v3v3(planes_queue[0], planes_queue[1]);
1590 float d = 1.0f - q * q;
1593 if (d > FLT_EPSILON * 10 && q < stop_explosion) {
1595 mul_v3_fl(planes_queue[0], (planes_queue[0][3] - planes_queue[1][3] * q) * d);
1596 mul_v3_fl(planes_queue[1], (planes_queue[1][3] - planes_queue[0][3] * q) * d);
1599 d = 1.0f / (
fabsf(q) + 1.0f);
1600 mul_v3_fl(planes_queue[0], planes_queue[0][3] * d);
1601 mul_v3_fl(planes_queue[1], planes_queue[1][3] * d);
1605 d =
dot_v3v3(planes_queue[2], move_nor);
1608 if (
fabsf(d) > 0.02f) {
1614 if (
fabsf(d) > 1.0f - boundary_fix_threshold) {
1615 disable_boundary_fix =
true;
1619 approximate_free_direction =
false;
1621 else if (
size == 1) {
1624 if (g->edges_len > 2) {
1625 disable_boundary_fix =
true;
1626 approximate_free_direction =
true;
1632 disable_boundary_fix =
true;
1638 float total_angle = 0;
1639 float total_angle_back = 0;
1643 float nor_back[3] = {0, 0, 0};
1644 bool has_back =
false;
1645 bool has_front =
false;
1646 bool cycle = (g->is_orig_closed && !g->split) || g->is_even_split;
1647 for (
uint k = 0; k < g->edges_len; k++, edge_ptr++) {
1648 if (!(k & 1) || (!cycle && k == g->edges_len - 1)) {
1650 for (
uint l = 0;
l < 2;
l++) {
1652 if (face && (first_edge ==
nullptr ||
1653 (first_edge->
faces[0] != face && first_edge->
faces[1] != face)))
1656 float ofs = face->
reversed ? -ofs_back_clamped : ofs_front_clamped;
1658 if (do_flat_faces) {
1659 ofs *= face_weight[face->
index];
1666 int corner = corner_next + (face->
face.
size() - 1);
1667 int corner_prev = corner - 1;
1670 m < face->
face.
size() && vm[orig_corner_verts[corner]] !=
i;
1673 corner_prev = corner;
1674 corner = corner_next;
1678 orig_mvert_co[vm[orig_corner_verts[corner_next]]]);
1680 total_angle_back +=
angle * ofs * ofs;
1683 total_angle +=
angle * ofs * ofs;
1705 if ((cycle && k == 0) || (!cycle && k + 3 >= g->edges_len)) {
1715 if (
LIKELY(length_sq > FLT_EPSILON)) {
1721 if (
LIKELY(length_sq > FLT_EPSILON)) {
1722 mul_v3_fl(nor_back, total_angle_back / length_sq);
1728 if (has_front && has_back) {
1730 float nor_back_length =
len_v3(nor_back);
1733 q /= nor_length * nor_back_length;
1735 float d = 1.0f - q * q;
1736 if (
LIKELY(d > FLT_EPSILON)) {
1738 if (
LIKELY(nor_length > FLT_EPSILON)) {
1739 mul_v3_fl(
nor, (1 - nor_back_length * q / nor_length) * d);
1741 if (
LIKELY(nor_back_length > FLT_EPSILON)) {
1742 mul_v3_fl(nor_back, (1 - nor_length * q / nor_back_length) * d);
1754 if (has_front && total_angle > FLT_EPSILON) {
1757 if (has_back && total_angle_back > FLT_EPSILON) {
1758 mul_v3_fl(nor_back, 1.0f / total_angle_back);
1760 if (has_front && total_angle > FLT_EPSILON) {
1766 if (!disable_boundary_fix && g->edges_len > 2) {
1767 approximate_free_direction =
true;
1770 disable_boundary_fix =
true;
1773 if (approximate_free_direction) {
1778 for (k = 1; k + 1 < g->edges_len; k++, edge_ptr++) {
1779 const int2 &edge = orig_edges[(*edge_ptr)->old_edge];
1781 tmp, orig_mvert_co[vm[edge[0]] ==
i ? edge[1] : edge[0]], orig_mvert_co[
i]);
1785 disable_boundary_fix =
true;
1792 if (!disable_boundary_fix) {
1794 float constr_nor[3];
1795 const int2 &e0_edge = orig_edges[g->edges[0]->old_edge];
1796 const int2 &e1_edge = orig_edges[g->edges[g->edges_len - 1]->old_edge];
1800 orig_mvert_co[vm[e0_edge[0]] ==
i ? e0_edge[1] : e0_edge[0]],
1803 orig_mvert_co[vm[e1_edge[0]] ==
i ? e1_edge[1] : e1_edge[0]],
1814 if (g->edges[0]->faces[0]->reversed) {
1815 negate_v3_v3(f0, face_nors[g->edges[0]->faces[0]->index]);
1818 copy_v3_v3(f0, face_nors[g->edges[0]->faces[0]->index]);
1820 if (g->edges[g->edges_len - 1]->faces[0]->reversed) {
1821 negate_v3_v3(f1, face_nors[g->edges[g->edges_len - 1]->faces[0]->index]);
1824 copy_v3_v3(f1, face_nors[g->edges[g->edges_len - 1]->faces[0]->index]);
1835 float d =
dot_v3v3(constr_nor, move_nor);
1837 if (
fabsf(d) > 0.1f) {
1842 float scalar_vgroup = 1;
1844 if (dvert && !do_flat_faces) {
1846 if (defgrp_invert) {
1852 scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv);
1856 if (do_angle_clamp) {
1857 if (g->edges_len > 2) {
1858 float min_length = 0;
1861 for (
NewEdgeRef **p = g->edges; k < g->edges_len; k++, p++) {
1862 float length = orig_edge_lengths[(*p)->old_edge];
1863 float e_ang = (*p)->angle;
1865 if (
length < min_length || k == 0) {
1871 float max_off = min_length * 0.5f / cos_ang;
1872 if (max_off < offset * 0.5f) {
1873 scalar_vgroup *= max_off / offset * 2;
1879 float min_length = 0;
1881 for (
NewEdgeRef **p = g->edges; k < g->edges_len; k++, p++) {
1882 float length = orig_edge_lengths[(*p)->old_edge];
1883 if (
length < min_length || k == 0) {
1887 if (min_length < offset) {
1888 scalar_vgroup *= min_length / offset;
1902 if (do_flat_faces) {
1916 uint(*singularity_edges)[2] =
nullptr;
1917 uint totsingularity = 0;
1918 if (has_singularities) {
1919 has_singularities =
false;
1921 uint singularity_edges_len = 1;
1923 for (
NewEdgeRef ***new_edges = orig_edge_data_arr;
i < edges_num;
i++, new_edges++) {
1924 if (*new_edges && (do_shell || edge_adj_faces_len[
i] == 1) && (**new_edges)->old_edge ==
i) {
1926 if ((*l)->link_edge_groups[0]->is_singularity &&
1927 (*l)->link_edge_groups[1]->is_singularity)
1929 const uint v1 = (*l)->link_edge_groups[0]->new_vert;
1930 const uint v2 = (*l)->link_edge_groups[1]->new_vert;
1931 bool exists_already =
false;
1933 for (
uint(*p)[2] = singularity_edges; j < totsingularity; p++, j++) {
1934 if (((*p)[0] == v1 && (*p)[1] ==
v2) || ((*p)[0] ==
v2 && (*p)[1] == v1)) {
1935 exists_already =
true;
1939 if (!exists_already) {
1940 has_singularities =
true;
1941 if (singularity_edges_len <= totsingularity) {
1942 singularity_edges_len = totsingularity + 1;
1943 singularity_edges =
static_cast<uint(*)[2]
>(
1945 singularity_edges_len *
sizeof(*singularity_edges),
1948 singularity_edges[totsingularity][0] = v1;
1949 singularity_edges[totsingularity][1] =
v2;
1951 if (edge_adj_faces_len[
i] == 1 && do_rim) {
1967 mesh,
int(new_verts_num),
int(new_edges_num),
int(new_faces_num),
int(new_loops_num));
1975 int *origindex_edge =
static_cast<int *
>(
1977 int *origindex_face =
static_cast<int *
>(
1982 if (!result_edge_bweight && (bevel_convex != 0.0f || orig_vert_bweight !=
nullptr)) {
1987 "bevel_weight_edge"));
1992 if (shell_defgrp_index != -1 || rim_defgrp_index != -1) {
1993 dst_dvert =
result->deform_verts_for_write().data();
1998 const float *vertex_crease =
static_cast<const float *
>(
2000 float *result_edge_crease =
nullptr;
2001 if (vertex_crease || orig_edge_crease) {
2004 if (!result_edge_crease) {
2016 gs_ptr = orig_vert_groups_arr;
2017 for (
uint i = 0;
i < verts_num;
i++, gs_ptr++) {
2024 copy_v3_v3(vert_positions[g->new_vert], g->co);
2034 edge_index += totsingularity;
2035 for (
NewEdgeRef ***new_edges = orig_edge_data_arr;
i < edges_num;
i++, new_edges++) {
2036 if (*new_edges && (do_shell || edge_adj_faces_len[
i] == 1) && (**new_edges)->old_edge ==
i) {
2039 const uint v1 = (*l)->link_edge_groups[0]->new_vert;
2040 const uint v2 = (*l)->link_edge_groups[1]->new_vert;
2042 if (has_singularities && ((*l)->link_edge_groups[0]->is_singularity &&
2043 (*l)->link_edge_groups[1]->is_singularity))
2046 for (
uint(*p)[2] = singularity_edges; j < totsingularity; p++, j++) {
2047 if (((*p)[0] == v1 && (*p)[1] ==
v2) || ((*p)[0] ==
v2 && (*p)[1] == v1)) {
2062 if (result_edge_crease) {
2063 result_edge_crease[
insert] = orig_edge_crease ? orig_edge_crease[(*l)->old_edge] :
2066 if (result_edge_bweight) {
2067 result_edge_bweight[
insert] = orig_edge_bweight ? orig_edge_bweight[(*l)->old_edge] :
2070 if (bevel_convex != 0.0f && (*l)->faces[1] !=
nullptr) {
2072 result_edge_bweight[
insert] +
2073 ((*l)->angle >
M_PI + FLT_EPSILON ?
2074 clamp_f(bevel_convex, 0.0f, 1.0f) :
2075 ((*l)->angle <
M_PI - FLT_EPSILON ?
clamp_f(bevel_convex, -1.0f, 0.0f) :
2086 if (singularity_edges) {
2110 gs_ptr = orig_vert_groups_arr;
2111 for (
uint i = 0;
i < verts_num;
i++, gs_ptr++) {
2118 for (
uint j = 0; j < g->edges_len; j++,
e++) {
2119 printf(
"%u/%d, ", (*e)->old_edge,
int(*e)->new_edge);
2121 printf(
"(tg:%u)(s:%u,c:%d)\n", g->topo_group, g->split, g->is_orig_closed);
2128 const VArraySpan src_material_index = *src_attributes.
lookup<
int>(
"material_index",
2136 gs_ptr = orig_vert_groups_arr;
2137 for (
uint i = 0;
i < verts_num;
i++, gs_ptr++) {
2144 float mv_crease = vertex_crease ? vertex_crease[
i] : 0.0f;
2145 float mv_bweight = orig_vert_bweight ? orig_vert_bweight[
i] : 0.0f;
2148 float last_max_crease = 0.0f;
2149 float first_max_crease = 0.0f;
2151 float last_max_bweight = 0.0f;
2152 float first_max_bweight = 0.0f;
2161 if (result_edge_crease) {
2162 if (orig_edge_crease) {
2174 if (result_edge_crease) {
2175 if (orig_edge_crease && orig_edge_crease[orig_edge_index] > max_crease) {
2176 max_crease = orig_edge_crease[orig_edge_index];
2180 if (result_edge_bweight) {
2182 max_bweight = std::max(bweight, max_bweight);
2188 const float bweight_open_edge =
2193 if (bweight_open_edge > 0) {
2194 max_bweight =
min_ff(bweight_open_edge, max_bweight);
2197 if (bevel_convex < 0.0f) {
2203 first_max_crease = max_crease;
2204 first_max_bweight = max_bweight;
2213 if (origindex_edge) {
2216 edges[edge_index][0] = last_g->
new_vert;
2217 edges[edge_index][1] = g->
new_vert;
2218 if (result_edge_crease) {
2219 result_edge_crease[edge_index] =
max_ff(mv_crease,
2220 min_ff(last_max_crease, max_crease));
2222 if (result_edge_bweight) {
2223 result_edge_bweight[edge_index] =
max_ff(mv_bweight,
2224 min_ff(last_max_bweight, max_bweight));
2229 last_max_crease = max_crease;
2230 last_max_bweight = max_bweight;
2233 if (!(g + 1)->valid || g->
topo_group != (g + 1)->topo_group) {
2243 if (origindex_edge) {
2247 edges[edge_index][0] = last_g->
new_vert;
2248 edges[edge_index][1] = first_g->
new_vert;
2249 if (result_edge_crease) {
2250 result_edge_crease[edge_index] =
max_ff(mv_crease,
2251 min_ff(last_max_crease, first_max_crease));
2253 if (result_edge_bweight) {
2254 result_edge_bweight[edge_index] =
max_ff(
2255 mv_bweight,
min_ff(last_max_bweight, first_max_bweight));
2262 short most_mat_nr = 0;
2263 uint most_mat_nr_face = 0;
2264 uint most_mat_nr_count = 0;
2265 for (
short l = 0;
l < mat_nrs;
l++) {
2270 if ((do_rim && !g3->is_orig_closed) || (do_shell && g3->split)) {
2272 if ((!src_material_index.
is_empty() ?
2273 src_material_index[g3->edges[0]->faces[0]->index] :
2276 face = g3->edges[0]->faces[0]->index;
2279 NewEdgeRef *le = g3->edges[g3->edges_len - 1];
2297 if (
count > most_mat_nr_count) {
2299 most_mat_nr_face = face;
2300 most_mat_nr_count =
count;
2304 &mesh->
face_data, &
result->face_data,
int(most_mat_nr_face),
int(face_index), 1);
2305 if (origindex_face) {
2308 face_offsets[face_index] = int(loop_index);
2312 CLAMP(dst_material_index.
span[face_index], 0, mat_nr_max);
2315 for (
uint k = 0; g2->
valid && k < j; g2++) {
2318 for (
int l = 0;
l < face.
size();
l++) {
2319 const int vert = orig_corner_verts[face[
l]];
2320 if (vm[vert] ==
i) {
2321 loops_data[k] = face[
l];
2330 for (
uint k = 0; k < j; k++) {
2333 corner_verts[loop_index] = edges[edge_index - j + k][0];
2334 corner_edges[loop_index++] = edge_index - j + k;
2338 for (
uint k = 1; k <= j; k++) {
2344 corner_verts[loop_index] = edges[edge_index - k][1];
2345 corner_edges[loop_index++] = edge_index - k;
2354 last_max_crease = 0;
2355 first_max_crease = 0;
2356 last_max_bweight = 0;
2357 first_max_bweight = 0;
2366 for (
uint i = 0;
i < edges_num;
i++) {
2367 if (edge_adj_faces_len[
i] == 1 && orig_edge_data_arr[
i] &&
2368 (*orig_edge_data_arr[
i])->old_edge ==
i)
2378 if (v1_singularity && v2_singularity) {
2382 const uint orig_face_index = (*new_edges)->faces[0]->index;
2386 int((*new_edges)->faces[0]->index),
2389 face_offsets[face_index] = int(loop_index);
2390 dst_material_index.
span[face_index] = (!src_material_index.
is_empty() ?
2391 src_material_index[orig_face_index] :
2394 CLAMP(dst_material_index.
span[face_index], 0, mat_nr_max);
2399 const uint old_v1 = vm[orig_edges[edge1->
old_edge][0]];
2400 const uint old_v2 = vm[orig_edges[edge1->
old_edge][1]];
2401 for (
uint j = 0; j < face.
size(); j++) {
2402 const int vert = orig_corner_verts[face.
start() + j];
2403 if (vm[vert] == old_v1) {
2404 loop1 = face.
start() + int(j);
2406 else if (vm[vert] == old_v2) {
2407 loop2 = face.
start() + int(j);
2411 int2 open_face_edge;
2412 uint open_face_edge_index;
2414 if (rim_defgrp_index != -1) {
2420 corner_verts[loop_index] = edges[edge1->
new_edge][0];
2421 corner_edges[loop_index++] = edge1->
new_edge;
2423 if (!v2_singularity) {
2425 if (rim_defgrp_index != -1) {
2431 corner_verts[loop_index] = edges[edge1->
new_edge][1];
2432 open_face_edge = edges[open_face_edge_index];
2433 if (
ELEM(edges[edge2->
new_edge][1], open_face_edge[0], open_face_edge[1])) {
2434 corner_edges[loop_index++] = open_face_edge_index;
2441 if (rim_defgrp_index != -1) {
2447 corner_verts[loop_index] = edges[edge2->
new_edge][1];
2448 corner_edges[loop_index++] = edge2->
new_edge;
2450 if (!v1_singularity) {
2452 if (rim_defgrp_index != -1) {
2458 corner_verts[loop_index] = edges[edge2->
new_edge][0];
2459 open_face_edge = edges[open_face_edge_index];
2460 if (
ELEM(edges[edge1->
new_edge][0], open_face_edge[0], open_face_edge[1])) {
2461 corner_edges[loop_index++] = open_face_edge_index;
2469 if (!v1_singularity) {
2471 if (rim_defgrp_index != -1) {
2477 corner_verts[loop_index] = edges[edge1->
new_edge][0];
2478 open_face_edge = edges[open_face_edge_index];
2479 if (
ELEM(edges[edge2->
new_edge][0], open_face_edge[0], open_face_edge[1])) {
2480 corner_edges[loop_index++] = open_face_edge_index;
2487 if (rim_defgrp_index != -1) {
2493 corner_verts[loop_index] = edges[edge2->
new_edge][0];
2494 corner_edges[loop_index++] = edge2->
new_edge;
2496 if (!v2_singularity) {
2498 if (rim_defgrp_index != -1) {
2504 corner_verts[loop_index] = edges[edge2->
new_edge][1];
2505 open_face_edge = edges[open_face_edge_index];
2506 if (
ELEM(edges[edge1->
new_edge][1], open_face_edge[0], open_face_edge[1])) {
2507 corner_edges[loop_index++] = open_face_edge_index;
2514 if (rim_defgrp_index != -1) {
2520 corner_verts[loop_index] = edges[edge1->
new_edge][1];
2521 corner_edges[loop_index++] = edge1->
new_edge;
2532 for (
uint i = 0;
i < faces_num * 2;
i++) {
2536 uint valid_edges = 0;
2538 while (totloop > 0 && (!fr.
link_edges[totloop - 1] ||
2546 vm[orig_corner_verts[loopstart + (totloop - 1)]]);
2547 for (
uint j = 0; j < totloop; j++) {
2552 vm[orig_corner_verts[loopstart + j]]);
2554 vm[orig_corner_verts[loopstart + j]]);
2559 if (k == 0 || face_verts[k - 1] != new_v1) {
2560 face_loops[k] = loopstart + j;
2567 BLI_assert(k == 0 || edges[face_edges[k]][1] == face_verts[k - 1] ||
2568 edges[face_edges[k]][0] == face_verts[k - 1]);
2570 edges[face_edges[k]][1] == new_v1 || edges[face_edges[k]][0] == new_v1);
2571 face_verts[k++] = new_v1;
2573 prior_edge = new_edge;
2574 prior_flip = 1 - flip;
2575 if (j < totloop - 1 || face_verts[0] != new_v2) {
2576 face_loops[k] = loopstart + (j + 1) % totloop;
2577 face_edges[k] = new_edge->
new_edge;
2578 face_verts[k++] = new_v2;
2581 face_edges[0] = new_edge->
new_edge;
2585 if (k > 2 && valid_edges > 2) {
2588 face_offsets[face_index] = int(loop_index);
2589 dst_material_index.
span[face_index] = (!src_material_index.
is_empty() ?
2590 src_material_index[fr.
index] :
2592 (fr.
reversed != do_flip ? mat_ofs : 0);
2593 CLAMP(dst_material_index.
span[face_index], 0, mat_nr_max);
2595 for (
int l =
int(k) - 1;
l >= 0;
l--) {
2596 if (shell_defgrp_index != -1) {
2605 corner_verts[loop_index] = face_verts[
l];
2606 corner_edges[loop_index++] = face_edges[
l];
2611 for (
uint next_l = 0; next_l < k; next_l++) {
2617 corner_verts[loop_index] = face_verts[
l];
2618 corner_edges[loop_index++] = face_edges[next_l];
2630 if (edge_index != new_edges_num) {
2633 "Internal Error: edges array wrong size: %u instead of %u",
2637 if (face_index != new_faces_num) {
2640 "Internal Error: faces array wrong size: %u instead of %u",
2644 if (loop_index != new_loops_num) {
2647 "Internal Error: loops array wrong size: %u instead of %u",
2660 for (
EdgeGroup **p = orig_vert_groups_arr;
i < verts_num;
i++, p++) {
2670 for (
NewEdgeRef ***p = orig_edge_data_arr + (edges_num - 1);
i > 0;
i--, p--) {
2671 if (*p && (**p)->old_edge ==
i - 1) {
2686#undef MOD_SOLIDIFY_EMPTY_TAG
2688 dst_material_index.
finish();