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);
198 const VArraySpan orig_vert_bweight = *orig_attributes.
lookup<
float>(
"bevel_weight_vert",
200 const VArraySpan orig_edge_bweight = *orig_attributes.
lookup<
float>(
"bevel_weight_edge",
202 const VArraySpan orig_edge_crease = *orig_attributes.
lookup<
float>(
"crease_edge",
205 uint new_verts_num = 0;
206 uint new_edges_num = 0;
207 uint new_loops_num = 0;
208 uint new_faces_num = 0;
210#define MOD_SOLIDIFY_EMPTY_TAG uint(-1)
220 uint largest_ngon = 3;
227 const int2 &edge = orig_edges[orig_corner_edges[face.
start()]];
229 sub_v3_v3v3(edgedir, orig_vert_positions[edge[1]], orig_vert_positions[edge[0]]);
231 face_nors[
i][2] = 1.0f;
234 face_nors[
i][1] = 1.0f;
237 null_faces[
i] =
true;
244 new_face_ref_a.
face = face;
248 face_sides_arr[
i * 2] = std::move(new_face_ref_a);
253 new_face_ref_b.
face = face;
257 face_sides_arr[
i * 2 + 1] = std::move(new_face_ref_b);
259 if (face.
size() > largest_ngon) {
265 new_loops_num +=
uint(face.
size() * 2);
274 for (
const int64_t edge : orig_corner_edges.
slice(orig_faces[
i])) {
275 edge_adj_faces_len[edge]++;
288 for (
uint i = 0;
i < verts_num;
i++) {
296 bool has_singularities =
false;
303 for (
uint i = 0;
i < verts_num;
i++) {
304 orig_mvert_co[
i][0] = orig_vert_positions[
i][0];
305 orig_mvert_co[
i][1] = orig_vert_positions[
i][1];
306 orig_mvert_co[
i][2] = orig_vert_positions[
i][2];
316 for (
const int64_t corner : orig_faces[
i]) {
317 const int vert = orig_corner_verts[corner];
318 const int edge = orig_corner_edges[corner];
319 const bool reversed = orig_edges[edge][1] != vert;
321 if (old_face_edge_ref ==
nullptr) {
322 const uint len = edge_adj_faces_len[edge];
326 adj_faces[0] =
uint(
i);
327 for (
uint k = 1; k <
len; k++) {
330 adj_faces_reversed[0] = reversed;
333 edge_adj_faces[edge] = ref;
348 float edgedir[3] = {0, 0, 0};
358 for (
uint i = 0;
i < edges_num;
i++) {
359 const int2 &edge = orig_edges[
i];
360 if (edge_adj_faces_len[
i] > 0) {
361 uint v1 = vm[edge[0]];
373 if (orig_edge_lengths[
i] <= merge_tolerance_sqr) {
377 bool can_merge =
true;
378 for (
uint k = 0; k < edges_num && can_merge; k++) {
379 if (k !=
i && edge_adj_faces_len[k] > 0 &&
380 (
ELEM(vm[orig_edges[k][0]], v1,
v2) !=
ELEM(vm[orig_edges[k][1]], v1,
v2)))
382 for (
uint j = 0; j < edge_adj_faces[k]->
faces_len && can_merge; j++) {
385 int cur = face.
size() - 1;
387 uint cur_v = vm[orig_corner_verts[face[cur]]];
388 uint next_v = vm[orig_corner_verts[face[
next]]];
389 changes += (
ELEM(cur_v, v1,
v2) !=
ELEM(next_v, v1,
v2));
392 can_merge = can_merge && changes <= 2;
398 orig_edge_lengths[
i] = 0.0f;
399 vert_adj_edges_len[v1]++;
400 vert_adj_edges_len[
v2]++;
405 (combined_verts[
v2] + 1) /
406 float(combined_verts[v1] + combined_verts[
v2] + 2));
408 for (
uint j =
v2; j < verts_num; j++) {
413 vert_adj_edges_len[v1] += vert_adj_edges_len[
v2];
414 vert_adj_edges_len[
v2] = 0;
415 combined_verts[v1] += combined_verts[
v2] + 1;
418 new_loops_num -= edge_adj_faces_len[
i] * 2;
421 edge_adj_faces_len[
i] = 0;
425 edge_adj_faces[
i] =
nullptr;
428 orig_edge_lengths[
i] =
sqrtf(orig_edge_lengths[
i]);
429 vert_adj_edges_len[v1]++;
430 vert_adj_edges_len[
v2]++;
435 for (
uint i = 0;
i < edges_num;
i++) {
436 const int2 &edge = orig_edges[
i];
437 const uint v1 = vm[edge[0]];
438 const uint v2 = vm[edge[1]];
439 if (v1 ==
v2 && edge_adj_faces[
i]) {
442 const uint face = edge_adj_faces[
i]->
faces[j];
443 if (!face_singularity[face]) {
444 bool is_singularity =
true;
445 for (
const int vert : orig_corner_verts.
slice(orig_faces[face])) {
446 if (vm[vert] != v1) {
447 is_singularity =
false;
451 if (is_singularity) {
452 face_singularity[face] =
true;
462 new_loops_num -= edge_adj_faces_len[
i] * 2;
465 edge_adj_faces_len[
i] = 0;
469 edge_adj_faces[
i] =
nullptr;
479 for (
uint i = 0;
i < edges_num;
i++) {
480 const int2 &edge = orig_edges[
i];
481 if (edge_adj_faces_len[
i] > 0) {
482 const int vs[2] = {int(vm[edge[0]]), int(vm[edge[1]])};
483 uint invalid_edge_index = 0;
484 bool invalid_edge_reversed =
false;
485 for (
uint j = 0; j < 2; j++) {
486 const int vert = vs[j];
487 const uint len = vert_adj_edges_len[vert];
490 if (old_edge_vert_ref ==
nullptr) {
493 for (
uint k = 1; k <
len; k++) {
498 vert_adj_edges[vert] = ref;
501 const uint *f = old_edge_vert_ref->
edges;
503 const uint edge = old_edge_vert_ref->
edges[k];
505 old_edge_vert_ref->
edges[k] =
i;
509 if (vm[orig_edges[edge][0]] == vs[1 - j]) {
510 invalid_edge_index = edge + 1;
511 invalid_edge_reversed = (j == 0);
514 if (vm[orig_edges[edge][1]] == vs[1 - j]) {
515 invalid_edge_index = edge + 1;
516 invalid_edge_reversed = (j == 1);
520 if (invalid_edge_index) {
531 if (invalid_edge_index) {
532 const uint tmp = invalid_edge_index - 1;
533 invalid_edge_index =
i;
536 OldEdgeFaceRef *invalid_adj_faces = edge_adj_faces[invalid_edge_index];
540 if (i_adj_faces->
faces[k] == invalid_adj_faces->
faces[
l] &&
551 new_faces_num -= 2 * j;
552 new_loops_num -= 4 * j;
561 adj_faces[j] = i_adj_faces->
faces[k];
567 adj_faces[j] = invalid_adj_faces->
faces[k];
568 adj_faces_loops_reversed[j++] = (invalid_edge_reversed !=
573 edge_adj_faces_len[invalid_edge_index] = 0;
574 edge_adj_faces_len[
i] =
len;
578 i_adj_faces->
faces = adj_faces;
580 i_adj_faces->
used += invalid_adj_faces->
used;
584 edge_adj_faces[invalid_edge_index] = i_adj_faces;
586 i = invalid_edge_index;
596 const int2 *edge = orig_edges.
data();
599 for (
uint i = 0;
i < edges_num;
i++, edge++) {
600 if (edge_adj_faces_len[
i] > 0) {
607 for (
uint j = 0; j < adj_len; j++) {
609 const int j_loopstart = orig_faces[face].start();
610 const int totloop = orig_faces[face].
size();
611 const uint j_first_v = vm[orig_corner_verts[j_loopstart]];
612 for (
uint k = j + 1; k < adj_len; k++) {
613 if (orig_faces[adj_faces->
faces[k]].
size() != totloop) {
617 const int k_loopstart = orig_faces[adj_faces->
faces[k]].start();
620 const int *corner_vert = &orig_corner_verts[k_loopstart];
621 for (
l = 0;
l < totloop && vm[*corner_vert] != j_first_v;
l++, corner_vert++) {
630 const int count_dir = reversed ? -1 : 1;
631 bool has_diff =
false;
632 for (
int m = 0, n =
l + totloop; m < totloop && !has_diff; m++, n += count_dir) {
633 const int vert = orig_corner_verts[j_loopstart + m];
634 has_diff = has_diff ||
635 vm[vert] != vm[orig_corner_verts[k_loopstart + n % totloop]];
640 for (
uint m = 0; m < totloop; m++) {
641 const int e = orig_corner_edges[j_loopstart + m];
645 uint *e_adj_faces_faces = e_adj_faces->
faces;
648 if (e_adj_faces_faces != adj_faces->
faces) {
651 face_index < faces_len && e_adj_faces_faces[face_index] != face;
657 if (face_index == faces_len) {
665 memmove(e_adj_faces_faces + face_index,
666 e_adj_faces_faces + face_index + 1,
667 (faces_len - face_index - 1) *
sizeof(*e_adj_faces_faces));
668 memmove(e_adj_faces_reversed + face_index,
669 e_adj_faces_reversed + face_index + 1,
670 (faces_len - face_index - 1) *
sizeof(*e_adj_faces_reversed));
672 if (edge_adj_faces_len[
e] > 0) {
673 edge_adj_faces_len[
e]--;
674 if (edge_adj_faces_len[
e] == 0) {
676 edge_adj_faces[
e] =
nullptr;
679 else if (e_adj_faces->
used > 1) {
680 for (
uint n = 0; n < edges_num; n++) {
681 if (edge_adj_faces[n] == e_adj_faces && edge_adj_faces_len[n] > 0) {
682 edge_adj_faces_len[n]--;
683 if (edge_adj_faces_len[n] == 0) {
684 edge_adj_faces[n]->
used--;
685 edge_adj_faces[n] =
nullptr;
696 new_loops_num -= 2 * del_loops;
709 for (
uint i = 0;
i < edges_num;
i++) {
710 const int2 &edge = orig_edges[
i];
711 const uint v1 = vm[edge[0]];
712 const uint v2 = vm[edge[1]];
713 if (edge_adj_faces_len[
i] > 0) {
714 if (
LIKELY(orig_edge_lengths[
i] > FLT_EPSILON)) {
716 mul_v3_fl(edgedir, 1.0f / orig_edge_lengths[
i]);
728 for (
int j = 0; j < link1->
edges_len; j++) {
730 if (edge_adj_faces_len[
e] > 0 &&
e !=
i) {
732 vm[vm[orig_edges[
e][0]] == v1 ? orig_edges[
e][1] : orig_edges[
e][0]];
740 for (
int j = 0; j < link2->
edges_len; j++) {
742 if (edge_adj_faces_len[
e] > 0 &&
e !=
i) {
744 vm[vm[orig_edges[
e][0]] ==
v2 ? orig_edges[
e][1] : orig_edges[
e][0]];
760 const uint *adj_faces_faces = adj_faces->
faces;
762 uint new_edges_len = 0;
765 new_edges_len = adj_len;
767 float ref_nor[3] = {0, 0, 0};
769 for (
uint j = 0; j < adj_len; j++) {
770 const bool reverse = adj_faces_reversed[j];
771 const uint face_i = adj_faces_faces[j];
779 if (orig_faces[face_i].
size() > 3) {
789 sorted_faces[j].
angle = 0.0f;
793 sorted_faces[j].
angle = 0.0f;
799 sorted_faces[j].
face =
800 &face_sides_arr[adj_faces_faces[j] * 2 + (adj_faces_reversed[j] ? 1 : 0)];
808 sorted_faces[0].
face =
809 &face_sides_arr[adj_faces_faces[0] * 2 + (adj_faces_reversed[0] ? 1 : 0)];
819 new_edges[new_edges_len] =
nullptr;
821 for (
uint j = 0; j < new_edges_len; j++) {
824 const uint next_j = j + 1 == adj_len ? 0 : j + 1;
827 sorted_faces[next_j].
face + 1;
835 sorted_faces[0].
face + j;
841 if (do_shell || (adj_len == 1 && do_rim)) {
842 edge_data_edge_index = 0;
852 new_edge_ref.
new_edge = edge_data_edge_index;
853 *edge_data = new_edge_ref;
855 new_edges[j] = edge_data;
856 for (
uint k = 0; k < 2; k++) {
857 if (
faces[k] !=
nullptr) {
858 for (
int l = 0;
l <
faces[k]->face.size();
l++) {
859 const int edge = orig_corner_edges[
faces[k]->face.start() +
l];
860 if (edge_adj_faces[edge] == edge_adj_faces[
i]) {
861 if (edge !=
i && orig_edge_data_arr[edge] ==
nullptr) {
862 orig_edge_data_arr[edge] = new_edges;
864 faces[k]->link_edges[
l] = edge_data;
872 orig_edge_data_arr[
i] = new_edges;
873 if (do_shell || (adj_len == 1 && do_rim)) {
874 new_edges_num += new_edges_len;
880 for (
uint i = 0;
i < edges_num;
i++) {
881 if (edge_adj_faces[
i]) {
882 if (edge_adj_faces[
i]->used > 1) {
883 edge_adj_faces[
i]->
used--;
898 for (
uint i = 0;
i < verts_num;
i++, adj_edges_ptr++) {
899 if (*adj_edges_ptr !=
nullptr && (*adj_edges_ptr)->
edges_len >= 2) {
903 bool contains_long_groups =
false;
904 uint topo_groups = 0;
908 const uint *adj_edges = (*adj_edges_ptr)->edges;
909 const uint tot_adj_edges = (*adj_edges_ptr)->edges_len;
911 uint unassigned_edges_len = 0;
912 for (
uint j = 0; j < tot_adj_edges; j++) {
913 NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]];
919 unassigned_edges_len++;
926 for (
uint j = 0, k = 0; j < tot_adj_edges; j++) {
927 NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]];
930 unassigned_edges[k++] = *new_edges;
938 uint edge_groups_len = unassigned_edges_len / 2;
941 uint assigned_edges_len = 0;
943 uint found_edge_index = 0;
944 bool insert_at_start =
false;
945 uint eg_capacity = 5;
946 NewFaceRef *eg_track_faces[2] = {
nullptr,
nullptr};
949 while (assigned_edges_len < unassigned_edges_len) {
950 found_edge =
nullptr;
951 insert_at_start =
false;
952 if (eg_index >= 0 && edge_groups[eg_index].edges_len == 0) {
958 while (!edge && j < unassigned_edges_len) {
959 edge = unassigned_edges[j++];
960 if (edge && last_open_edge_track &&
961 (edge->
faces[0] != last_open_edge_track || edge->
faces[1] !=
nullptr))
966 if (!edge && last_open_edge_track) {
968 last_open_edge_track =
nullptr;
971 while (!edge && j < unassigned_edges_len) {
972 edge = unassigned_edges[j++];
975 else if (!last_open_edge_track && eg_index > 0) {
980 found_edge_index = j - 1;
982 if (!last_open_edge_track && vm[orig_edges[edge->
old_edge][0]] ==
i) {
983 eg_track_faces[0] = edge->
faces[0];
984 eg_track_faces[1] = edge->
faces[1];
985 if (edge->
faces[1] ==
nullptr) {
991 eg_track_faces[0] = edge->
faces[1];
992 eg_track_faces[1] = edge->
faces[0];
995 else if (eg_index >= 0) {
997 for (found_edge_index = 0; found_edge_index < unassigned_edges_len;
998 found_edge_index++, edge_ptr++)
1002 if (edge->
faces[0] == eg_track_faces[1]) {
1003 insert_at_start =
false;
1004 eg_track_faces[1] = edge->
faces[1];
1006 if (edge->
faces[1] ==
nullptr) {
1013 if (edge->
faces[0] == eg_track_faces[0]) {
1014 insert_at_start =
true;
1015 eg_track_faces[0] = edge->
faces[1];
1017 if (edge->
faces[1] ==
nullptr) {
1022 if (edge->
faces[1] !=
nullptr) {
1023 if (edge->
faces[1] == eg_track_faces[1]) {
1024 insert_at_start =
false;
1025 eg_track_faces[1] = edge->
faces[0];
1029 if (edge->
faces[1] == eg_track_faces[0]) {
1030 insert_at_start =
true;
1031 eg_track_faces[0] = edge->
faces[0];
1040 unassigned_edges[found_edge_index] =
nullptr;
1041 assigned_edges_len++;
1042 const uint needed_capacity = edge_groups[eg_index].
edges_len + 1;
1043 if (needed_capacity > eg_capacity) {
1044 eg_capacity = needed_capacity + 1;
1046 if (insert_at_start) {
1048 edge_groups[eg_index].edges,
1049 edge_groups[eg_index].edges_len *
sizeof(*new_eg));
1053 edge_groups[eg_index].edges,
1054 edge_groups[eg_index].edges_len *
sizeof(*new_eg));
1057 edge_groups[eg_index].
edges = new_eg;
1059 else if (insert_at_start) {
1060 memmove(edge_groups[eg_index].edges + 1,
1061 edge_groups[eg_index].edges,
1062 edge_groups[eg_index].edges_len *
sizeof(*edge_groups[eg_index].edges));
1064 edge_groups[eg_index].
edges[insert_at_start ? 0 : edge_groups[eg_index].
edges_len] =
1067 if (edge_groups[eg_index].edges[edge_groups[eg_index].edges_len - 1]->
faces[1] !=
1070 last_open_edge_track =
nullptr;
1072 if (edge_groups[eg_index].edges_len > 3) {
1073 contains_long_groups =
true;
1085 edge_group.
valid =
true;
1086 edge_group.
edges = edges;
1091 edge_group.
split = 0;
1097 edge_groups[eg_index] = edge_group;
1099 eg_track_faces[0] =
nullptr;
1100 eg_track_faces[1] =
nullptr;
1117 if (contains_long_groups) {
1119 for (
uint j = 0; j < eg_index; j++) {
1120 const uint edges_len = edge_groups[j + add_index].
edges_len;
1121 if (edges_len > 3) {
1122 bool has_doubles =
false;
1124 EdgeGroup g = edge_groups[j + add_index];
1125 for (
uint k = 0; k < edges_len; k++) {
1126 for (
uint l = k + 1;
l < edges_len;
l++) {
1135 const uint prior_splits = splits;
1136 const uint prior_index = add_index;
1137 int unique_start = -1;
1138 int first_unique_end = -1;
1139 int last_split = -1;
1140 int first_split = -1;
1141 bool first_even_split =
false;
1143 while (real_k < edges_len ||
1146 (first_unique_end == -1 ? 0 : first_unique_end) +
int(edges_len) ||
1147 first_split != last_split)))
1149 const uint k = real_k % edges_len;
1151 if (first_unique_end != -1 && unique_start == -1) {
1152 unique_start = int(real_k);
1155 else if (first_unique_end == -1) {
1156 first_unique_end = int(k);
1158 else if (unique_start != -1) {
1159 const uint split = ((
uint(unique_start) + real_k + 1) / 2) % edges_len;
1160 const bool is_even_split = ((
uint(unique_start) + real_k) & 1);
1161 if (last_split != -1) {
1163 if (prior_splits != splits) {
1164 memmove(edge_groups + j + add_index + 1,
1165 edge_groups + j + add_index,
1166 (
uint(eg_index) - j) *
sizeof(*edge_groups));
1169 if (last_split >
split) {
1170 const uint edges_len_group = (
split + edges_len) -
uint(last_split);
1174 g.
edges + last_split,
1175 (edges_len -
uint(last_split)) *
sizeof(*edges));
1176 memcpy(edges + (edges_len -
uint(last_split)),
1178 split *
sizeof(*edges));
1181 edge_group.
valid =
true;
1182 edge_group.
edges = edges;
1193 edge_groups[j + add_index] = edge_group;
1199 memcpy(edges, g.
edges + last_split, edges_len_group *
sizeof(*edges));
1202 edge_group.
valid =
true;
1203 edge_group.
edges = edges;
1214 edge_groups[j + add_index] = edge_group;
1218 last_split = int(
split);
1219 if (first_split == -1) {
1220 first_split = int(
split);
1221 first_even_split = is_even_split;
1227 if (first_split != -1) {
1229 if (prior_splits != splits) {
1230 memmove(edge_groups + (j + prior_index + 1),
1231 edge_groups + (j + prior_index),
1232 (
uint(eg_index) + add_index - (j + prior_index)) *
1233 sizeof(*edge_groups));
1234 memmove(edge_groups + (j + add_index + 2),
1235 edge_groups + (j + add_index + 1),
1236 (
uint(eg_index) - j) *
sizeof(*edge_groups));
1240 memmove(edge_groups + (j + add_index + 2),
1241 edge_groups + (j + add_index + 1),
1242 (
uint(eg_index) - j - 1) *
sizeof(*edge_groups));
1246 memcpy(edges, g.
edges,
uint(first_split) *
sizeof(*edges));
1249 edge_group_a.
valid =
true;
1250 edge_group_a.
edges = edges;
1255 edge_group_a.
split = 1;
1261 edge_groups[j + prior_index] = edge_group_a;
1268 g.
edges + last_split,
1269 (edges_len -
uint(last_split)) *
sizeof(*edges));
1272 edge_group_b.
valid =
true;
1273 edge_group_b.
edges = edges;
1278 edge_group_b.
split = add_index - prior_index + 1;
1284 edge_groups[j + add_index] = edge_group_b;
1286 if (prior_splits != splits) {
1290 if (first_unique_end != -1 && prior_splits == splits) {
1291 has_singularities =
true;
1301 orig_vert_groups_arr[
i] = edge_groups;
1305 bool contains_open_splits =
false;
1306 uint open_edges = 0;
1307 uint contains_splits = 0;
1308 uint last_added = 0;
1309 uint first_added = 0;
1310 bool first_set =
false;
1313 for (
uint j = 0; j < g->edges_len; j++,
e++) {
1314 const uint flip =
uint(vm[orig_edges[(*e)->old_edge][1]] ==
i);
1315 BLI_assert(flip || vm[orig_edges[(*e)->old_edge][0]] ==
i);
1316 (*e)->link_edge_groups[flip] = g;
1319 if (do_shell || (do_rim && !g->is_orig_closed)) {
1321 g->new_vert = new_verts_num++;
1322 if (do_rim || (do_shell && g->split)) {
1324 contains_splits += (g->split != 0);
1325 contains_open_splits |= g->split && !g->is_orig_closed;
1329 open_edges +=
uint(added < last_added);
1332 first_added = added;
1335 if (!(g + 1)->valid || g->topo_group != (g + 1)->topo_group) {
1336 if (new_verts > 2) {
1338 new_edges_num += new_verts;
1339 open_edges +=
uint(first_added < last_added);
1340 open_edges -=
uint(open_edges && !contains_open_splits);
1341 if (do_shell && do_rim) {
1342 new_loops_num += new_verts * 2;
1344 else if (do_shell) {
1345 new_loops_num += new_verts * 2 - open_edges;
1348 new_loops_num += new_verts * 2 + open_edges - contains_splits;
1351 else if (new_verts == 2) {
1353 new_loops_num += 2u -
uint(!(do_rim && do_shell) && contains_open_splits);
1356 contains_open_splits =
false;
1357 contains_splits = 0;
1388 float *face_weight =
nullptr;
1390 if (do_flat_faces) {
1394 float scalar_vgroup = 1.0f;
1395 for (
const int vert : orig_corner_verts.
slice(orig_faces[
i])) {
1397 if (defgrp_invert) {
1405 scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv);
1406 face_weight[
i] = scalar_vgroup;
1410 gs_ptr = orig_vert_groups_arr;
1411 for (
uint i = 0;
i < verts_num;
i++, gs_ptr++) {
1414 if (!g->is_singularity) {
1420 float move_nor[3] = {0, 0, 0};
1423 (g->is_orig_closed || g->split));
1424 bool approximate_free_direction =
false;
1431 uint queue_index = 0;
1433 float fallback_nor[3];
1434 float fallback_ofs = 0.0f;
1436 const bool cycle = (g->is_orig_closed && !g->split) || g->is_even_split;
1437 for (
uint k = 0; k < g->edges_len; k++, edge_ptr++) {
1438 if (!(k & 1) || (!cycle && k == g->edges_len - 1)) {
1440 for (
uint l = 0;
l < 2;
l++) {
1442 if (face && (first_edge ==
nullptr ||
1443 (first_edge->
faces[0] != face && first_edge->
faces[1] != face)))
1445 float ofs = face->
reversed ? ofs_back_clamped : ofs_front_clamped;
1447 if (do_flat_faces) {
1448 ofs *= face_weight[face->
index];
1451 if (!null_faces[face->
index]) {
1454 face_nors[face->
index],
1456 planes_queue[queue_index++][3] = ofs;
1466 if ((cycle && k == 0) || (!cycle && k + 3 >= g->edges_len)) {
1471 if (queue_index > 2) {
1476 for (
uint k = 0; k < queue_index; k++) {
1477 for (
uint m = k + 1; m < queue_index; m++) {
1478 float p =
dot_v3v3(planes_queue[k], planes_queue[m]);
1488 swap_v4_v4(planes_queue[min_n0], planes_queue[0]);
1489 swap_v4_v4(planes_queue[min_n1], planes_queue[1]);
1492 swap_v4_v4(planes_queue[min_n0], planes_queue[1]);
1497 float max_p = -1.0f;
1498 for (
uint k = 2; k < queue_index; k++) {
1500 dot_v3v3(planes_queue[1], planes_queue[k]));
1501 if (max_p <= min_p) {
1506 swap_v4_v4(planes_queue[min_n1], planes_queue[2]);
1509 while (queue_index > 2) {
1512 float best_p = -1.0f;
1513 float best_ofs_diff = 0.0f;
1514 for (
uint k = 0; k < queue_index; k++) {
1515 for (
uint m = k + 1; m < queue_index; m++) {
1516 float p =
dot_v3v3(planes_queue[m], planes_queue[k]);
1517 float ofs_diff =
fabsf(planes_queue[m][3] - planes_queue[k][3]);
1518 if (p > best_p + FLT_EPSILON || (p >= best_p && ofs_diff < best_ofs_diff)) {
1520 best_ofs_diff = ofs_diff;
1528 if (best_p < 0.98f) {
1531 add_v3_v3(planes_queue[best_n0], planes_queue[best_n1]);
1533 planes_queue[best_n0][3] = (planes_queue[best_n0][3] + planes_queue[best_n1][3]) *
1536 memmove(planes_queue + best_n1,
1537 planes_queue + best_n1 + 1,
1538 (queue_index - best_n1) *
sizeof(*planes_queue));
1548 const float boundary_fix_threshold = 0.7f;
1553 for (
int k = 0; k < 3; k++) {
1554 for (
int m = 0; m <
size; m++) {
1555 madd_v3_v3fl(mat[k], planes_queue[m], planes_queue[m][k]);
1565 for (
int k = 0; k <
size; k++) {
1570 if (!disable_boundary_fix) {
1572 float greatest_angle_cos = 1.0f;
1573 for (
uint k = 0; k < 2; k++) {
1575 float p =
dot_v3v3(planes_queue[m], planes_queue[k]);
1576 greatest_angle_cos = std::min(p, greatest_angle_cos);
1579 if (greatest_angle_cos > boundary_fix_threshold) {
1580 approximate_free_direction =
true;
1583 disable_boundary_fix =
true;
1587 else if (
size > 1) {
1590 const float q =
dot_v3v3(planes_queue[0], planes_queue[1]);
1591 float d = 1.0f - q * q;
1594 if (d > FLT_EPSILON * 10 && q < stop_explosion) {
1596 mul_v3_fl(planes_queue[0], (planes_queue[0][3] - planes_queue[1][3] * q) * d);
1597 mul_v3_fl(planes_queue[1], (planes_queue[1][3] - planes_queue[0][3] * q) * d);
1600 d = 1.0f / (
fabsf(q) + 1.0f);
1601 mul_v3_fl(planes_queue[0], planes_queue[0][3] * d);
1602 mul_v3_fl(planes_queue[1], planes_queue[1][3] * d);
1606 d =
dot_v3v3(planes_queue[2], move_nor);
1609 if (
fabsf(d) > 0.02f) {
1615 if (
fabsf(d) > 1.0f - boundary_fix_threshold) {
1616 disable_boundary_fix =
true;
1620 approximate_free_direction =
false;
1622 else if (
size == 1) {
1625 if (g->edges_len > 2) {
1626 disable_boundary_fix =
true;
1627 approximate_free_direction =
true;
1633 disable_boundary_fix =
true;
1639 float total_angle = 0;
1640 float total_angle_back = 0;
1644 float nor_back[3] = {0, 0, 0};
1645 bool has_back =
false;
1646 bool has_front =
false;
1647 bool cycle = (g->is_orig_closed && !g->split) || g->is_even_split;
1648 for (
uint k = 0; k < g->edges_len; k++, edge_ptr++) {
1649 if (!(k & 1) || (!cycle && k == g->edges_len - 1)) {
1651 for (
uint l = 0;
l < 2;
l++) {
1653 if (face && (first_edge ==
nullptr ||
1654 (first_edge->
faces[0] != face && first_edge->
faces[1] != face)))
1657 float ofs = face->
reversed ? -ofs_back_clamped : ofs_front_clamped;
1659 if (do_flat_faces) {
1660 ofs *= face_weight[face->
index];
1667 int corner = corner_next + (face->
face.
size() - 1);
1668 int corner_prev = corner - 1;
1671 m < face->
face.
size() && vm[orig_corner_verts[corner]] !=
i;
1674 corner_prev = corner;
1675 corner = corner_next;
1679 orig_mvert_co[vm[orig_corner_verts[corner_next]]]);
1681 total_angle_back +=
angle * ofs * ofs;
1684 total_angle +=
angle * ofs * ofs;
1706 if ((cycle && k == 0) || (!cycle && k + 3 >= g->edges_len)) {
1716 if (
LIKELY(length_sq > FLT_EPSILON)) {
1722 if (
LIKELY(length_sq > FLT_EPSILON)) {
1723 mul_v3_fl(nor_back, total_angle_back / length_sq);
1729 if (has_front && has_back) {
1731 float nor_back_length =
len_v3(nor_back);
1734 q /= nor_length * nor_back_length;
1736 float d = 1.0f - q * q;
1737 if (
LIKELY(d > FLT_EPSILON)) {
1739 if (
LIKELY(nor_length > FLT_EPSILON)) {
1740 mul_v3_fl(
nor, (1 - nor_back_length * q / nor_length) * d);
1742 if (
LIKELY(nor_back_length > FLT_EPSILON)) {
1743 mul_v3_fl(nor_back, (1 - nor_length * q / nor_back_length) * d);
1755 if (has_front && total_angle > FLT_EPSILON) {
1758 if (has_back && total_angle_back > FLT_EPSILON) {
1759 mul_v3_fl(nor_back, 1.0f / total_angle_back);
1761 if (has_front && total_angle > FLT_EPSILON) {
1767 if (!disable_boundary_fix && g->edges_len > 2) {
1768 approximate_free_direction =
true;
1771 disable_boundary_fix =
true;
1774 if (approximate_free_direction) {
1779 for (k = 1; k + 1 < g->edges_len; k++, edge_ptr++) {
1780 const int2 &edge = orig_edges[(*edge_ptr)->old_edge];
1782 tmp, orig_mvert_co[vm[edge[0]] ==
i ? edge[1] : edge[0]], orig_mvert_co[
i]);
1786 disable_boundary_fix =
true;
1793 if (!disable_boundary_fix) {
1795 float constr_nor[3];
1796 const int2 &e0_edge = orig_edges[g->edges[0]->old_edge];
1797 const int2 &e1_edge = orig_edges[g->edges[g->edges_len - 1]->old_edge];
1801 orig_mvert_co[vm[e0_edge[0]] ==
i ? e0_edge[1] : e0_edge[0]],
1804 orig_mvert_co[vm[e1_edge[0]] ==
i ? e1_edge[1] : e1_edge[0]],
1815 if (g->edges[0]->faces[0]->reversed) {
1816 negate_v3_v3(f0, face_nors[g->edges[0]->faces[0]->index]);
1819 copy_v3_v3(f0, face_nors[g->edges[0]->faces[0]->index]);
1821 if (g->edges[g->edges_len - 1]->faces[0]->reversed) {
1822 negate_v3_v3(f1, face_nors[g->edges[g->edges_len - 1]->faces[0]->index]);
1825 copy_v3_v3(f1, face_nors[g->edges[g->edges_len - 1]->faces[0]->index]);
1836 float d =
dot_v3v3(constr_nor, move_nor);
1838 if (
fabsf(d) > 0.1f) {
1843 float scalar_vgroup = 1;
1845 if (dvert && !do_flat_faces) {
1847 if (defgrp_invert) {
1853 scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv);
1857 if (do_angle_clamp) {
1858 if (g->edges_len > 2) {
1859 float min_length = 0;
1862 for (
NewEdgeRef **p = g->edges; k < g->edges_len; k++, p++) {
1863 float length = orig_edge_lengths[(*p)->old_edge];
1864 float e_ang = (*p)->angle;
1866 if (
length < min_length || k == 0) {
1872 float max_off = min_length * 0.5f / cos_ang;
1873 if (max_off < offset * 0.5f) {
1874 scalar_vgroup *= max_off / offset * 2;
1880 float min_length = 0;
1882 for (
NewEdgeRef **p = g->edges; k < g->edges_len; k++, p++) {
1883 float length = orig_edge_lengths[(*p)->old_edge];
1884 if (
length < min_length || k == 0) {
1888 if (min_length < offset) {
1889 scalar_vgroup *= min_length / offset;
1903 if (do_flat_faces) {
1917 uint(*singularity_edges)[2] =
nullptr;
1918 uint totsingularity = 0;
1919 if (has_singularities) {
1920 has_singularities =
false;
1922 uint singularity_edges_len = 1;
1924 for (
NewEdgeRef ***new_edges = orig_edge_data_arr;
i < edges_num;
i++, new_edges++) {
1925 if (*new_edges && (do_shell || edge_adj_faces_len[
i] == 1) && (**new_edges)->old_edge ==
i) {
1927 if ((*l)->link_edge_groups[0]->is_singularity &&
1928 (*l)->link_edge_groups[1]->is_singularity)
1930 const uint v1 = (*l)->link_edge_groups[0]->new_vert;
1931 const uint v2 = (*l)->link_edge_groups[1]->new_vert;
1932 bool exists_already =
false;
1934 for (
uint(*p)[2] = singularity_edges; j < totsingularity; p++, j++) {
1935 if (((*p)[0] == v1 && (*p)[1] ==
v2) || ((*p)[0] ==
v2 && (*p)[1] == v1)) {
1936 exists_already =
true;
1940 if (!exists_already) {
1941 has_singularities =
true;
1942 if (singularity_edges_len <= totsingularity) {
1943 singularity_edges_len = totsingularity + 1;
1944 singularity_edges =
static_cast<uint(*)[2]
>(
1946 singularity_edges_len *
sizeof(*singularity_edges),
1949 singularity_edges[totsingularity][0] = v1;
1950 singularity_edges[totsingularity][1] =
v2;
1952 if (edge_adj_faces_len[
i] == 1 && do_rim) {
1968 mesh,
int(new_verts_num),
int(new_edges_num),
int(new_faces_num),
int(new_loops_num));
1977 int *origindex_edge =
static_cast<int *
>(
1979 int *origindex_face =
static_cast<int *
>(
1983 if (orig_attributes.
contains(
"bevel_weight_edge") ||
1984 (bevel_convex != 0.0f || !orig_vert_bweight.
is_empty()))
1992 if (shell_defgrp_index != -1 || rim_defgrp_index != -1) {
1993 dst_dvert =
result->deform_verts_for_write().data();
1998 const VArraySpan vertex_crease = *orig_attributes.
lookup<
float>(
"crease_vert",
2002 if (!vertex_crease.
is_empty() || !orig_edge_crease.is_empty()) {
2007 result_attributes.
remove(
"crease_vert");
2013 gs_ptr = orig_vert_groups_arr;
2014 for (
uint i = 0;
i < verts_num;
i++, gs_ptr++) {
2021 copy_v3_v3(vert_positions[g->new_vert], g->co);
2031 edge_index += totsingularity;
2032 for (
NewEdgeRef ***new_edges = orig_edge_data_arr;
i < edges_num;
i++, new_edges++) {
2033 if (*new_edges && (do_shell || edge_adj_faces_len[
i] == 1) && (**new_edges)->old_edge ==
i) {
2036 const uint v1 = (*l)->link_edge_groups[0]->new_vert;
2037 const uint v2 = (*l)->link_edge_groups[1]->new_vert;
2039 if (has_singularities && ((*l)->link_edge_groups[0]->is_singularity &&
2040 (*l)->link_edge_groups[1]->is_singularity))
2043 for (
uint(*p)[2] = singularity_edges; j < totsingularity; p++, j++) {
2044 if (((*p)[0] == v1 && (*p)[1] ==
v2) || ((*p)[0] ==
v2 && (*p)[1] == v1)) {
2059 if (result_edge_crease) {
2060 result_edge_crease.span[
insert] = !orig_edge_crease.is_empty() ?
2061 orig_edge_crease[(*l)->old_edge] :
2064 if (result_edge_bweight) {
2065 result_edge_bweight.
span[
insert] = !orig_edge_bweight.is_empty() ?
2066 orig_edge_bweight[(*l)->old_edge] :
2068 if (bevel_convex != 0.0f && (*l)->faces[1] !=
nullptr) {
2071 ((*l)->angle >
M_PI + FLT_EPSILON ?
2072 clamp_f(bevel_convex, 0.0f, 1.0f) :
2073 ((*l)->angle <
M_PI - FLT_EPSILON ?
2074 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);
2127 const VArraySpan src_material_index = *orig_attributes.
lookup<
int>(
"material_index",
2134 gs_ptr = orig_vert_groups_arr;
2135 for (
uint i = 0;
i < verts_num;
i++, gs_ptr++) {
2142 float mv_crease = !vertex_crease.
is_empty() ? vertex_crease[
i] : 0.0f;
2143 float mv_bweight = !orig_vert_bweight.
is_empty() ? orig_vert_bweight[
i] : 0.0f;
2146 float last_max_crease = 0.0f;
2147 float first_max_crease = 0.0f;
2149 float last_max_bweight = 0.0f;
2150 float first_max_bweight = 0.0f;
2159 if (result_edge_crease) {
2160 if (!orig_edge_crease.is_empty()) {
2172 if (result_edge_crease) {
2173 if (!orig_edge_crease.is_empty() &&
2174 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 =
2189 !orig_edge_bweight.is_empty() ?
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.span[edge_index] =
max_ff(mv_crease,
2220 min_ff(last_max_crease, max_crease));
2222 if (result_edge_bweight) {
2223 result_edge_bweight.
span[edge_index] =
max_ff(
2224 mv_bweight,
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.span[edge_index] =
max_ff(
2251 mv_crease,
min_ff(last_max_crease, first_max_crease));
2253 if (result_edge_bweight) {
2254 result_edge_bweight.
span[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);
2309 dst_material_index.span[face_index] = most_mat_nr + (g->
is_orig_closed || !do_rim ?
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();
2689 result_edge_bweight.
finish();
2690 result_edge_crease.finish();