142 const uint verts_num =
uint(mesh->verts_num);
143 const uint edges_num =
uint(mesh->edges_num);
144 const uint faces_num =
uint(mesh->faces_num);
146 if (faces_num == 0 && verts_num != 0) {
152 const short mat_nr_max = mat_nrs - 1;
153 const short mat_ofs = mat_nrs > 1 ? smd->
mat_ofs : 0;
154 const short mat_ofs_rim = mat_nrs > 1 ? smd->
mat_ofs_rim : 0;
163 const float ofs_front_clamped =
clamp_nonzero(ofs_front, 1e-5f);
164 const float ofs_back_clamped =
clamp_nonzero(ofs_back, 1e-5f);
196 const float *orig_vert_bweight =
static_cast<const float *
>(
198 const float *orig_edge_bweight =
static_cast<const float *
>(
200 const float *orig_edge_crease =
static_cast<const float *
>(
203 uint new_verts_num = 0;
204 uint new_edges_num = 0;
205 uint new_loops_num = 0;
206 uint new_faces_num = 0;
208#define MOD_SOLIDIFY_EMPTY_TAG uint(-1)
217 static_cast<bool *
>(
MEM_calloc_arrayN(faces_num,
sizeof(*null_faces), __func__)) :
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;
244 new_face_ref_a.
face = face;
245 new_face_ref_a.index =
uint(i);
246 new_face_ref_a.reversed =
false;
247 new_face_ref_a.link_edges = link_edges;
248 face_sides_arr[i * 2] = new_face_ref_a;
254 new_face_ref_b.
face = face;
255 new_face_ref_b.index =
uint(i);
256 new_face_ref_b.reversed =
true;
257 new_face_ref_b.link_edges = link_edges;
258 face_sides_arr[i * 2 + 1] = new_face_ref_b;
260 if (face.size() > largest_ngon) {
261 largest_ngon =
uint(face.size());
266 new_loops_num +=
uint(face.size() * 2);
271 uint *edge_adj_faces_len =
static_cast<uint *
>(
276 for (
const int64_t edge : orig_corner_edges.
slice(orig_faces[i])) {
277 edge_adj_faces_len[edge]++;
286 float *orig_edge_lengths =
static_cast<float *
>(
293 for (
uint i = 0; i < verts_num; i++) {
301 bool has_singularities =
false;
307 float(*orig_mvert_co)[3] =
static_cast<float(*)[3]
>(
310 for (
uint i = 0; i < verts_num; i++) {
311 orig_mvert_co[i][0] = orig_vert_positions[i][0];
312 orig_mvert_co[i][1] = orig_vert_positions[i][1];
313 orig_mvert_co[i][2] = orig_vert_positions[i][2];
324 for (
const int64_t corner : orig_faces[i]) {
325 const int vert = orig_corner_verts[corner];
326 const int edge = orig_corner_edges[corner];
327 const bool reversed = orig_edges[edge][1] != vert;
329 if (old_face_edge_ref ==
nullptr) {
330 const uint len = edge_adj_faces_len[edge];
332 uint *adj_faces =
static_cast<uint *
>(
334 bool *adj_faces_reversed =
static_cast<bool *
>(
336 adj_faces[0] =
uint(i);
337 for (
uint k = 1; k <
len; k++) {
340 adj_faces_reversed[0] = reversed;
344 edge_adj_faces[edge] = ref;
359 float edgedir[3] = {0, 0, 0};
360 uint *vert_adj_edges_len =
static_cast<uint *
>(
365 bool *face_singularity =
static_cast<bool *
>(
369 uint *combined_verts =
static_cast<uint *
>(
372 for (
uint i = 0; i < edges_num; i++) {
373 const int2 &edge = orig_edges[i];
374 if (edge_adj_faces_len[i] > 0) {
375 uint v1 = vm[edge[0]];
387 if (orig_edge_lengths[i] <= merge_tolerance_sqr) {
391 bool can_merge =
true;
392 for (
uint k = 0; k < edges_num && can_merge; k++) {
393 if (k != i && edge_adj_faces_len[k] > 0 &&
394 (
ELEM(vm[orig_edges[k][0]], v1,
v2) !=
ELEM(vm[orig_edges[k][1]], v1,
v2)))
396 for (
uint j = 0; j < edge_adj_faces[k]->
faces_len && can_merge; j++) {
399 int cur = face.
size() - 1;
400 for (
int next = 0;
next < face.size() && changes <= 2;
next++) {
401 uint cur_v = vm[orig_corner_verts[face[cur]]];
402 uint next_v = vm[orig_corner_verts[face[
next]]];
403 changes += (
ELEM(cur_v, v1,
v2) !=
ELEM(next_v, v1,
v2));
406 can_merge = can_merge && changes <= 2;
412 orig_edge_lengths[i] = 0.0f;
413 vert_adj_edges_len[v1]++;
414 vert_adj_edges_len[
v2]++;
419 (combined_verts[
v2] + 1) /
420 float(combined_verts[v1] + combined_verts[
v2] + 2));
422 for (
uint j =
v2; j < verts_num; j++) {
427 vert_adj_edges_len[v1] += vert_adj_edges_len[
v2];
428 vert_adj_edges_len[
v2] = 0;
429 combined_verts[v1] += combined_verts[
v2] + 1;
432 new_loops_num -= edge_adj_faces_len[i] * 2;
435 edge_adj_faces_len[i] = 0;
437 MEM_freeN(edge_adj_faces[i]->faces_reversed);
439 edge_adj_faces[i] =
nullptr;
442 orig_edge_lengths[i] =
sqrtf(orig_edge_lengths[i]);
443 vert_adj_edges_len[v1]++;
444 vert_adj_edges_len[
v2]++;
449 for (
uint i = 0; i < edges_num; i++) {
450 const int2 &edge = orig_edges[i];
451 const uint v1 = vm[edge[0]];
452 const uint v2 = vm[edge[1]];
453 if (v1 ==
v2 && edge_adj_faces[i]) {
456 const uint face = edge_adj_faces[i]->
faces[j];
457 if (!face_singularity[face]) {
458 bool is_singularity =
true;
459 for (
const int vert : orig_corner_verts.
slice(orig_faces[face])) {
460 if (vm[vert] != v1) {
461 is_singularity =
false;
465 if (is_singularity) {
466 face_singularity[face] =
true;
476 new_loops_num -= edge_adj_faces_len[i] * 2;
479 edge_adj_faces_len[i] = 0;
481 MEM_freeN(edge_adj_faces[i]->faces_reversed);
483 edge_adj_faces[i] =
nullptr;
493 for (
uint i = 0; i < edges_num; i++) {
494 const int2 &edge = orig_edges[i];
495 if (edge_adj_faces_len[i] > 0) {
496 const int vs[2] = {
int(vm[edge[0]]),
int(vm[edge[1]])};
497 uint invalid_edge_index = 0;
498 bool invalid_edge_reversed =
false;
499 for (
uint j = 0; j < 2; j++) {
500 const int vert = vs[j];
501 const uint len = vert_adj_edges_len[vert];
504 if (old_edge_vert_ref ==
nullptr) {
505 uint *adj_edges =
static_cast<uint *
>(
508 for (
uint k = 1; k <
len; k++) {
514 vert_adj_edges[vert] = ref;
517 const uint *f = old_edge_vert_ref->
edges;
519 const uint edge = old_edge_vert_ref->
edges[k];
521 old_edge_vert_ref->
edges[k] = i;
525 if (vm[orig_edges[edge][0]] == vs[1 - j]) {
526 invalid_edge_index = edge + 1;
527 invalid_edge_reversed = (j == 0);
530 if (vm[orig_edges[edge][1]] == vs[1 - j]) {
531 invalid_edge_index = edge + 1;
532 invalid_edge_reversed = (j == 1);
536 if (invalid_edge_index) {
547 if (invalid_edge_index) {
548 const uint tmp = invalid_edge_index - 1;
549 invalid_edge_index = i;
552 OldEdgeFaceRef *invalid_adj_faces = edge_adj_faces[invalid_edge_index];
556 if (i_adj_faces->
faces[k] == invalid_adj_faces->
faces[
l] &&
567 new_faces_num -= 2 * j;
568 new_loops_num -= 4 * j;
571 uint *adj_faces =
static_cast<uint *
>(
573 bool *adj_faces_loops_reversed =
static_cast<bool *
>(
579 adj_faces[j] = i_adj_faces->
faces[k];
585 adj_faces[j] = invalid_adj_faces->
faces[k];
586 adj_faces_loops_reversed[j++] = (invalid_edge_reversed !=
591 edge_adj_faces_len[invalid_edge_index] = 0;
592 edge_adj_faces_len[i] =
len;
596 i_adj_faces->
faces = adj_faces;
598 i_adj_faces->
used += invalid_adj_faces->
used;
602 edge_adj_faces[invalid_edge_index] = i_adj_faces;
604 i = invalid_edge_index;
614 const int2 *edge = orig_edges.
data();
617 for (
uint i = 0; i < edges_num; i++, edge++) {
618 if (edge_adj_faces_len[i] > 0) {
625 for (
uint j = 0; j < adj_len; j++) {
627 const int j_loopstart = orig_faces[face].start();
628 const int totloop = orig_faces[face].
size();
629 const uint j_first_v = vm[orig_corner_verts[j_loopstart]];
630 for (
uint k = j + 1; k < adj_len; k++) {
631 if (orig_faces[adj_faces->
faces[k]].
size() != totloop) {
635 const int k_loopstart = orig_faces[adj_faces->
faces[k]].start();
638 const int *corner_vert = &orig_corner_verts[k_loopstart];
639 for (
l = 0;
l < totloop && vm[*corner_vert] != j_first_v;
l++, corner_vert++) {
648 const int count_dir = reversed ? -1 : 1;
649 bool has_diff =
false;
650 for (
int m = 0, n =
l + totloop; m < totloop && !has_diff; m++, n += count_dir) {
651 const int vert = orig_corner_verts[j_loopstart + m];
652 has_diff = has_diff ||
653 vm[vert] != vm[orig_corner_verts[k_loopstart + n % totloop]];
658 for (
uint m = 0; m < totloop; m++) {
659 const int e = orig_corner_edges[j_loopstart + m];
663 uint *e_adj_faces_faces = e_adj_faces->
faces;
666 if (e_adj_faces_faces != adj_faces->
faces) {
669 face_index < faces_len && e_adj_faces_faces[face_index] != face;
675 if (face_index == faces_len) {
683 memmove(e_adj_faces_faces + face_index,
684 e_adj_faces_faces + face_index + 1,
685 (faces_len - face_index - 1) *
sizeof(*e_adj_faces_faces));
686 memmove(e_adj_faces_reversed + face_index,
687 e_adj_faces_reversed + face_index + 1,
688 (faces_len - face_index - 1) *
sizeof(*e_adj_faces_reversed));
690 if (edge_adj_faces_len[
e] > 0) {
691 edge_adj_faces_len[
e]--;
692 if (edge_adj_faces_len[
e] == 0) {
694 edge_adj_faces[
e] =
nullptr;
697 else if (e_adj_faces->
used > 1) {
698 for (
uint n = 0; n < edges_num; n++) {
699 if (edge_adj_faces[n] == e_adj_faces && edge_adj_faces_len[n] > 0) {
700 edge_adj_faces_len[n]--;
701 if (edge_adj_faces_len[n] == 0) {
702 edge_adj_faces[n]->
used--;
703 edge_adj_faces[n] =
nullptr;
714 new_loops_num -= 2 *
uint(del_loops);
727 for (
uint i = 0; i < edges_num; i++) {
728 const int2 &edge = orig_edges[i];
729 const uint v1 = vm[edge[0]];
730 const uint v2 = vm[edge[1]];
731 if (edge_adj_faces_len[i] > 0) {
732 if (
LIKELY(orig_edge_lengths[i] > FLT_EPSILON)) {
734 mul_v3_fl(edgedir, 1.0f / orig_edge_lengths[i]);
746 for (
int j = 0; j < link1->
edges_len; j++) {
748 if (edge_adj_faces_len[
e] > 0 &&
e != i) {
750 vm[vm[orig_edges[
e][0]] == v1 ? orig_edges[
e][1] : orig_edges[
e][0]];
758 for (
int j = 0; j < link2->
edges_len; j++) {
760 if (edge_adj_faces_len[
e] > 0 &&
e != i) {
762 vm[vm[orig_edges[
e][0]] ==
v2 ? orig_edges[
e][1] : orig_edges[
e][0]];
778 const uint *adj_faces_faces = adj_faces->
faces;
780 uint new_edges_len = 0;
784 new_edges_len = adj_len;
786 float ref_nor[3] = {0, 0, 0};
788 for (
uint j = 0; j < adj_len; j++) {
789 const bool reverse = adj_faces_reversed[j];
790 const uint face_i = adj_faces_faces[j];
798 if (orig_faces[face_i].
size() > 3) {
808 sorted_faces[j].
angle = 0.0f;
812 sorted_faces[j].
angle = 0.0f;
818 sorted_faces[j].
face = face_sides_arr + adj_faces_faces[j] * 2 +
819 (adj_faces_reversed[j] ? 1 : 0);
827 sorted_faces[0].
face = face_sides_arr + adj_faces_faces[0] * 2 +
828 (adj_faces_reversed[0] ? 1 : 0);
839 new_edges[new_edges_len] =
nullptr;
841 for (
uint j = 0; j < new_edges_len; j++) {
844 const uint next_j = j + 1 == adj_len ? 0 : j + 1;
845 faces[0] = sorted_faces[j].
face;
846 faces[1] = sorted_faces[next_j].
face->
reversed ? sorted_faces[next_j].
face - 1 :
847 sorted_faces[next_j].
face + 1;
848 angle = sorted_faces[next_j].
angle - sorted_faces[j].
angle;
855 sorted_faces[0].
face + j;
862 if (do_shell || (adj_len == 1 && do_rim)) {
863 edge_data_edge_index = 0;
868 new_edge_ref.faces[0] = faces[0];
869 new_edge_ref.faces[1] = faces[1];
870 new_edge_ref.link_edge_groups[0] =
nullptr;
871 new_edge_ref.link_edge_groups[1] =
nullptr;
872 new_edge_ref.angle =
angle;
873 new_edge_ref.new_edge = edge_data_edge_index;
874 *edge_data = new_edge_ref;
876 new_edges[j] = edge_data;
877 for (
uint k = 0; k < 2; k++) {
878 if (faces[k] !=
nullptr) {
879 for (
int l = 0;
l < faces[k]->face.size();
l++) {
880 const int edge = orig_corner_edges[faces[k]->face.start() +
l];
881 if (edge_adj_faces[edge] == edge_adj_faces[i]) {
882 if (edge != i && orig_edge_data_arr[edge] ==
nullptr) {
883 orig_edge_data_arr[edge] = new_edges;
885 faces[k]->link_edges[
l] = edge_data;
893 orig_edge_data_arr[i] = new_edges;
894 if (do_shell || (adj_len == 1 && do_rim)) {
895 new_edges_num += new_edges_len;
901 for (
uint i = 0; i < edges_num; i++) {
902 if (edge_adj_faces[i]) {
903 if (edge_adj_faces[i]->used > 1) {
904 edge_adj_faces[i]->
used--;
908 MEM_freeN(edge_adj_faces[i]->faces_reversed);
919 for (
uint i = 0; i < verts_num; i++, adj_edges_ptr++) {
920 if (*adj_edges_ptr !=
nullptr && (*adj_edges_ptr)->
edges_len >= 2) {
924 bool contains_long_groups =
false;
925 uint topo_groups = 0;
929 const uint *adj_edges = (*adj_edges_ptr)->
edges;
930 const uint tot_adj_edges = (*adj_edges_ptr)->edges_len;
932 uint unassigned_edges_len = 0;
933 for (
uint j = 0; j < tot_adj_edges; j++) {
934 NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]];
940 unassigned_edges_len++;
947 for (
uint j = 0, k = 0; j < tot_adj_edges; j++) {
948 NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]];
951 unassigned_edges[k++] = *new_edges;
959 uint edge_groups_len = unassigned_edges_len / 2;
963 uint assigned_edges_len = 0;
965 uint found_edge_index = 0;
966 bool insert_at_start =
false;
967 uint eg_capacity = 5;
968 NewFaceRef *eg_track_faces[2] = {
nullptr,
nullptr};
971 while (assigned_edges_len < unassigned_edges_len) {
972 found_edge =
nullptr;
973 insert_at_start =
false;
974 if (eg_index >= 0 && edge_groups[eg_index].edges_len == 0) {
980 while (!edge && j < unassigned_edges_len) {
981 edge = unassigned_edges[j++];
982 if (edge && last_open_edge_track &&
983 (edge->faces[0] != last_open_edge_track || edge->faces[1] !=
nullptr))
988 if (!edge && last_open_edge_track) {
990 last_open_edge_track =
nullptr;
993 while (!edge && j < unassigned_edges_len) {
994 edge = unassigned_edges[j++];
997 else if (!last_open_edge_track && eg_index > 0) {
1002 found_edge_index = j - 1;
1004 if (!last_open_edge_track && vm[orig_edges[edge->old_edge][0]] == i) {
1005 eg_track_faces[0] = edge->faces[0];
1006 eg_track_faces[1] = edge->faces[1];
1007 if (edge->faces[1] ==
nullptr) {
1008 last_open_edge_track = edge->faces[0]->
reversed ? edge->faces[0] - 1 :
1013 eg_track_faces[0] = edge->faces[1];
1014 eg_track_faces[1] = edge->faces[0];
1017 else if (eg_index >= 0) {
1019 for (found_edge_index = 0; found_edge_index < unassigned_edges_len;
1020 found_edge_index++, edge_ptr++)
1024 if (edge->faces[0] == eg_track_faces[1]) {
1025 insert_at_start =
false;
1026 eg_track_faces[1] = edge->faces[1];
1028 if (edge->faces[1] ==
nullptr) {
1030 last_open_edge_track = edge->faces[0]->
reversed ? edge->faces[0] - 1 :
1035 if (edge->faces[0] == eg_track_faces[0]) {
1036 insert_at_start =
true;
1037 eg_track_faces[0] = edge->faces[1];
1039 if (edge->faces[1] ==
nullptr) {
1044 if (edge->faces[1] !=
nullptr) {
1045 if (edge->faces[1] == eg_track_faces[1]) {
1046 insert_at_start =
false;
1047 eg_track_faces[1] = edge->faces[0];
1051 if (edge->faces[1] == eg_track_faces[0]) {
1052 insert_at_start =
true;
1053 eg_track_faces[0] = edge->faces[0];
1062 unassigned_edges[found_edge_index] =
nullptr;
1063 assigned_edges_len++;
1064 const uint needed_capacity = edge_groups[eg_index].
edges_len + 1;
1065 if (needed_capacity > eg_capacity) {
1066 eg_capacity = needed_capacity + 1;
1069 if (insert_at_start) {
1071 edge_groups[eg_index].edges,
1072 edge_groups[eg_index].edges_len *
sizeof(*new_eg));
1076 edge_groups[eg_index].edges,
1077 edge_groups[eg_index].edges_len *
sizeof(*new_eg));
1080 edge_groups[eg_index].
edges = new_eg;
1082 else if (insert_at_start) {
1083 memmove(edge_groups[eg_index].edges + 1,
1084 edge_groups[eg_index].edges,
1085 edge_groups[eg_index].edges_len *
sizeof(*edge_groups[eg_index].edges));
1087 edge_groups[eg_index].
edges[insert_at_start ? 0 : edge_groups[eg_index].
edges_len] =
1090 if (edge_groups[eg_index].edges[edge_groups[eg_index].edges_len - 1]->faces[1] !=
1093 last_open_edge_track =
nullptr;
1095 if (edge_groups[eg_index].edges_len > 3) {
1096 contains_long_groups =
true;
1109 edge_group.
valid =
true;
1110 edge_group.edges = edges;
1111 edge_group.edges_len = 0;
1113 edge_group.is_orig_closed =
true;
1114 edge_group.is_even_split =
false;
1115 edge_group.split = 0;
1116 edge_group.is_singularity =
false;
1117 edge_group.topo_group = topo_groups;
1121 edge_groups[eg_index] = edge_group;
1123 eg_track_faces[0] =
nullptr;
1124 eg_track_faces[1] =
nullptr;
1141 if (contains_long_groups) {
1143 for (
uint j = 0; j < eg_index; j++) {
1144 const uint edges_len = edge_groups[j + add_index].
edges_len;
1145 if (edges_len > 3) {
1146 bool has_doubles =
false;
1147 bool *doubles =
static_cast<bool *
>(
1149 EdgeGroup g = edge_groups[j + add_index];
1150 for (
uint k = 0; k < edges_len; k++) {
1151 for (
uint l = k + 1;
l < edges_len;
l++) {
1160 const uint prior_splits = splits;
1161 const uint prior_index = add_index;
1162 int unique_start = -1;
1163 int first_unique_end = -1;
1164 int last_split = -1;
1165 int first_split = -1;
1166 bool first_even_split =
false;
1168 while (real_k < edges_len ||
1171 (first_unique_end == -1 ? 0 : first_unique_end) +
int(edges_len) ||
1172 first_split != last_split)))
1174 const uint k = real_k % edges_len;
1176 if (first_unique_end != -1 && unique_start == -1) {
1177 unique_start =
int(real_k);
1180 else if (first_unique_end == -1) {
1181 first_unique_end =
int(k);
1183 else if (unique_start != -1) {
1184 const uint split = ((
uint(unique_start) + real_k + 1) / 2) % edges_len;
1185 const bool is_even_split = ((
uint(unique_start) + real_k) & 1);
1186 if (last_split != -1) {
1188 if (prior_splits != splits) {
1189 memmove(edge_groups + j + add_index + 1,
1190 edge_groups + j + add_index,
1191 (
uint(eg_index) - j) *
sizeof(*edge_groups));
1194 if (last_split > split) {
1195 const uint edges_len_group = (split + edges_len) -
uint(last_split);
1199 g.
edges + last_split,
1200 (edges_len -
uint(last_split)) *
sizeof(*edges));
1201 memcpy(edges + (edges_len -
uint(last_split)),
1203 split *
sizeof(*edges));
1206 edge_group.
valid =
true;
1207 edge_group.edges = edges;
1208 edge_group.edges_len = edges_len_group;
1211 edge_group.is_even_split = is_even_split;
1213 edge_group.is_singularity =
false;
1218 edge_groups[j + add_index] = edge_group;
1221 const uint edges_len_group = split -
uint(last_split);
1224 memcpy(edges, g.
edges + last_split, edges_len_group *
sizeof(*edges));
1227 edge_group.
valid =
true;
1228 edge_group.edges = edges;
1229 edge_group.edges_len = edges_len_group;
1232 edge_group.is_even_split = is_even_split;
1234 edge_group.is_singularity =
false;
1239 edge_groups[j + add_index] = edge_group;
1243 last_split =
int(split);
1244 if (first_split == -1) {
1245 first_split =
int(split);
1246 first_even_split = is_even_split;
1252 if (first_split != -1) {
1254 if (prior_splits != splits) {
1255 memmove(edge_groups + (j + prior_index + 1),
1256 edge_groups + (j + prior_index),
1257 (
uint(eg_index) + add_index - (j + prior_index)) *
1258 sizeof(*edge_groups));
1259 memmove(edge_groups + (j + add_index + 2),
1260 edge_groups + (j + add_index + 1),
1261 (
uint(eg_index) - j) *
sizeof(*edge_groups));
1265 memmove(edge_groups + (j + add_index + 2),
1266 edge_groups + (j + add_index + 1),
1267 (
uint(eg_index) - j - 1) *
sizeof(*edge_groups));
1271 memcpy(edges, g.
edges,
uint(first_split) *
sizeof(*edges));
1274 edge_group_a.
valid =
true;
1275 edge_group_a.edges = edges;
1276 edge_group_a.edges_len =
uint(first_split);
1279 edge_group_a.is_even_split = first_even_split;
1280 edge_group_a.split = 1;
1281 edge_group_a.is_singularity =
false;
1286 edge_groups[j + prior_index] = edge_group_a;
1291 edges_len -
uint(last_split),
sizeof(*edges), __func__));
1293 g.
edges + last_split,
1294 (edges_len -
uint(last_split)) *
sizeof(*edges));
1297 edge_group_b.
valid =
true;
1298 edge_group_b.edges = edges;
1299 edge_group_b.edges_len = (edges_len -
uint(last_split));
1302 edge_group_b.is_even_split =
false;
1303 edge_group_b.split = add_index - prior_index + 1;
1304 edge_group_b.is_singularity =
false;
1309 edge_groups[j + add_index] = edge_group_b;
1311 if (prior_splits != splits) {
1315 if (first_unique_end != -1 && prior_splits == splits) {
1316 has_singularities =
true;
1326 orig_vert_groups_arr[i] = edge_groups;
1330 bool contains_open_splits =
false;
1331 uint open_edges = 0;
1332 uint contains_splits = 0;
1333 uint last_added = 0;
1334 uint first_added = 0;
1335 bool first_set =
false;
1338 for (
uint j = 0; j < g->edges_len; j++,
e++) {
1339 const uint flip =
uint(vm[orig_edges[(*e)->old_edge][1]] == i);
1340 BLI_assert(flip || vm[orig_edges[(*e)->old_edge][0]] == i);
1341 (*e)->link_edge_groups[flip] = g;
1344 if (do_shell || (do_rim && !g->is_orig_closed)) {
1346 g->new_vert = new_verts_num++;
1347 if (do_rim || (do_shell && g->split)) {
1349 contains_splits += (g->split != 0);
1350 contains_open_splits |= g->split && !g->is_orig_closed;
1354 open_edges +=
uint(added < last_added);
1357 first_added = added;
1360 if (!(g + 1)->valid || g->topo_group != (g + 1)->topo_group) {
1361 if (new_verts > 2) {
1363 new_edges_num += new_verts;
1364 open_edges +=
uint(first_added < last_added);
1365 open_edges -=
uint(open_edges && !contains_open_splits);
1366 if (do_shell && do_rim) {
1367 new_loops_num += new_verts * 2;
1369 else if (do_shell) {
1370 new_loops_num += new_verts * 2 - open_edges;
1373 new_loops_num += new_verts * 2 + open_edges - contains_splits;
1376 else if (new_verts == 2) {
1378 new_loops_num += 2u -
uint(!(do_rim && do_shell) && contains_open_splits);
1381 contains_open_splits =
false;
1382 contains_splits = 0;
1397 for (
OldVertEdgeRef **p = vert_adj_edges; i < verts_num; i++, p++) {
1413 float *face_weight =
nullptr;
1415 if (do_flat_faces) {
1416 face_weight =
static_cast<float *
>(
1420 float scalar_vgroup = 1.0f;
1421 for (
const int vert : orig_corner_verts.
slice(orig_faces[i])) {
1423 if (defgrp_invert) {
1431 scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv);
1432 face_weight[i] = scalar_vgroup;
1436 gs_ptr = orig_vert_groups_arr;
1437 for (
uint i = 0; i < verts_num; i++, gs_ptr++) {
1440 if (!g->is_singularity) {
1446 float move_nor[3] = {0, 0, 0};
1449 (g->is_orig_closed || g->split));
1450 bool approximate_free_direction =
false;
1456 float(*planes_queue)[4] =
static_cast<float(*)[4]
>(
1458 uint queue_index = 0;
1460 float fallback_nor[3];
1461 float fallback_ofs = 0.0f;
1463 const bool cycle = (g->is_orig_closed && !g->split) || g->is_even_split;
1464 for (
uint k = 0; k < g->edges_len; k++, edge_ptr++) {
1465 if (!(k & 1) || (!cycle && k == g->edges_len - 1)) {
1467 for (
uint l = 0;
l < 2;
l++) {
1469 if (face && (first_edge ==
nullptr ||
1470 (first_edge->
faces[0] != face && first_edge->
faces[1] != face)))
1472 float ofs = face->
reversed ? ofs_back_clamped : ofs_front_clamped;
1474 if (do_flat_faces) {
1475 ofs *= face_weight[face->index];
1478 if (!null_faces[face->index]) {
1481 face_nors[face->index],
1482 face->reversed ? -1 : 1);
1483 planes_queue[queue_index++][3] = ofs;
1488 mul_v3_v3fl(fallback_nor, face_nors[face->index], face->reversed ? -1 : 1);
1493 if ((cycle && k == 0) || (!cycle && k + 3 >= g->edges_len)) {
1498 if (queue_index > 2) {
1503 for (
uint k = 0; k < queue_index; k++) {
1504 for (
uint m = k + 1; m < queue_index; m++) {
1505 float p =
dot_v3v3(planes_queue[k], planes_queue[m]);
1515 swap_v4_v4(planes_queue[min_n0], planes_queue[0]);
1516 swap_v4_v4(planes_queue[min_n1], planes_queue[1]);
1519 swap_v4_v4(planes_queue[min_n0], planes_queue[1]);
1524 float max_p = -1.0f;
1525 for (
uint k = 2; k < queue_index; k++) {
1527 dot_v3v3(planes_queue[1], planes_queue[k]));
1528 if (max_p <= min_p) {
1533 swap_v4_v4(planes_queue[min_n1], planes_queue[2]);
1536 while (queue_index > 2) {
1539 float best_p = -1.0f;
1540 float best_ofs_diff = 0.0f;
1541 for (
uint k = 0; k < queue_index; k++) {
1542 for (
uint m = k + 1; m < queue_index; m++) {
1543 float p =
dot_v3v3(planes_queue[m], planes_queue[k]);
1544 float ofs_diff =
fabsf(planes_queue[m][3] - planes_queue[k][3]);
1545 if (p > best_p + FLT_EPSILON || (p >= best_p && ofs_diff < best_ofs_diff)) {
1547 best_ofs_diff = ofs_diff;
1555 if (best_p < 0.98f) {
1558 add_v3_v3(planes_queue[best_n0], planes_queue[best_n1]);
1560 planes_queue[best_n0][3] = (planes_queue[best_n0][3] + planes_queue[best_n1][3]) *
1563 memmove(planes_queue + best_n1,
1564 planes_queue + best_n1 + 1,
1565 (queue_index - best_n1) *
sizeof(*planes_queue));
1567 const uint size = queue_index;
1575 const float boundary_fix_threshold = 0.7f;
1580 for (
int k = 0; k < 3; k++) {
1581 for (
int m = 0; m <
size; m++) {
1582 madd_v3_v3fl(mat[k], planes_queue[m], planes_queue[m][k]);
1592 for (
int k = 0; k <
size; k++) {
1597 if (!disable_boundary_fix) {
1599 float greatest_angle_cos = 1.0f;
1600 for (
uint k = 0; k < 2; k++) {
1602 float p =
dot_v3v3(planes_queue[m], planes_queue[k]);
1603 if (p < greatest_angle_cos) {
1604 greatest_angle_cos = p;
1608 if (greatest_angle_cos > boundary_fix_threshold) {
1609 approximate_free_direction =
true;
1612 disable_boundary_fix =
true;
1616 else if (size > 1) {
1619 const float q =
dot_v3v3(planes_queue[0], planes_queue[1]);
1620 float d = 1.0f - q * q;
1623 if (d > FLT_EPSILON * 10 && q < stop_explosion) {
1625 mul_v3_fl(planes_queue[0], (planes_queue[0][3] - planes_queue[1][3] * q) * d);
1626 mul_v3_fl(planes_queue[1], (planes_queue[1][3] - planes_queue[0][3] * q) * d);
1629 d = 1.0f / (
fabsf(q) + 1.0f);
1630 mul_v3_fl(planes_queue[0], planes_queue[0][3] * d);
1631 mul_v3_fl(planes_queue[1], planes_queue[1][3] * d);
1635 d =
dot_v3v3(planes_queue[2], move_nor);
1638 if (
fabsf(d) > 0.02f) {
1644 if (
fabsf(d) > 1.0f - boundary_fix_threshold) {
1645 disable_boundary_fix =
true;
1649 approximate_free_direction =
false;
1651 else if (size == 1) {
1654 if (g->edges_len > 2) {
1655 disable_boundary_fix =
true;
1656 approximate_free_direction =
true;
1662 disable_boundary_fix =
true;
1668 float total_angle = 0;
1669 float total_angle_back = 0;
1673 float nor_back[3] = {0, 0, 0};
1674 bool has_back =
false;
1675 bool has_front =
false;
1676 bool cycle = (g->is_orig_closed && !g->split) || g->is_even_split;
1677 for (
uint k = 0; k < g->edges_len; k++, edge_ptr++) {
1678 if (!(k & 1) || (!cycle && k == g->edges_len - 1)) {
1680 for (
uint l = 0;
l < 2;
l++) {
1682 if (face && (first_edge ==
nullptr ||
1683 (first_edge->
faces[0] != face && first_edge->
faces[1] != face)))
1686 float ofs = face->
reversed ? -ofs_back_clamped : ofs_front_clamped;
1688 if (do_flat_faces) {
1689 ofs *= face_weight[face->index];
1695 int corner_next = face->face.start();
1696 int corner = corner_next + (face->face.size() - 1);
1697 int corner_prev = corner - 1;
1700 m < face->face.size() && vm[orig_corner_verts[corner]] != i;
1703 corner_prev = corner;
1704 corner = corner_next;
1706 angle =
angle_v3v3v3(orig_mvert_co[vm[orig_corner_verts[corner_prev]]],
1708 orig_mvert_co[vm[orig_corner_verts[corner_next]]]);
1709 if (face->reversed) {
1710 total_angle_back += angle * ofs * ofs;
1713 total_angle += angle * ofs * ofs;
1717 if (face->reversed) {
1724 mul_v3_v3fl(face_nor, face_nors[face->index], angle * ofs);
1725 if (face->reversed) {
1735 if ((cycle && k == 0) || (!cycle && k + 3 >= g->edges_len)) {
1745 if (
LIKELY(length_sq > FLT_EPSILON)) {
1751 if (
LIKELY(length_sq > FLT_EPSILON)) {
1752 mul_v3_fl(nor_back, total_angle_back / length_sq);
1758 if (has_front && has_back) {
1760 float nor_back_length =
len_v3(nor_back);
1763 q /= nor_length * nor_back_length;
1765 float d = 1.0f - q * q;
1766 if (
LIKELY(d > FLT_EPSILON)) {
1768 if (
LIKELY(nor_length > FLT_EPSILON)) {
1769 mul_v3_fl(
nor, (1 - nor_back_length * q / nor_length) * d);
1771 if (
LIKELY(nor_back_length > FLT_EPSILON)) {
1772 mul_v3_fl(nor_back, (1 - nor_length * q / nor_back_length) * d);
1784 if (has_front && total_angle > FLT_EPSILON) {
1787 if (has_back && total_angle_back > FLT_EPSILON) {
1788 mul_v3_fl(nor_back, 1.0f / total_angle_back);
1790 if (has_front && total_angle > FLT_EPSILON) {
1796 if (!disable_boundary_fix && g->edges_len > 2) {
1797 approximate_free_direction =
true;
1800 disable_boundary_fix =
true;
1803 if (approximate_free_direction) {
1808 for (k = 1; k + 1 < g->edges_len; k++, edge_ptr++) {
1809 const int2 &edge = orig_edges[(*edge_ptr)->old_edge];
1811 tmp, orig_mvert_co[vm[edge[0]] == i ? edge[1] : edge[0]], orig_mvert_co[i]);
1815 disable_boundary_fix =
true;
1822 if (!disable_boundary_fix) {
1824 float constr_nor[3];
1825 const int2 &e0_edge = orig_edges[g->edges[0]->old_edge];
1826 const int2 &e1_edge = orig_edges[g->edges[g->edges_len - 1]->old_edge];
1830 orig_mvert_co[vm[e0_edge[0]] == i ? e0_edge[1] : e0_edge[0]],
1833 orig_mvert_co[vm[e1_edge[0]] == i ? e1_edge[1] : e1_edge[0]],
1844 if (g->edges[0]->faces[0]->reversed) {
1845 negate_v3_v3(f0, face_nors[g->edges[0]->faces[0]->index]);
1848 copy_v3_v3(f0, face_nors[g->edges[0]->faces[0]->index]);
1850 if (g->edges[g->edges_len - 1]->faces[0]->reversed) {
1851 negate_v3_v3(f1, face_nors[g->edges[g->edges_len - 1]->faces[0]->index]);
1854 copy_v3_v3(f1, face_nors[g->edges[g->edges_len - 1]->faces[0]->index]);
1865 float d =
dot_v3v3(constr_nor, move_nor);
1867 if (
fabsf(d) > 0.1f) {
1872 float scalar_vgroup = 1;
1874 if (dvert && !do_flat_faces) {
1876 if (defgrp_invert) {
1882 scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv);
1886 if (do_angle_clamp) {
1887 if (g->edges_len > 2) {
1888 float min_length = 0;
1889 float angle = 0.5f *
M_PI;
1891 for (
NewEdgeRef **p = g->edges; k < g->edges_len; k++, p++) {
1892 float length = orig_edge_lengths[(*p)->old_edge];
1893 float e_ang = (*p)->angle;
1894 if (e_ang > angle) {
1897 if (length < min_length || k == 0) {
1901 float cos_ang =
cosf(angle * 0.5f);
1903 float max_off = min_length * 0.5f / cos_ang;
1904 if (max_off < offset * 0.5f) {
1905 scalar_vgroup *= max_off / offset * 2;
1911 float min_length = 0;
1913 for (
NewEdgeRef **p = g->edges; k < g->edges_len; k++, p++) {
1914 float length = orig_edge_lengths[(*p)->old_edge];
1915 if (length < min_length || k == 0) {
1919 if (min_length < offset) {
1920 scalar_vgroup *= min_length / offset;
1934 if (do_flat_faces) {
1948 uint(*singularity_edges)[2] =
nullptr;
1949 uint totsingularity = 0;
1950 if (has_singularities) {
1951 has_singularities =
false;
1953 uint singularity_edges_len = 1;
1954 singularity_edges =
static_cast<uint(*)[2]
>(
1955 MEM_malloc_arrayN(singularity_edges_len,
sizeof(*singularity_edges), __func__));
1956 for (
NewEdgeRef ***new_edges = orig_edge_data_arr; i < edges_num; i++, new_edges++) {
1957 if (*new_edges && (do_shell || edge_adj_faces_len[i] == 1) && (**new_edges)->old_edge == i) {
1959 if ((*l)->link_edge_groups[0]->is_singularity &&
1960 (*l)->link_edge_groups[1]->is_singularity)
1962 const uint v1 = (*l)->link_edge_groups[0]->new_vert;
1963 const uint v2 = (*l)->link_edge_groups[1]->new_vert;
1964 bool exists_already =
false;
1966 for (
uint(*p)[2] = singularity_edges; j < totsingularity; p++, j++) {
1967 if (((*p)[0] == v1 && (*p)[1] ==
v2) || ((*p)[0] ==
v2 && (*p)[1] == v1)) {
1968 exists_already =
true;
1972 if (!exists_already) {
1973 has_singularities =
true;
1974 if (singularity_edges_len <= totsingularity) {
1975 singularity_edges_len = totsingularity + 1;
1976 singularity_edges =
static_cast<uint(*)[2]
>(
1978 singularity_edges_len *
sizeof(*singularity_edges),
1981 singularity_edges[totsingularity][0] = v1;
1982 singularity_edges[totsingularity][1] =
v2;
1984 if (edge_adj_faces_len[i] == 1 && do_rim) {
2000 mesh,
int(new_verts_num),
int(new_edges_num),
int(new_faces_num),
int(new_loops_num));
2008 int *origindex_edge =
static_cast<int *
>(
2010 int *origindex_face =
static_cast<int *
>(
2014 &result->edge_data,
CD_PROP_FLOAT,
"bevel_weight_edge", result->edges_num));
2015 if (!result_edge_bweight && (bevel_convex != 0.0f || orig_vert_bweight !=
nullptr)) {
2020 "bevel_weight_edge"));
2025 if (shell_defgrp_index != -1 || rim_defgrp_index != -1) {
2026 dst_dvert = result->deform_verts_for_write().data();
2031 const float *vertex_crease =
static_cast<const float *
>(
2033 float *result_edge_crease =
nullptr;
2034 if (vertex_crease || orig_edge_crease) {
2036 &result->edge_data,
CD_PROP_FLOAT,
"crease_edge", result->edges_num));
2037 if (!result_edge_crease) {
2049 gs_ptr = orig_vert_groups_arr;
2050 for (
uint i = 0; i < verts_num; i++, gs_ptr++) {
2056 &mesh->vert_data, &result->vert_data,
int(i),
int(g->new_vert), 1);
2057 copy_v3_v3(vert_positions[g->new_vert], g->co);
2067 edge_index += totsingularity;
2068 for (
NewEdgeRef ***new_edges = orig_edge_data_arr; i < edges_num; i++, new_edges++) {
2069 if (*new_edges && (do_shell || edge_adj_faces_len[i] == 1) && (**new_edges)->old_edge == i) {
2072 const uint v1 = (*l)->link_edge_groups[0]->new_vert;
2073 const uint v2 = (*l)->link_edge_groups[1]->new_vert;
2075 if (has_singularities && ((*l)->link_edge_groups[0]->is_singularity &&
2076 (*l)->link_edge_groups[1]->is_singularity))
2079 for (
uint(*p)[2] = singularity_edges; j < totsingularity; p++, j++) {
2080 if (((*p)[0] == v1 && (*p)[1] ==
v2) || ((*p)[0] ==
v2 && (*p)[1] == v1)) {
2095 if (result_edge_crease) {
2096 result_edge_crease[
insert] = orig_edge_crease ? orig_edge_crease[(*l)->old_edge] :
2099 if (result_edge_bweight) {
2100 result_edge_bweight[
insert] = orig_edge_bweight ? orig_edge_bweight[(*l)->old_edge] :
2103 if (bevel_convex != 0.0f && (*l)->faces[1] !=
nullptr) {
2105 result_edge_bweight[
insert] +
2106 ((*l)->angle >
M_PI + FLT_EPSILON ?
2107 clamp_f(bevel_convex, 0.0f, 1.0f) :
2108 ((*l)->angle <
M_PI - FLT_EPSILON ?
clamp_f(bevel_convex, -1.0f, 0.0f) :
2119 if (singularity_edges) {
2143 gs_ptr = orig_vert_groups_arr;
2144 for (
uint i = 0; i < verts_num; i++, gs_ptr++) {
2151 for (
uint j = 0; j < g->edges_len; j++,
e++) {
2152 printf(
"%u/%d, ", (*e)->old_edge,
int(*e)->new_edge);
2154 printf(
"(tg:%u)(s:%u,c:%d)\n", g->topo_group, g->split, g->is_orig_closed);
2161 const VArraySpan src_material_index = *src_attributes.
lookup<
int>(
"material_index",
2162 bke::AttrDomain::Face);
2165 "material_index", bke::AttrDomain::Face);
2169 gs_ptr = orig_vert_groups_arr;
2170 for (
uint i = 0; i < verts_num; i++, gs_ptr++) {
2177 float mv_crease = vertex_crease ? vertex_crease[i] : 0.0f;
2178 float mv_bweight = orig_vert_bweight ? orig_vert_bweight[i] : 0.0f;
2181 float last_max_crease = 0.0f;
2182 float first_max_crease = 0.0f;
2184 float last_max_bweight = 0.0f;
2185 float first_max_bweight = 0.0f;
2194 if (result_edge_crease) {
2195 if (orig_edge_crease) {
2207 if (result_edge_crease) {
2208 if (orig_edge_crease && orig_edge_crease[orig_edge_index] > max_crease) {
2209 max_crease = orig_edge_crease[orig_edge_index];
2213 if (result_edge_bweight) {
2215 if (bweight > max_bweight) {
2216 max_bweight = bweight;
2223 const float bweight_open_edge =
2228 if (bweight_open_edge > 0) {
2229 max_bweight =
min_ff(bweight_open_edge, max_bweight);
2232 if (bevel_convex < 0.0f) {
2238 first_max_crease = max_crease;
2239 first_max_bweight = max_bweight;
2248 if (origindex_edge) {
2251 edges[edge_index][0] = last_g->
new_vert;
2252 edges[edge_index][1] = g->
new_vert;
2253 if (result_edge_crease) {
2254 result_edge_crease[edge_index] =
max_ff(mv_crease,
2255 min_ff(last_max_crease, max_crease));
2257 if (result_edge_bweight) {
2258 result_edge_bweight[edge_index] =
max_ff(mv_bweight,
2259 min_ff(last_max_bweight, max_bweight));
2264 last_max_crease = max_crease;
2265 last_max_bweight = max_bweight;
2268 if (!(g + 1)->valid || g->
topo_group != (g + 1)->topo_group) {
2278 if (origindex_edge) {
2282 edges[edge_index][0] = last_g->
new_vert;
2283 edges[edge_index][1] = first_g->
new_vert;
2284 if (result_edge_crease) {
2285 result_edge_crease[edge_index] =
max_ff(mv_crease,
2286 min_ff(last_max_crease, first_max_crease));
2288 if (result_edge_bweight) {
2289 result_edge_bweight[edge_index] =
max_ff(
2290 mv_bweight,
min_ff(last_max_bweight, first_max_bweight));
2295 int *loops_data =
static_cast<int *
>(
2298 short most_mat_nr = 0;
2299 uint most_mat_nr_face = 0;
2300 uint most_mat_nr_count = 0;
2301 for (
short l = 0;
l < mat_nrs;
l++) {
2306 if ((do_rim && !g3->is_orig_closed) || (do_shell && g3->split)) {
2308 if ((!src_material_index.
is_empty() ?
2309 src_material_index[g3->edges[0]->faces[0]->index] :
2312 face = g3->edges[0]->faces[0]->index;
2315 NewEdgeRef *le = g3->edges[g3->edges_len - 1];
2333 if (
count > most_mat_nr_count) {
2335 most_mat_nr_face = face;
2336 most_mat_nr_count =
count;
2340 &mesh->face_data, &result->face_data,
int(most_mat_nr_face),
int(face_index), 1);
2341 if (origindex_face) {
2344 face_offsets[face_index] =
int(loop_index);
2348 CLAMP(dst_material_index.
span[face_index], 0, mat_nr_max);
2351 for (
uint k = 0; g2->
valid && k < j; g2++) {
2354 for (
int l = 0;
l < face.size();
l++) {
2355 const int vert = orig_corner_verts[face[
l]];
2356 if (vm[vert] == i) {
2357 loops_data[k] = face[
l];
2366 for (
uint k = 0; k < j; k++) {
2368 &mesh->corner_data, &result->corner_data, loops_data[k],
int(loop_index), 1);
2369 corner_verts[loop_index] = edges[edge_index - j + k][0];
2370 corner_edges[loop_index++] = edge_index - j + k;
2374 for (
uint k = 1; k <= j; k++) {
2376 &result->corner_data,
2380 corner_verts[loop_index] = edges[edge_index - k][1];
2381 corner_edges[loop_index++] = edge_index - k;
2390 last_max_crease = 0;
2391 first_max_crease = 0;
2392 last_max_bweight = 0;
2393 first_max_bweight = 0;
2402 for (
uint i = 0; i < edges_num; i++) {
2403 if (edge_adj_faces_len[i] == 1 && orig_edge_data_arr[i] &&
2404 (*orig_edge_data_arr[i])->old_edge == i)
2406 NewEdgeRef **new_edges = orig_edge_data_arr[i];
2414 if (v1_singularity && v2_singularity) {
2418 const uint orig_face_index = (*new_edges)->faces[0]->index;
2422 int((*new_edges)->faces[0]->index),
2425 face_offsets[face_index] =
int(loop_index);
2426 dst_material_index.
span[face_index] = (!src_material_index.
is_empty() ?
2427 src_material_index[orig_face_index] :
2430 CLAMP(dst_material_index.
span[face_index], 0, mat_nr_max);
2435 const uint old_v1 = vm[orig_edges[edge1->
old_edge][0]];
2436 const uint old_v2 = vm[orig_edges[edge1->
old_edge][1]];
2437 for (
uint j = 0; j < face.size(); j++) {
2438 const int vert = orig_corner_verts[face.start() + j];
2439 if (vm[vert] == old_v1) {
2440 loop1 = face.start() +
int(j);
2442 else if (vm[vert] == old_v2) {
2443 loop2 = face.start() +
int(j);
2447 int2 open_face_edge;
2448 uint open_face_edge_index;
2450 if (rim_defgrp_index != -1) {
2455 &mesh->corner_data, &result->corner_data, loop1,
int(loop_index), 1);
2456 corner_verts[loop_index] = edges[edge1->
new_edge][0];
2457 corner_edges[loop_index++] = edge1->
new_edge;
2459 if (!v2_singularity) {
2461 if (rim_defgrp_index != -1) {
2466 &mesh->corner_data, &result->corner_data, loop2,
int(loop_index), 1);
2467 corner_verts[loop_index] = edges[edge1->
new_edge][1];
2468 open_face_edge = edges[open_face_edge_index];
2469 if (
ELEM(edges[edge2->
new_edge][1], open_face_edge[0], open_face_edge[1])) {
2470 corner_edges[loop_index++] = open_face_edge_index;
2477 if (rim_defgrp_index != -1) {
2482 &mesh->corner_data, &result->corner_data, loop2,
int(loop_index), 1);
2483 corner_verts[loop_index] = edges[edge2->
new_edge][1];
2484 corner_edges[loop_index++] = edge2->
new_edge;
2486 if (!v1_singularity) {
2488 if (rim_defgrp_index != -1) {
2493 &mesh->corner_data, &result->corner_data, loop1,
int(loop_index), 1);
2494 corner_verts[loop_index] = edges[edge2->
new_edge][0];
2495 open_face_edge = edges[open_face_edge_index];
2496 if (
ELEM(edges[edge1->
new_edge][0], open_face_edge[0], open_face_edge[1])) {
2497 corner_edges[loop_index++] = open_face_edge_index;
2505 if (!v1_singularity) {
2507 if (rim_defgrp_index != -1) {
2512 &mesh->corner_data, &result->corner_data, loop1,
int(loop_index), 1);
2513 corner_verts[loop_index] = edges[edge1->
new_edge][0];
2514 open_face_edge = edges[open_face_edge_index];
2515 if (
ELEM(edges[edge2->
new_edge][0], open_face_edge[0], open_face_edge[1])) {
2516 corner_edges[loop_index++] = open_face_edge_index;
2523 if (rim_defgrp_index != -1) {
2528 &mesh->corner_data, &result->corner_data, loop1,
int(loop_index), 1);
2529 corner_verts[loop_index] = edges[edge2->
new_edge][0];
2530 corner_edges[loop_index++] = edge2->
new_edge;
2532 if (!v2_singularity) {
2534 if (rim_defgrp_index != -1) {
2539 &mesh->corner_data, &result->corner_data, loop2,
int(loop_index), 1);
2540 corner_verts[loop_index] = edges[edge2->
new_edge][1];
2541 open_face_edge = edges[open_face_edge_index];
2542 if (
ELEM(edges[edge1->
new_edge][1], open_face_edge[0], open_face_edge[1])) {
2543 corner_edges[loop_index++] = open_face_edge_index;
2550 if (rim_defgrp_index != -1) {
2555 &mesh->corner_data, &result->corner_data, loop2,
int(loop_index), 1);
2556 corner_verts[loop_index] = edges[edge1->
new_edge][1];
2557 corner_edges[loop_index++] = edge1->
new_edge;
2566 uint *face_loops =
static_cast<uint *
>(
2568 uint *face_verts =
static_cast<uint *
>(
2570 uint *face_edges =
static_cast<uint *
>(
2572 for (
uint i = 0; i < faces_num * 2; i++, fr++) {
2575 uint valid_edges = 0;
2577 while (totloop > 0 && (!fr->
link_edges[totloop - 1] ||
2585 vm[orig_corner_verts[loopstart + (totloop - 1)]]);
2586 for (
uint j = 0; j < totloop; j++) {
2591 vm[orig_corner_verts[loopstart + j]]);
2593 vm[orig_corner_verts[loopstart + j]]);
2598 if (k == 0 || face_verts[k - 1] != new_v1) {
2599 face_loops[k] = loopstart + j;
2606 BLI_assert(k == 0 || edges[face_edges[k]][1] == face_verts[k - 1] ||
2607 edges[face_edges[k]][0] == face_verts[k - 1]);
2609 edges[face_edges[k]][1] == new_v1 || edges[face_edges[k]][0] == new_v1);
2610 face_verts[k++] = new_v1;
2612 prior_edge = new_edge;
2613 prior_flip = 1 - flip;
2614 if (j < totloop - 1 || face_verts[0] != new_v2) {
2615 face_loops[k] = loopstart + (j + 1) % totloop;
2616 face_edges[k] = new_edge->
new_edge;
2617 face_verts[k++] = new_v2;
2620 face_edges[0] = new_edge->
new_edge;
2624 if (k > 2 && valid_edges > 2) {
2626 &mesh->face_data, &result->face_data,
int(i / 2),
int(face_index), 1);
2627 face_offsets[face_index] =
int(loop_index);
2628 dst_material_index.
span[face_index] = (!src_material_index.
is_empty() ?
2629 src_material_index[fr->
index] :
2631 (fr->
reversed != do_flip ? mat_ofs : 0);
2632 CLAMP(dst_material_index.
span[face_index], 0, mat_nr_max);
2634 for (
int l =
int(k) - 1;
l >= 0;
l--) {
2635 if (shell_defgrp_index != -1) {
2640 &result->corner_data,
2644 corner_verts[loop_index] = face_verts[
l];
2645 corner_edges[loop_index++] = face_edges[
l];
2650 for (
uint next_l = 0; next_l < k; next_l++) {
2652 &result->corner_data,
2656 corner_verts[loop_index] = face_verts[
l];
2657 corner_edges[loop_index++] = face_edges[next_l];
2669 if (edge_index != new_edges_num) {
2672 "Internal Error: edges array wrong size: %u instead of %u",
2676 if (face_index != new_faces_num) {
2679 "Internal Error: faces array wrong size: %u instead of %u",
2683 if (loop_index != new_loops_num) {
2686 "Internal Error: loops array wrong size: %u instead of %u",
2699 for (
EdgeGroup **p = orig_vert_groups_arr; i < verts_num; i++, p++) {
2709 for (
NewEdgeRef ***p = orig_edge_data_arr + (edges_num - 1); i > 0; i--, p--) {
2710 if (*p && (**p)->old_edge == i - 1) {
2720 for (
NewFaceRef *p = face_sides_arr; i < faces_num * 2; i++, p++) {
2726#undef MOD_SOLIDIFY_EMPTY_TAG
2728 dst_material_index.
finish();