26 # pragma GCC diagnostic error "-Wsign-conversion"
129 return (
int)(
x->angle >
y->angle) - (
int)(
x->angle <
y->angle);
140 MVert *
mv, *mvert, *orig_mvert;
141 MEdge *ed, *medge, *orig_medge;
142 MLoop *ml, *mloop, *orig_mloop;
143 MPoly *mp, *mpoly, *orig_mpoly;
148 if (polys_num == 0 && verts_num != 0) {
154 const short mat_nr_max = mat_nrs - 1;
155 const short mat_ofs = mat_nrs > 1 ? smd->
mat_ofs : 0;
156 const short mat_ofs_rim = mat_nrs > 1 ? smd->
mat_ofs_rim : 0;
165 const float ofs_front_clamped =
clamp_nonzero(ofs_front, 1e-5f);
166 const float ofs_back_clamped =
clamp_nonzero(ofs_back, 1e-5f);
196 uint new_verts_num = 0;
197 uint new_edges_num = 0;
198 uint new_loops_num = 0;
199 uint new_polys_num = 0;
201 #define MOD_SOLIDIFY_EMPTY_TAG ((uint)-1)
208 polys_num * 2,
sizeof(*face_sides_arr),
"face_sides_arr in solidify");
213 uint largest_ngon = 3;
217 for (
uint i = 0; i < polys_num; i++, mp++) {
224 poly_nors[i][2] = 1.0f;
227 poly_nors[i][1] = 1.0f;
230 null_faces[i] =
true;
235 (
uint)mp->
totloop,
sizeof(*link_edges),
"NewFaceRef::link_edges in solidify");
237 .
face = mp, .index = i, .reversed =
false, .link_edges = link_edges};
239 (
uint)mp->
totloop,
sizeof(*link_edges),
"NewFaceRef::link_edges in solidify");
241 .
face = mp, .index = i, .reversed =
true, .link_edges = link_edges};
242 if (mp->
totloop > largest_ngon) {
254 edges_num,
sizeof(*edge_adj_faces_len),
"edge_adj_faces_len in solidify");
258 for (
uint i = 0; i < polys_num; i++, mp++) {
261 edge_adj_faces_len[ml->
e]++;
268 edges_num,
sizeof(*orig_edge_data_arr),
"orig_edge_data_arr in solidify");
271 edges_num,
sizeof(*orig_edge_lengths),
"orig_edge_lengths in solidify");
274 verts_num,
sizeof(*orig_vert_groups_arr),
"orig_vert_groups_arr in solidify");
277 for (
uint i = 0; i < verts_num; i++) {
285 bool has_singularities =
false;
289 verts_num,
sizeof(*vert_adj_edges),
"vert_adj_edges in solidify");
292 verts_num,
sizeof(*orig_mvert_co),
"orig_mvert_co in solidify");
294 for (
uint i = 0; i < verts_num; i++) {
295 orig_mvert_co[i][0] = orig_mvert[i].
co[0];
296 orig_mvert_co[i][1] = orig_mvert[i].
co[1];
297 orig_mvert_co[i][2] = orig_mvert[i].
co[2];
303 edges_num,
sizeof(*edge_adj_faces),
"edge_adj_faces in solidify");
308 for (
uint i = 0; i < polys_num; i++, mp++) {
311 const uint edge = ml->
e;
312 const bool reversed = orig_medge[edge].
v2 != ml->
v;
314 if (old_face_edge_ref ==
NULL) {
315 const uint len = edge_adj_faces_len[edge];
318 len,
sizeof(*adj_faces),
"OldEdgeFaceRef::faces in solidify");
320 len,
sizeof(*adj_faces_reversed),
"OldEdgeFaceRef::reversed in solidify");
322 for (
uint k = 1; k <
len; k++) {
325 adj_faces_reversed[0] = reversed;
328 edge_adj_faces[edge] = ref;
333 old_face_edge_ref->
faces[k] = i;
343 float edgedir[3] = {0, 0, 0};
345 verts_num,
sizeof(*vert_adj_edges_len),
"vert_adj_edges_len in solidify");
350 polys_num,
sizeof(*face_singularity),
"face_sides_arr in solidify");
354 verts_num,
sizeof(*combined_verts),
"combined_verts in solidify");
357 for (
uint i = 0; i < edges_num; i++, ed++) {
358 if (edge_adj_faces_len[i] > 0) {
371 if (orig_edge_lengths[i] <= merge_tolerance_sqr) {
375 bool can_merge =
true;
376 for (
uint k = 0; k < edges_num && can_merge; k++) {
377 if (k != i && edge_adj_faces_len[k] > 0 &&
379 for (
uint j = 0; j < edge_adj_faces[k]->
faces_len && can_merge; j++) {
380 mp = orig_mpoly + edge_adj_faces[k]->
faces[j];
389 can_merge = can_merge && changes <= 2;
395 orig_edge_lengths[i] = 0.0f;
396 vert_adj_edges_len[
v1]++;
397 vert_adj_edges_len[
v2]++;
402 (combined_verts[
v2] + 1) /
403 (
float)(combined_verts[
v1] + combined_verts[
v2] + 2));
405 for (
uint j =
v2; j < verts_num; j++) {
410 vert_adj_edges_len[
v1] += vert_adj_edges_len[
v2];
411 vert_adj_edges_len[
v2] = 0;
412 combined_verts[
v1] += combined_verts[
v2] + 1;
415 new_loops_num -= edge_adj_faces_len[i] * 2;
418 edge_adj_faces_len[i] = 0;
420 MEM_freeN(edge_adj_faces[i]->faces_reversed);
422 edge_adj_faces[i] =
NULL;
425 orig_edge_lengths[i] =
sqrtf(orig_edge_lengths[i]);
426 vert_adj_edges_len[
v1]++;
427 vert_adj_edges_len[
v2]++;
433 for (
uint i = 0; i < edges_num; i++, ed++) {
436 if (
v1 ==
v2 && edge_adj_faces[i]) {
439 const uint face = edge_adj_faces[i]->
faces[j];
440 if (!face_singularity[face]) {
441 bool is_singularity =
true;
442 for (
uint k = 0; k < orig_mpoly[face].
totloop; k++) {
443 if (vm[orig_mloop[((
uint)orig_mpoly[face].loopstart) + k].
v] !=
v1) {
444 is_singularity =
false;
448 if (is_singularity) {
449 face_singularity[face] =
true;
459 new_loops_num -= edge_adj_faces_len[i] * 2;
462 edge_adj_faces_len[i] = 0;
464 MEM_freeN(edge_adj_faces[i]->faces_reversed);
466 edge_adj_faces[i] =
NULL;
477 for (
uint i = 0; i < edges_num; i++, ed++) {
478 if (edge_adj_faces_len[i] > 0) {
479 const uint vs[2] = {vm[ed->
v1], vm[ed->
v2]};
480 uint invalid_edge_index = 0;
481 bool invalid_edge_reversed =
false;
482 for (
uint j = 0; j < 2; j++) {
483 const uint vert = vs[j];
484 const uint len = vert_adj_edges_len[vert];
487 if (old_edge_vert_ref ==
NULL) {
489 len,
sizeof(*adj_edges),
"OldVertEdgeRef::edges in solidify");
491 for (
uint k = 1; k <
len; k++) {
496 vert_adj_edges[vert] = ref;
499 const uint *f = old_edge_vert_ref->
edges;
501 const uint edge = old_edge_vert_ref->
edges[k];
503 old_edge_vert_ref->
edges[k] = i;
507 if (vm[orig_medge[edge].
v1] == vs[1 - j]) {
508 invalid_edge_index = edge + 1;
509 invalid_edge_reversed = (j == 0);
512 if (vm[orig_medge[edge].
v2] == vs[1 - j]) {
513 invalid_edge_index = edge + 1;
514 invalid_edge_reversed = (j == 1);
518 if (invalid_edge_index) {
529 if (invalid_edge_index) {
530 const uint tmp = invalid_edge_index - 1;
531 invalid_edge_index = i;
534 OldEdgeFaceRef *invalid_adj_faces = edge_adj_faces[invalid_edge_index];
538 if (i_adj_faces->
faces[k] == invalid_adj_faces->
faces[
l] &&
548 new_polys_num -= 2 * j;
549 new_loops_num -= 4 * j;
553 len,
sizeof(*adj_faces),
"OldEdgeFaceRef::faces in solidify");
555 len,
sizeof(*adj_faces_loops_reversed),
"OldEdgeFaceRef::reversed in solidify");
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;
598 for (
uint i = 0; i < edges_num; i++, ed++) {
599 if (edge_adj_faces_len[i] > 0) {
606 for (
uint j = 0; j < adj_len; j++) {
608 const int j_loopstart = orig_mpoly[face].
loopstart;
609 const int totloop = orig_mpoly[face].
totloop;
610 const uint j_first_v = vm[orig_mloop[j_loopstart].
v];
611 for (
uint k = j + 1; k < adj_len; k++) {
612 if (orig_mpoly[adj_faces->
faces[k]].
totloop != totloop) {
616 const int k_loopstart = orig_mpoly[adj_faces->
faces[k]].
loopstart;
618 ml = orig_mloop + k_loopstart;
619 for (
l = 0;
l < totloop && vm[ml->
v] != j_first_v;
l++, ml++) {
627 const int count_dir = reversed ? -1 : 1;
628 bool has_diff =
false;
629 ml = orig_mloop + j_loopstart;
630 for (
int m = 0, n =
l + totloop; m < totloop && !has_diff;
631 m++, n += count_dir, ml++) {
632 has_diff = has_diff || vm[ml->
v] != vm[orig_mloop[k_loopstart + n % totloop].v];
636 ml = orig_mloop + j_loopstart;
638 for (
uint m = 0; m < totloop; m++, ml++) {
643 uint *e_adj_faces_faces = e_adj_faces->
faces;
646 if (e_adj_faces_faces != adj_faces->
faces) {
649 face_index < faces_len && e_adj_faces_faces[face_index] != face;
654 if (face_index == faces_len) {
662 memmove(e_adj_faces_faces + face_index,
663 e_adj_faces_faces + face_index + 1,
664 (faces_len - face_index - 1) *
sizeof(*e_adj_faces_faces));
665 memmove(e_adj_faces_reversed + face_index,
666 e_adj_faces_reversed + face_index + 1,
667 (faces_len - face_index - 1) *
sizeof(*e_adj_faces_reversed));
669 if (edge_adj_faces_len[
e] > 0) {
670 edge_adj_faces_len[
e]--;
671 if (edge_adj_faces_len[
e] == 0) {
673 edge_adj_faces[
e] =
NULL;
676 else if (e_adj_faces->
used > 1) {
677 for (
uint n = 0; n < edges_num; n++) {
678 if (edge_adj_faces[n] == e_adj_faces && edge_adj_faces_len[n] > 0) {
679 edge_adj_faces_len[n]--;
680 if (edge_adj_faces_len[n] == 0) {
681 edge_adj_faces[n]->
used--;
682 edge_adj_faces[n] =
NULL;
693 new_loops_num -= 2 * (
uint)del_loops;
707 for (
uint i = 0; i < edges_num; i++, ed++) {
710 if (edge_adj_faces_len[i] > 0) {
711 if (
LIKELY(orig_edge_lengths[i] > FLT_EPSILON)) {
713 mul_v3_fl(edgedir, 1.0f / orig_edge_lengths[i]);
725 for (
int j = 0; j < link1->
edges_len; j++) {
727 if (edge_adj_faces_len[
e] > 0 &&
e != i) {
729 vm[vm[orig_medge[
e].
v1] ==
v1 ? orig_medge[
e].v2 : orig_medge[
e].v1];
737 for (
int j = 0; j < link2->
edges_len; j++) {
739 if (edge_adj_faces_len[
e] > 0 &&
e != i) {
741 vm[vm[orig_medge[
e].
v1] ==
v2 ? orig_medge[
e].v2 : orig_medge[
e].v1];
757 const uint *adj_faces_faces = adj_faces->
faces;
759 uint new_edges_len = 0;
761 adj_len,
sizeof(*sorted_faces),
"sorted_faces in solidify");
763 new_edges_len = adj_len;
765 float ref_nor[3] = {0, 0, 0};
767 for (
uint j = 0; j < adj_len; j++) {
768 const bool reverse = adj_faces_reversed[j];
769 const uint face_i = adj_faces_faces[j];
777 if (orig_mpoly[face_i].totloop > 3) {
787 sorted_faces[j].
angle = 0.0f;
791 sorted_faces[j].
angle = 0.0f;
797 sorted_faces[j].
face = face_sides_arr + adj_faces_faces[j] * 2 +
798 (adj_faces_reversed[j] ? 1 : 0);
806 sorted_faces[0].
face = face_sides_arr + adj_faces_faces[0] * 2 +
807 (adj_faces_reversed[0] ? 1 : 0);
817 new_edges_len + 1,
sizeof(*new_edges),
"new_edges in solidify");
818 new_edges[new_edges_len] =
NULL;
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;
847 .new_edge = edge_data_edge_index};
848 new_edges[j] = edge_data;
849 for (
uint k = 0; k < 2; k++) {
851 ml = orig_mloop +
faces[k]->face->loopstart;
852 for (
int l = 0;
l <
faces[k]->face->totloop;
l++, ml++) {
853 if (edge_adj_faces[ml->
e] == edge_adj_faces[i]) {
854 if (ml->
e != i && orig_edge_data_arr[ml->
e] ==
NULL) {
855 orig_edge_data_arr[ml->
e] = new_edges;
857 faces[k]->link_edges[
l] = edge_data;
865 orig_edge_data_arr[i] = new_edges;
866 if (do_shell || (adj_len == 1 && do_rim)) {
867 new_edges_num += new_edges_len;
873 for (
uint i = 0; i < edges_num; i++) {
874 if (edge_adj_faces[i]) {
875 if (edge_adj_faces[i]->used > 1) {
876 edge_adj_faces[i]->
used--;
880 MEM_freeN(edge_adj_faces[i]->faces_reversed);
891 for (
uint i = 0; i < verts_num; i++, adj_edges_ptr++) {
892 if (*adj_edges_ptr !=
NULL && (*adj_edges_ptr)->edges_len >= 2) {
896 bool contains_long_groups =
false;
897 uint topo_groups = 0;
901 const uint *adj_edges = (*adj_edges_ptr)->
edges;
902 const uint tot_adj_edges = (*adj_edges_ptr)->edges_len;
904 uint unassigned_edges_len = 0;
905 for (
uint j = 0; j < tot_adj_edges; j++) {
906 NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]];
912 unassigned_edges_len++;
918 unassigned_edges_len,
sizeof(*unassigned_edges),
"unassigned_edges in solidify");
919 for (
uint j = 0, k = 0; j < tot_adj_edges; j++) {
920 NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]];
923 unassigned_edges[k++] = *new_edges;
931 uint edge_groups_len = unassigned_edges_len / 2;
933 edge_groups_len + 1,
sizeof(*edge_groups),
"edge_groups in solidify");
935 uint assigned_edges_len = 0;
937 uint found_edge_index = 0;
938 bool insert_at_start =
false;
939 uint eg_capacity = 5;
943 while (assigned_edges_len < unassigned_edges_len) {
945 insert_at_start =
false;
946 if (eg_index >= 0 && edge_groups[eg_index].edges_len == 0) {
952 while (!edge && j < unassigned_edges_len) {
953 edge = unassigned_edges[j++];
954 if (edge && last_open_edge_track &&
955 (edge->faces[0] != last_open_edge_track || edge->faces[1] !=
NULL)) {
959 if (!edge && last_open_edge_track) {
961 last_open_edge_track =
NULL;
964 while (!edge && j < unassigned_edges_len) {
965 edge = unassigned_edges[j++];
968 else if (!last_open_edge_track && eg_index > 0) {
973 found_edge_index = j - 1;
975 if (!last_open_edge_track && vm[orig_medge[edge->old_edge].
v1] == i) {
976 eg_track_faces[0] = edge->faces[0];
977 eg_track_faces[1] = edge->faces[1];
978 if (edge->faces[1] ==
NULL) {
979 last_open_edge_track = edge->faces[0]->reversed ? edge->faces[0] - 1 :
984 eg_track_faces[0] = edge->faces[1];
985 eg_track_faces[1] = edge->faces[0];
988 else if (eg_index >= 0) {
990 for (found_edge_index = 0; found_edge_index < unassigned_edges_len;
991 found_edge_index++, edge_ptr++) {
994 if (edge->faces[0] == eg_track_faces[1]) {
995 insert_at_start =
false;
996 eg_track_faces[1] = edge->faces[1];
998 if (edge->faces[1] ==
NULL) {
1000 last_open_edge_track = edge->faces[0]->reversed ? edge->faces[0] - 1 :
1005 if (edge->faces[0] == eg_track_faces[0]) {
1006 insert_at_start =
true;
1007 eg_track_faces[0] = edge->faces[1];
1009 if (edge->faces[1] ==
NULL) {
1014 if (edge->faces[1] !=
NULL) {
1015 if (edge->faces[1] == eg_track_faces[1]) {
1016 insert_at_start =
false;
1017 eg_track_faces[1] = edge->faces[0];
1021 if (edge->faces[1] == eg_track_faces[0]) {
1022 insert_at_start =
true;
1023 eg_track_faces[0] = edge->faces[0];
1032 unassigned_edges[found_edge_index] =
NULL;
1033 assigned_edges_len++;
1034 const uint needed_capacity = edge_groups[eg_index].
edges_len + 1;
1035 if (needed_capacity > eg_capacity) {
1036 eg_capacity = needed_capacity + 1;
1038 eg_capacity,
sizeof(*new_eg),
"edge_group realloc in solidify");
1039 if (insert_at_start) {
1041 edge_groups[eg_index].edges,
1042 edge_groups[eg_index].edges_len *
sizeof(*new_eg));
1046 edge_groups[eg_index].edges,
1047 edge_groups[eg_index].edges_len *
sizeof(*new_eg));
1050 edge_groups[eg_index].
edges = new_eg;
1052 else if (insert_at_start) {
1053 memmove(edge_groups[eg_index].edges + 1,
1054 edge_groups[eg_index].edges,
1055 edge_groups[eg_index].edges_len *
sizeof(*edge_groups[eg_index].edges));
1057 edge_groups[eg_index].
edges[insert_at_start ? 0 : edge_groups[eg_index].
edges_len] =
1060 if (edge_groups[eg_index].edges[edge_groups[eg_index].edges_len - 1]->
faces[1] !=
1062 last_open_edge_track =
NULL;
1064 if (edge_groups[eg_index].edges_len > 3) {
1065 contains_long_groups =
true;
1075 eg_capacity,
sizeof(*edges),
"edge_group in solidify");
1081 .is_orig_closed =
true,
1082 .is_even_split =
false,
1084 .is_singularity =
false,
1085 .topo_group = topo_groups,
1086 .co = {0.0f, 0.0f, 0.0f},
1087 .no = {0.0f, 0.0f, 0.0f},
1090 eg_track_faces[0] =
NULL;
1091 eg_track_faces[1] =
NULL;
1108 if (contains_long_groups) {
1110 for (
uint j = 0; j < eg_index; j++) {
1111 const uint edges_len = edge_groups[j + add_index].
edges_len;
1112 if (edges_len > 3) {
1113 bool has_doubles =
false;
1115 edges_len,
sizeof(*doubles),
"doubles in solidify");
1117 for (
uint k = 0; k < edges_len; k++) {
1118 for (
uint l = k + 1;
l < edges_len;
l++) {
1119 if (
g.edges[k]->old_edge ==
g.edges[
l]->old_edge) {
1127 const uint prior_splits = splits;
1128 const uint prior_index = add_index;
1129 int unique_start = -1;
1130 int first_unique_end = -1;
1131 int last_split = -1;
1132 int first_split = -1;
1133 bool first_even_split =
false;
1135 while (real_k < edges_len ||
1136 (
g.is_orig_closed &&
1138 (first_unique_end == -1 ? 0 : first_unique_end) + (
int)edges_len ||
1139 first_split != last_split))) {
1140 const uint k = real_k % edges_len;
1142 if (first_unique_end != -1 && unique_start == -1) {
1143 unique_start = (int)real_k;
1146 else if (first_unique_end == -1) {
1147 first_unique_end = (int)k;
1149 else if (unique_start != -1) {
1150 const uint split = (((
uint)unique_start + real_k + 1) / 2) % edges_len;
1151 const bool is_even_split = (((
uint)unique_start + real_k) & 1);
1152 if (last_split != -1) {
1154 if (prior_splits != splits) {
1155 memmove(edge_groups + j + add_index + 1,
1156 edge_groups + j + add_index,
1157 ((
uint)eg_index - j) *
sizeof(*edge_groups));
1160 if (last_split >
split) {
1161 const uint edges_len_group = (
split + edges_len) - (
uint)last_split;
1163 edges_len_group,
sizeof(*edges),
"edge_group split in solidify");
1165 g.edges + last_split,
1166 (edges_len - (
uint)last_split) *
sizeof(*edges));
1167 memcpy(edges + (edges_len - (
uint)last_split),
1169 split *
sizeof(*edges));
1170 edge_groups[j + add_index] = (
EdgeGroup){
1173 .edges_len = edges_len_group,
1175 .is_orig_closed =
g.is_orig_closed,
1176 .is_even_split = is_even_split,
1177 .split = add_index - prior_index + 1 + (
uint)!
g.is_orig_closed,
1178 .is_singularity =
false,
1179 .topo_group =
g.topo_group,
1180 .co = {0.0f, 0.0f, 0.0f},
1181 .no = {0.0f, 0.0f, 0.0f},
1188 edges_len_group,
sizeof(*edges),
"edge_group split in solidify");
1189 memcpy(edges,
g.edges + last_split, edges_len_group *
sizeof(*edges));
1190 edge_groups[j + add_index] = (
EdgeGroup){
1193 .edges_len = edges_len_group,
1195 .is_orig_closed =
g.is_orig_closed,
1196 .is_even_split = is_even_split,
1197 .split = add_index - prior_index + 1 + (
uint)!
g.is_orig_closed,
1198 .is_singularity =
false,
1199 .topo_group =
g.topo_group,
1200 .co = {0.0f, 0.0f, 0.0f},
1201 .no = {0.0f, 0.0f, 0.0f},
1207 last_split = (int)
split;
1208 if (first_split == -1) {
1209 first_split = (int)
split;
1210 first_even_split = is_even_split;
1216 if (first_split != -1) {
1217 if (!
g.is_orig_closed) {
1218 if (prior_splits != splits) {
1219 memmove(edge_groups + (j + prior_index + 1),
1220 edge_groups + (j + prior_index),
1221 ((
uint)eg_index + add_index - (j + prior_index)) *
1222 sizeof(*edge_groups));
1223 memmove(edge_groups + (j + add_index + 2),
1224 edge_groups + (j + add_index + 1),
1225 ((
uint)eg_index - j) *
sizeof(*edge_groups));
1229 memmove(edge_groups + (j + add_index + 2),
1230 edge_groups + (j + add_index + 1),
1231 ((
uint)eg_index - j - 1) *
sizeof(*edge_groups));
1234 (
uint)first_split,
sizeof(*edges),
"edge_group split in solidify");
1235 memcpy(edges,
g.edges, (
uint)first_split *
sizeof(*edges));
1236 edge_groups[j + prior_index] = (
EdgeGroup){
1239 .edges_len = (
uint)first_split,
1241 .is_orig_closed =
g.is_orig_closed,
1242 .is_even_split = first_even_split,
1244 .is_singularity =
false,
1245 .topo_group =
g.topo_group,
1246 .co = {0.0f, 0.0f, 0.0f},
1247 .no = {0.0f, 0.0f, 0.0f},
1254 "edge_group split in solidify");
1256 g.edges + last_split,
1257 (edges_len - (
uint)last_split) *
sizeof(*edges));
1258 edge_groups[j + add_index] = (
EdgeGroup){
1261 .edges_len = (edges_len - (
uint)last_split),
1263 .is_orig_closed =
g.is_orig_closed,
1264 .is_even_split =
false,
1265 .split = add_index - prior_index + 1,
1266 .is_singularity =
false,
1267 .topo_group =
g.topo_group,
1268 .co = {0.0f, 0.0f, 0.0f},
1269 .no = {0.0f, 0.0f, 0.0f},
1273 if (prior_splits != splits) {
1277 if (first_unique_end != -1 && prior_splits == splits) {
1278 has_singularities =
true;
1288 orig_vert_groups_arr[i] = edge_groups;
1292 bool contains_open_splits =
false;
1293 uint open_edges = 0;
1294 uint contains_splits = 0;
1295 uint last_added = 0;
1296 uint first_added = 0;
1297 bool first_set =
false;
1300 for (
uint j = 0; j <
g->edges_len; j++,
e++) {
1301 const uint flip = (
uint)(vm[orig_medge[(*e)->old_edge].
v2] == i);
1302 BLI_assert(flip || vm[orig_medge[(*e)->old_edge].
v1] == i);
1303 (*e)->link_edge_groups[flip] =
g;
1306 if (do_shell || (do_rim && !
g->is_orig_closed)) {
1308 g->new_vert = new_verts_num++;
1309 if (do_rim || (do_shell &&
g->split)) {
1311 contains_splits += (
g->split != 0);
1312 contains_open_splits |=
g->split && !
g->is_orig_closed;
1316 open_edges += (
uint)(added < last_added);
1319 first_added = added;
1322 if (!(
g + 1)->valid ||
g->topo_group != (
g + 1)->topo_group) {
1323 if (new_verts > 2) {
1325 new_edges_num += new_verts;
1326 open_edges += (
uint)(first_added < last_added);
1327 open_edges -= (
uint)(open_edges && !contains_open_splits);
1328 if (do_shell && do_rim) {
1329 new_loops_num += new_verts * 2;
1331 else if (do_shell) {
1332 new_loops_num += new_verts * 2 - open_edges;
1335 new_loops_num += new_verts * 2 + open_edges - contains_splits;
1338 else if (new_verts == 2) {
1340 new_loops_num += 2u - (
uint)(!(do_rim && do_shell) && contains_open_splits);
1343 contains_open_splits =
false;
1344 contains_splits = 0;
1359 for (
OldVertEdgeRef **p = vert_adj_edges; i < verts_num; i++, p++) {
1375 float *face_weight =
NULL;
1377 if (do_flat_faces) {
1378 face_weight =
MEM_malloc_arrayN(polys_num,
sizeof(*face_weight),
"face_weight in solidify");
1381 for (
uint i = 0; i < polys_num; i++, mp++) {
1382 float scalar_vgroup = 1.0f;
1383 int loopend = mp->loopstart + mp->totloop;
1384 ml = orig_mloop + mp->loopstart;
1385 for (
int j = mp->loopstart; j < loopend; j++, ml++) {
1387 if (defgrp_invert) {
1395 scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv);
1396 face_weight[i] = scalar_vgroup;
1401 gs_ptr = orig_vert_groups_arr;
1402 for (
uint i = 0; i < verts_num; i++,
mv++, gs_ptr++) {
1405 for (
uint j = 0;
g->valid; j++,
g++) {
1406 if (!
g->is_singularity) {
1412 float move_nor[3] = {0, 0, 0};
1413 bool disable_boundary_fix = (smd->nonmanifold_boundary_mode ==
1415 (
g->is_orig_closed ||
g->split));
1416 bool approximate_free_direction =
false;
1423 g->edges_len + 1,
sizeof(*planes_queue),
"planes_queue in solidify");
1424 uint queue_index = 0;
1426 float fallback_nor[3];
1427 float fallback_ofs = 0.0f;
1429 const bool cycle = (
g->is_orig_closed && !
g->split) ||
g->is_even_split;
1430 for (
uint k = 0; k <
g->edges_len; k++, edge_ptr++) {
1431 if (!(k & 1) || (!cycle && k ==
g->edges_len - 1)) {
1433 for (
uint l = 0;
l < 2;
l++) {
1435 if (face && (first_edge ==
NULL ||
1436 (first_edge->
faces[0] != face && first_edge->
faces[1] != face))) {
1437 float ofs = face->
reversed ? ofs_back_clamped : ofs_front_clamped;
1439 if (do_flat_faces) {
1440 ofs *= face_weight[face->
index];
1443 if (!null_faces[face->
index]) {
1446 poly_nors[face->
index],
1448 planes_queue[queue_index++][3] = ofs;
1458 if ((cycle && k == 0) || (!cycle && k + 3 >=
g->edges_len)) {
1463 if (queue_index > 2) {
1468 for (
uint k = 0; k < queue_index; k++) {
1469 for (
uint m = k + 1; m < queue_index; m++) {
1470 float p =
dot_v3v3(planes_queue[k], planes_queue[m]);
1480 swap_v4_v4(planes_queue[min_n0], planes_queue[0]);
1481 swap_v4_v4(planes_queue[min_n1], planes_queue[1]);
1484 swap_v4_v4(planes_queue[min_n0], planes_queue[1]);
1489 float max_p = -1.0f;
1490 for (
uint k = 2; k < queue_index; k++) {
1492 dot_v3v3(planes_queue[1], planes_queue[k]));
1493 if (max_p <= min_p) {
1498 swap_v4_v4(planes_queue[min_n1], planes_queue[2]);
1501 while (queue_index > 2) {
1504 float best_p = -1.0f;
1505 float best_ofs_diff = 0.0f;
1506 for (
uint k = 0; k < queue_index; k++) {
1507 for (
uint m = k + 1; m < queue_index; m++) {
1508 float p =
dot_v3v3(planes_queue[m], planes_queue[k]);
1509 float ofs_diff =
fabsf(planes_queue[m][3] - planes_queue[k][3]);
1510 if (p > best_p + FLT_EPSILON || (p >= best_p && ofs_diff < best_ofs_diff)) {
1512 best_ofs_diff = ofs_diff;
1520 if (best_p < 0.98f) {
1523 add_v3_v3(planes_queue[best_n0], planes_queue[best_n1]);
1525 planes_queue[best_n0][3] = (planes_queue[best_n0][3] + planes_queue[best_n1][3]) *
1528 memmove(planes_queue + best_n1,
1529 planes_queue + best_n1 + 1,
1530 (queue_index - best_n1) *
sizeof(*planes_queue));
1540 const float boundary_fix_threshold = 0.7f;
1545 for (
int k = 0; k < 3; k++) {
1546 for (
int m = 0; m <
size; m++) {
1547 madd_v3_v3fl(mat[k], planes_queue[m], planes_queue[m][k]);
1557 for (
int k = 0; k <
size; k++) {
1562 if (!disable_boundary_fix) {
1564 float greatest_angle_cos = 1.0f;
1565 for (
uint k = 0; k < 2; k++) {
1567 float p =
dot_v3v3(planes_queue[m], planes_queue[k]);
1568 if (p < greatest_angle_cos) {
1569 greatest_angle_cos = p;
1573 if (greatest_angle_cos > boundary_fix_threshold) {
1574 approximate_free_direction =
true;
1577 disable_boundary_fix =
true;
1581 else if (
size > 1) {
1583 const float stop_explosion = 0.999f -
fabsf(smd->offset_fac) * 0.05f;
1584 const float q =
dot_v3v3(planes_queue[0], planes_queue[1]);
1585 float d = 1.0f - q * q;
1588 if (d > FLT_EPSILON * 10 && q < stop_explosion) {
1590 mul_v3_fl(planes_queue[0], (planes_queue[0][3] - planes_queue[1][3] * q) * d);
1591 mul_v3_fl(planes_queue[1], (planes_queue[1][3] - planes_queue[0][3] * q) * d);
1594 d = 1.0f / (
fabsf(q) + 1.0f);
1595 mul_v3_fl(planes_queue[0], planes_queue[0][3] * d);
1596 mul_v3_fl(planes_queue[1], planes_queue[1][3] * d);
1600 d =
dot_v3v3(planes_queue[2], move_nor);
1603 if (
fabsf(d) > 0.02f) {
1609 if (
fabsf(d) > 1.0f - boundary_fix_threshold) {
1610 disable_boundary_fix =
true;
1614 approximate_free_direction =
false;
1616 else if (
size == 1) {
1619 if (
g->edges_len > 2) {
1620 disable_boundary_fix =
true;
1621 approximate_free_direction =
true;
1627 disable_boundary_fix =
true;
1633 float total_angle = 0;
1634 float total_angle_back = 0;
1638 float nor_back[3] = {0, 0, 0};
1639 bool has_back =
false;
1640 bool has_front =
false;
1641 bool cycle = (
g->is_orig_closed && !
g->split) ||
g->is_even_split;
1642 for (
uint k = 0; k <
g->edges_len; k++, edge_ptr++) {
1643 if (!(k & 1) || (!cycle && k ==
g->edges_len - 1)) {
1645 for (
uint l = 0;
l < 2;
l++) {
1647 if (face && (first_edge ==
NULL ||
1648 (first_edge->
faces[0] != face && first_edge->
faces[1] != face))) {
1650 float ofs = face->
reversed ? -ofs_back_clamped : ofs_front_clamped;
1652 if (do_flat_faces) {
1653 ofs *= face_weight[face->
index];
1656 if (smd->nonmanifold_offset_mode ==
1660 MLoop *ml_prev = ml - 1;
1661 for (
int m = 0; m < face->
face->
totloop && vm[ml->v] != i;
1668 orig_mvert_co[vm[ml_next->
v]]);
1670 total_angle_back +=
angle * ofs * ofs;
1673 total_angle +=
angle * ofs * ofs;
1695 if ((cycle && k == 0) || (!cycle && k + 3 >=
g->edges_len)) {
1705 if (
LIKELY(length_sq > FLT_EPSILON)) {
1711 if (
LIKELY(length_sq > FLT_EPSILON)) {
1712 mul_v3_fl(nor_back, total_angle_back / length_sq);
1718 if (has_front && has_back) {
1720 float nor_back_length =
len_v3(nor_back);
1723 q /= nor_length * nor_back_length;
1725 float d = 1.0f - q * q;
1726 if (
LIKELY(d > FLT_EPSILON)) {
1728 if (
LIKELY(nor_length > FLT_EPSILON)) {
1729 mul_v3_fl(
nor, (1 - nor_back_length * q / nor_length) * d);
1731 if (
LIKELY(nor_back_length > FLT_EPSILON)) {
1732 mul_v3_fl(nor_back, (1 - nor_length * q / nor_back_length) * d);
1744 if (has_front && total_angle > FLT_EPSILON) {
1747 if (has_back && total_angle_back > FLT_EPSILON) {
1748 mul_v3_fl(nor_back, 1.0f / total_angle_back);
1750 if (has_front && total_angle > FLT_EPSILON) {
1756 if (!disable_boundary_fix &&
g->edges_len > 2) {
1757 approximate_free_direction =
true;
1760 disable_boundary_fix =
true;
1763 if (approximate_free_direction) {
1768 for (k = 1; k + 1 <
g->edges_len; k++, edge_ptr++) {
1769 MEdge *
e = orig_medge + (*edge_ptr)->old_edge;
1770 sub_v3_v3v3(tmp, orig_mvert_co[vm[
e->v1] == i ?
e->v2 :
e->v1], orig_mvert_co[i]);
1774 disable_boundary_fix =
true;
1781 if (!disable_boundary_fix) {
1783 float constr_nor[3];
1784 MEdge *e0_edge = orig_medge +
g->edges[0]->old_edge;
1785 MEdge *e1_edge = orig_medge +
g->edges[
g->edges_len - 1]->old_edge;
1789 orig_mvert_co[vm[e0_edge->
v1] == i ? e0_edge->
v2 : e0_edge->
v1],
1792 orig_mvert_co[vm[e1_edge->
v1] == i ? e1_edge->
v2 : e1_edge->
v1],
1803 if (
g->edges[0]->faces[0]->reversed) {
1807 copy_v3_v3(f0, poly_nors[
g->edges[0]->faces[0]->index]);
1809 if (
g->edges[
g->edges_len - 1]->faces[0]->reversed) {
1810 negate_v3_v3(f1, poly_nors[
g->edges[
g->edges_len - 1]->faces[0]->index]);
1813 copy_v3_v3(f1, poly_nors[
g->edges[
g->edges_len - 1]->faces[0]->index]);
1824 float d =
dot_v3v3(constr_nor, move_nor);
1826 if (
fabsf(d) > 0.1f) {
1831 float scalar_vgroup = 1;
1833 if (dvert && !do_flat_faces) {
1835 if (defgrp_invert) {
1841 scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv);
1845 if (do_angle_clamp) {
1846 if (
g->edges_len > 2) {
1847 float min_length = 0;
1850 for (
NewEdgeRef **p =
g->edges; k < g->edges_len; k++, p++) {
1851 float length = orig_edge_lengths[(*p)->old_edge];
1852 float e_ang = (*p)->angle;
1853 if (e_ang >
angle) {
1856 if (
length < min_length || k == 0) {
1862 float max_off = min_length * 0.5f / cos_ang;
1863 if (max_off <
offset * 0.5f) {
1864 scalar_vgroup *= max_off /
offset * 2;
1870 float min_length = 0;
1872 for (
NewEdgeRef **p =
g->edges; k < g->edges_len; k++, p++) {
1873 float length = orig_edge_lengths[(*p)->old_edge];
1874 if (
length < min_length || k == 0) {
1878 if (min_length <
offset) {
1879 scalar_vgroup *= min_length /
offset;
1893 if (do_flat_faces) {
1907 uint(*singularity_edges)[2] =
NULL;
1908 uint totsingularity = 0;
1909 if (has_singularities) {
1910 has_singularities =
false;
1912 uint singularity_edges_len = 1;
1914 singularity_edges_len,
sizeof(*singularity_edges),
"singularity_edges in solidify");
1915 for (
NewEdgeRef ***new_edges = orig_edge_data_arr; i < edges_num; i++, new_edges++) {
1916 if (*new_edges && (do_shell || edge_adj_faces_len[i] == 1) && (**new_edges)->old_edge == i) {
1918 if ((*l)->link_edge_groups[0]->is_singularity &&
1919 (*l)->link_edge_groups[1]->is_singularity) {
1920 const uint v1 = (*l)->link_edge_groups[0]->new_vert;
1921 const uint v2 = (*l)->link_edge_groups[1]->new_vert;
1922 bool exists_already =
false;
1924 for (
uint(*p)[2] = singularity_edges; j < totsingularity; p++, j++) {
1925 if (((*p)[0] ==
v1 && (*p)[1] ==
v2) || ((*p)[0] ==
v2 && (*p)[1] ==
v1)) {
1926 exists_already =
true;
1930 if (!exists_already) {
1931 has_singularities =
true;
1932 if (singularity_edges_len <= totsingularity) {
1933 singularity_edges_len = totsingularity + 1;
1935 singularity_edges_len *
1936 sizeof(*singularity_edges),
1937 "singularity_edges in solidify");
1939 singularity_edges[totsingularity][0] =
v1;
1940 singularity_edges[totsingularity][1] =
v2;
1942 if (edge_adj_faces_len[i] == 1 && do_rim) {
1958 (
int)(new_verts_num),
1959 (
int)(new_edges_num),
1961 (
int)(new_loops_num),
1962 (
int)(new_polys_num));
1978 if (shell_defgrp_index != -1 || rim_defgrp_index != -1) {
1981 if (dvert ==
NULL) {
1992 if (vertex_crease) {
2003 gs_ptr = orig_vert_groups_arr;
2004 for (
uint i = 0; i < verts_num; i++, gs_ptr++) {
2008 for (
uint j = 0;
g->valid; j++,
g++) {
2012 mvert[
g->new_vert].flag = orig_mvert[i].flag;
2022 edge_index += totsingularity;
2023 for (
NewEdgeRef ***new_edges = orig_edge_data_arr; i < edges_num; i++, new_edges++) {
2024 if (*new_edges && (do_shell || edge_adj_faces_len[i] == 1) && (**new_edges)->old_edge == i) {
2027 const uint v1 = (*l)->link_edge_groups[0]->new_vert;
2028 const uint v2 = (*l)->link_edge_groups[1]->new_vert;
2030 if (has_singularities && ((*l)->link_edge_groups[0]->is_singularity &&
2031 (*l)->link_edge_groups[1]->is_singularity)) {
2033 for (
uint(*p)[2] = singularity_edges; j < totsingularity; p++, j++) {
2034 if (((*p)[0] ==
v1 && (*p)[1] ==
v2) || ((*p)[0] ==
v2 && (*p)[1] ==
v1)) {
2050 medge[
insert].crease = orig_medge[(*l)->old_edge].crease;
2051 medge[
insert].bweight = orig_medge[(*l)->old_edge].bweight;
2052 if (bevel_convex != 0.0f && (*l)->faces[1] !=
NULL) {
2054 (
int)medge[
insert].bweight + (int)(((*l)->angle >
M_PI + FLT_EPSILON ?
2055 clamp_f(bevel_convex, 0.0f, 1.0f) :
2056 ((*l)->angle <
M_PI - FLT_EPSILON ?
2057 clamp_f(bevel_convex, -1.0f, 0.0f) :
2069 if (singularity_edges) {
2093 gs_ptr = orig_vert_groups_arr;
2094 for (
uint i = 0; i < verts_num; i++, gs_ptr++) {
2101 for (
uint j = 0; j <
g->edges_len; j++,
e++) {
2102 printf(
"%u/%d, ", (*e)->old_edge, (
int)(*e)->new_edge);
2104 printf(
"(tg:%u)(s:%u,c:%d)\n",
g->topo_group,
g->split,
g->is_orig_closed);
2113 gs_ptr = orig_vert_groups_arr;
2115 for (
uint i = 0; i < verts_num; i++, gs_ptr++,
mv++) {
2122 char mv_crease = vertex_crease ? (char)(vertex_crease[i] * 255.0f) : 0;
2125 char last_max_crease = 0;
2126 char first_max_crease = 0;
2128 char last_max_bweight = 0;
2129 char first_max_bweight = 0;
2131 short last_flag = 0;
2132 short first_flag = 0;
2133 for (
uint j = 0;
g->valid;
g++) {
2134 if ((do_rim && !
g->is_orig_closed) || (do_shell &&
g->split)) {
2141 if (
g->edges_len == 2) {
2142 max_crease =
min_cc(orig_medge[
g->edges[0]->old_edge].crease,
2143 orig_medge[
g->edges[1]->old_edge].crease);
2146 for (
uint k = 1; k <
g->edges_len - 1; k++) {
2147 ed = orig_medge +
g->edges[k]->old_edge;
2148 if (ed->crease > max_crease) {
2149 max_crease = ed->crease;
2152 char bweight = medge[
g->edges[k]->new_edge].bweight;
2153 if (bweight > max_bweight) {
2154 max_bweight = bweight;
2161 const char bweight_open_edge =
min_cc(
2162 orig_medge[
g->edges[0]->old_edge].bweight,
2163 orig_medge[
g->edges[
g->edges_len - 1]->old_edge].bweight);
2164 if (bweight_open_edge > 0) {
2165 max_bweight =
min_cc(bweight_open_edge, max_bweight);
2168 if (bevel_convex < 0.0f) {
2174 first_max_crease = max_crease;
2175 first_max_bweight = max_bweight;
2185 if (origindex_edge) {
2188 medge[edge_index].v1 = last_g->
new_vert;
2189 medge[edge_index].v2 =
g->new_vert;
2192 medge[edge_index].crease =
max_cc(mv_crease,
min_cc(last_max_crease, max_crease));
2193 medge[edge_index++].bweight =
max_cc(
mv->bweight,
2194 min_cc(last_max_bweight, max_bweight));
2197 last_max_crease = max_crease;
2198 last_max_bweight = max_bweight;
2202 if (!(
g + 1)->valid ||
g->topo_group != (
g + 1)->topo_group) {
2212 if (origindex_edge) {
2216 medge[edge_index].v1 = last_g->
new_vert;
2217 medge[edge_index].v2 = first_g->
new_vert;
2220 medge[edge_index].crease =
max_cc(mv_crease,
2221 min_cc(last_max_crease, first_max_crease));
2222 medge[edge_index++].bweight =
max_cc(
mv->bweight,
2223 min_cc(last_max_bweight, first_max_bweight));
2228 short most_mat_nr = 0;
2229 uint most_mat_nr_face = 0;
2230 uint most_mat_nr_count = 0;
2231 for (
short l = 0;
l < mat_nrs;
l++) {
2236 if ((do_rim && !g3->is_orig_closed) || (do_shell && g3->split)) {
2238 if (g3->edges[0]->faces[0]->face->mat_nr ==
l) {
2239 face = g3->edges[0]->faces[0]->
index;
2242 NewEdgeRef *le = g3->edges[g3->edges_len - 1];
2254 if (
count > most_mat_nr_count) {
2256 most_mat_nr_face = face;
2257 most_mat_nr_count =
count;
2261 &
mesh->
pdata, &
result->pdata, (
int)most_mat_nr_face, (
int)poly_index, 1);
2262 if (origindex_poly) {
2265 mpoly[poly_index].loopstart = (int)loop_index;
2266 mpoly[poly_index].totloop = (int)j;
2267 mpoly[poly_index].mat_nr = most_mat_nr +
2268 (
g->is_orig_closed || !do_rim ? 0 : mat_ofs_rim);
2269 CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max);
2270 mpoly[poly_index].flag = orig_mpoly[most_mat_nr_face].flag;
2273 for (
uint k = 0; g2->
valid && k < j; g2++) {
2277 for (
int l = 0;
l < face->
totloop;
l++, ml++) {
2278 if (vm[ml->v] == i) {
2288 for (
uint k = 0; k < j; k++) {
2290 mloop[loop_index].v = medge[edge_index - j + k].v1;
2291 mloop[loop_index++].e = edge_index - j + k;
2295 for (
uint k = 1; k <= j; k++) {
2298 mloop[loop_index].v = medge[edge_index - k].v2;
2299 mloop[loop_index++].e = edge_index - k;
2308 last_max_crease = 0;
2309 first_max_crease = 0;
2310 last_max_bweight = 0;
2311 first_max_bweight = 0;
2322 for (
uint i = 0; i < edges_num; i++) {
2323 if (edge_adj_faces_len[i] == 1 && orig_edge_data_arr[i] &&
2324 (*orig_edge_data_arr[i])->old_edge == i) {
2325 NewEdgeRef **new_edges = orig_edge_data_arr[i];
2333 if (v1_singularity && v2_singularity) {
2337 MPoly *face = (*new_edges)->faces[0]->face;
2339 &
mesh->
pdata, &
result->pdata, (
int)(*new_edges)->faces[0]->index, (
int)poly_index, 1);
2340 mpoly[poly_index].loopstart = (int)loop_index;
2341 mpoly[poly_index].totloop = 4 - (int)(v1_singularity || v2_singularity);
2342 mpoly[poly_index].mat_nr = face->
mat_nr + mat_ofs_rim;
2343 CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max);
2344 mpoly[poly_index].flag = face->
flag;
2350 const uint old_v1 = vm[orig_medge[edge1->
old_edge].v1];
2351 const uint old_v2 = vm[orig_medge[edge1->
old_edge].v2];
2353 if (vm[ml->v] == old_v1) {
2356 else if (vm[ml->v] == old_v2) {
2361 MEdge *open_face_edge;
2362 uint open_face_edge_index;
2364 if (rim_defgrp_index != -1) {
2369 mloop[loop_index].v = medge[edge1->
new_edge].v1;
2370 mloop[loop_index++].e = edge1->
new_edge;
2372 if (!v2_singularity) {
2374 if (rim_defgrp_index != -1) {
2379 mloop[loop_index].v = medge[edge1->
new_edge].v2;
2380 open_face_edge = medge + open_face_edge_index;
2381 if (
ELEM(medge[edge2->
new_edge].v2, open_face_edge->
v1, open_face_edge->
v2)) {
2382 mloop[loop_index++].e = open_face_edge_index;
2389 if (rim_defgrp_index != -1) {
2394 mloop[loop_index].v = medge[edge2->
new_edge].v2;
2395 mloop[loop_index++].e = edge2->
new_edge;
2397 if (!v1_singularity) {
2399 if (rim_defgrp_index != -1) {
2404 mloop[loop_index].v = medge[edge2->
new_edge].v1;
2405 open_face_edge = medge + open_face_edge_index;
2406 if (
ELEM(medge[edge1->
new_edge].v1, open_face_edge->
v1, open_face_edge->
v2)) {
2407 mloop[loop_index++].e = open_face_edge_index;
2415 if (!v1_singularity) {
2417 if (rim_defgrp_index != -1) {
2422 mloop[loop_index].v = medge[edge1->
new_edge].v1;
2423 open_face_edge = medge + open_face_edge_index;
2424 if (
ELEM(medge[edge2->
new_edge].v1, open_face_edge->
v1, open_face_edge->
v2)) {
2425 mloop[loop_index++].e = open_face_edge_index;
2432 if (rim_defgrp_index != -1) {
2437 mloop[loop_index].v = medge[edge2->
new_edge].v1;
2438 mloop[loop_index++].e = edge2->
new_edge;
2440 if (!v2_singularity) {
2442 if (rim_defgrp_index != -1) {
2447 mloop[loop_index].v = medge[edge2->
new_edge].v2;
2448 open_face_edge = medge + open_face_edge_index;
2449 if (
ELEM(medge[edge1->
new_edge].v2, open_face_edge->
v1, open_face_edge->
v2)) {
2450 mloop[loop_index++].e = open_face_edge_index;
2457 if (rim_defgrp_index != -1) {
2462 mloop[loop_index].v = medge[edge1->
new_edge].v2;
2463 mloop[loop_index++].e = edge1->
new_edge;
2473 largest_ngon * 2,
sizeof(*face_loops),
"face_loops in solidify");
2475 largest_ngon * 2,
sizeof(*face_verts),
"face_verts in solidify");
2477 largest_ngon * 2,
sizeof(*face_edges),
"face_edges in solidify");
2478 for (
uint i = 0; i < polys_num * 2; i++, fr++) {
2481 uint valid_edges = 0;
2483 while (totloop > 0 && (!fr->
link_edges[totloop - 1] ||
2490 vm[orig_mloop[loopstart + (totloop - 1)].v]);
2491 for (
uint j = 0; j < totloop; j++) {
2496 vm[orig_mloop[loopstart + j].v]);
2498 vm[orig_medge[
new_edge->old_edge].v1] == vm[orig_mloop[loopstart + j].v]);
2500 const uint new_v1 =
new_edge->link_edge_groups[flip]->new_vert;
2502 const uint new_v2 =
new_edge->link_edge_groups[1 - flip]->new_vert;
2503 if (k == 0 || face_verts[k - 1] != new_v1) {
2504 face_loops[k] = loopstart + j;
2509 face_edges[k] =
new_edge->link_edge_groups[flip]->open_face_edge;
2511 BLI_assert(k == 0 || medge[face_edges[k]].
v2 == face_verts[k - 1] ||
2512 medge[face_edges[k]].
v1 == face_verts[k - 1]);
2514 medge[face_edges[k]].
v2 == new_v1 || medge[face_edges[k]].
v1 == new_v1);
2515 face_verts[k++] = new_v1;
2518 prior_flip = 1 - flip;
2519 if (j < totloop - 1 || face_verts[0] != new_v2) {
2520 face_loops[k] = loopstart + (j + 1) % totloop;
2521 face_edges[k] =
new_edge->new_edge;
2522 face_verts[k++] = new_v2;
2525 face_edges[0] =
new_edge->new_edge;
2529 if (k > 2 && valid_edges > 2) {
2531 mpoly[poly_index].loopstart = (int)loop_index;
2532 mpoly[poly_index].totloop = (int)k;
2533 mpoly[poly_index].mat_nr = fr->
face->
mat_nr + (fr->
reversed != do_flip ? mat_ofs : 0);
2534 CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max);
2535 mpoly[poly_index].flag = fr->
face->
flag;
2537 for (
int l = (
int)k - 1;
l >= 0;
l--) {
2538 if (shell_defgrp_index != -1) {
2544 mloop[loop_index].v = face_verts[
l];
2545 mloop[loop_index++].e = face_edges[
l];
2550 for (
uint next_l = 0; next_l < k; next_l++) {
2553 mloop[loop_index].v = face_verts[
l];
2554 mloop[loop_index++].e = face_edges[next_l];
2566 if (edge_index != new_edges_num) {
2569 "Internal Error: edges array wrong size: %u instead of %u",
2573 if (poly_index != new_polys_num) {
2576 "Internal Error: polys array wrong size: %u instead of %u",
2580 if (loop_index != new_loops_num) {
2583 "Internal Error: loops array wrong size: %u instead of %u",
2596 for (
EdgeGroup **p = orig_vert_groups_arr; i < verts_num; i++, p++) {
2606 for (
NewEdgeRef ***p = orig_edge_data_arr + (edges_num - 1); i > 0; i--, p--) {
2607 if (*p && (**p)->old_edge == i - 1) {
2617 for (
NewFaceRef *p = face_sides_arr; i < polys_num * 2; i++, p++) {
2624 #undef MOD_SOLIDIFY_EMPTY_TAG
typedef float(TangentPoint)[2]
void CustomData_free_layers(struct CustomData *data, int type, int totelem)
void * CustomData_get_layer(const struct CustomData *data, int type)
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
void * CustomData_duplicate_referenced_layer(struct CustomData *data, int type, int totelem)
void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
const float(* BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3]
struct Mesh * BKE_mesh_new_nomain_from_template(const struct Mesh *me_src, int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
MINLINE float max_ff(float a, float b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE float min_ff(float a, float b)
MINLINE char min_cc(char a, char b)
MINLINE int clamp_i(int value, int min, int max)
MINLINE char max_cc(char a, char b)
void zero_m3(float m[3][3])
bool invert_m3(float R[3][3])
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
MINLINE void swap_v4_v4(float a[4], float b[4])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
@ MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_FLAT
@ MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_ROUND
@ MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_NONE
@ MOD_SOLIDIFY_OFFSET_ANGLE_CLAMP
@ MOD_SOLIDIFY_NONMANIFOLD_FLAT_FACES
@ MOD_SOLIDIFY_VGROUP_INV
@ MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_EVEN
@ MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS
Object is a sort of wrapper for general info.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
struct OldEdgeFaceRef OldEdgeFaceRef
Mesh * MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
struct OldVertEdgeRef OldVertEdgeRef
static int comp_float_int_pair(const void *a, const void *b)
static float angle_signed_on_axis_normalized_v3v3_v3(const float n[3], const float ref_n[3], const float axis[3])
struct FaceKeyPair FaceKeyPair
static float clamp_nonzero(const float value, const float epsilon)
#define MOD_SOLIDIFY_EMPTY_TAG
struct NewEdgeRef NewEdgeRef
struct NewFaceRef NewFaceRef
struct EdgeGroup EdgeGroup
static float project_v3_v3(float r[3], const float a[3])
void MOD_get_vgroup(Object *ob, struct Mesh *mesh, const char *name, MDeformVert **dvert, int *defgrp_index)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
void(* MEM_freeN)(void *vmemh)
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
void *(* MEM_reallocN_id)(void *vmemh, size_t len, const char *str)
void *(* MEM_mallocN)(size_t len, const char *str)
Insertion insert(const float3 &point_prev, const float3 &handle_prev, const float3 &handle_next, const float3 &point_next, float parameter)
void split(const std::string &s, const char delim, std::vector< std::string > &tokens)
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
T length(const vec_base< T, Size > &a)
static MEdge new_edge(const int v1, const int v2)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
struct EdgeGroup * link_edge_groups[2]
struct NewEdgeRef ** link_edges
char nonmanifold_offset_mode
char shell_defgrp_name[64]