40 # pragma GCC diagnostic error "-Wsign-conversion"
133 return (
int)(
x->angle >
y->angle) - (
int)(
x->angle <
y->angle);
144 MVert *
mv, *mvert, *orig_mvert;
145 MEdge *ed, *medge, *orig_medge;
146 MLoop *ml, *mloop, *orig_mloop;
147 MPoly *mp, *mpoly, *orig_mpoly;
153 if (numPolys == 0 && numVerts != 0) {
159 const short mat_nr_max = mat_nrs - 1;
160 const short mat_ofs = mat_nrs > 1 ? smd->
mat_ofs : 0;
161 const short mat_ofs_rim = mat_nrs > 1 ? smd->
mat_ofs_rim : 0;
167 const float ofs_front_clamped =
max_ff(1e-5f,
fabsf(smd->
offset > 0 ? ofs_front : ofs_back));
168 const float ofs_back_clamped =
max_ff(1e-5f,
fabsf(smd->
offset > 0 ? ofs_back : ofs_front));
197 uint numNewVerts = 0;
198 uint numNewEdges = 0;
199 uint numNewLoops = 0;
200 uint numNewPolys = 0;
202 #define MOD_SOLIDIFY_EMPTY_TAG ((uint)-1)
217 numPolys * 2,
sizeof(*face_sides_arr),
"face_sides_arr in solidify");
222 uint largest_ngon = 3;
226 for (
uint i = 0; i < numPolys; i++, mp++) {
233 poly_nors[i][2] = 1.0f;
236 poly_nors[i][1] = 1.0f;
239 null_faces[i] =
true;
244 (
uint)mp->
totloop,
sizeof(*link_edges),
"NewFaceRef::link_edges in solidify");
246 .
face = mp, .index = i, .reversed =
false, .link_edges = link_edges};
248 (
uint)mp->
totloop,
sizeof(*link_edges),
"NewFaceRef::link_edges in solidify");
250 .
face = mp, .index = i, .reversed =
true, .link_edges = link_edges};
251 if (mp->
totloop > largest_ngon) {
263 numEdges,
sizeof(*edge_adj_faces_len),
"edge_adj_faces_len in solidify");
267 for (
uint i = 0; i < numPolys; i++, mp++) {
270 edge_adj_faces_len[ml->
e]++;
277 numEdges,
sizeof(*orig_edge_data_arr),
"orig_edge_data_arr in solidify");
280 numEdges,
sizeof(*orig_edge_lengths),
"orig_edge_lengths in solidify");
283 numVerts,
sizeof(*orig_vert_groups_arr),
"orig_vert_groups_arr in solidify");
286 for (
uint i = 0; i < numVerts; i++) {
294 bool has_singularities =
false;
298 numVerts,
sizeof(*vert_adj_edges),
"vert_adj_edges in solidify");
301 numVerts,
sizeof(*orig_mvert_co),
"orig_mvert_co in solidify");
303 for (
uint i = 0; i < numVerts; i++) {
304 orig_mvert_co[i][0] = orig_mvert[i].
co[0];
305 orig_mvert_co[i][1] = orig_mvert[i].
co[1];
306 orig_mvert_co[i][2] = orig_mvert[i].
co[2];
312 numEdges,
sizeof(*edge_adj_faces),
"edge_adj_faces in solidify");
317 for (
uint i = 0; i < numPolys; i++, mp++) {
320 const uint edge = ml->
e;
321 const bool reversed = orig_medge[edge].
v2 != ml->
v;
323 if (old_face_edge_ref ==
NULL) {
324 const uint len = edge_adj_faces_len[edge];
327 len,
sizeof(*adj_faces),
"OldEdgeFaceRef::faces in solidify");
329 len,
sizeof(*adj_faces_reversed),
"OldEdgeFaceRef::reversed in solidify");
331 for (
uint k = 1; k <
len; k++) {
334 adj_faces_reversed[0] = reversed;
337 edge_adj_faces[edge] = ref;
342 old_face_edge_ref->
faces[k] = i;
352 float edgedir[3] = {0, 0, 0};
354 numVerts,
sizeof(*vert_adj_edges_len),
"vert_adj_edges_len in solidify");
359 numPolys,
sizeof(*face_singularity),
"face_sides_arr in solidify");
363 numVerts,
sizeof(*combined_verts),
"combined_verts in solidify");
366 for (
uint i = 0; i < numEdges; i++, ed++) {
367 if (edge_adj_faces_len[i] > 0) {
380 if (orig_edge_lengths[i] <= merge_tolerance_sqr) {
384 bool can_merge =
true;
385 for (
uint k = 0; k < numEdges && can_merge; k++) {
386 if (k != i && edge_adj_faces_len[k] > 0 &&
388 for (
uint j = 0; j < edge_adj_faces[k]->
faces_len && can_merge; j++) {
389 mp = orig_mpoly + edge_adj_faces[k]->
faces[j];
398 can_merge = can_merge && changes <= 2;
404 orig_edge_lengths[i] = 0.0f;
405 vert_adj_edges_len[
v1]++;
406 vert_adj_edges_len[
v2]++;
411 (combined_verts[
v2] + 1) /
412 (
float)(combined_verts[
v1] + combined_verts[
v2] + 2));
414 for (
uint j =
v2; j < numVerts; j++) {
419 vert_adj_edges_len[
v1] += vert_adj_edges_len[
v2];
420 vert_adj_edges_len[
v2] = 0;
421 combined_verts[
v1] += combined_verts[
v2] + 1;
424 numNewLoops -= edge_adj_faces_len[i] * 2;
427 edge_adj_faces_len[i] = 0;
429 MEM_freeN(edge_adj_faces[i]->faces_reversed);
431 edge_adj_faces[i] =
NULL;
434 orig_edge_lengths[i] =
sqrtf(orig_edge_lengths[i]);
435 vert_adj_edges_len[
v1]++;
436 vert_adj_edges_len[
v2]++;
442 for (
uint i = 0; i < numEdges; i++, ed++) {
445 if (
v1 ==
v2 && edge_adj_faces[i]) {
448 const uint face = edge_adj_faces[i]->
faces[j];
449 if (!face_singularity[face]) {
450 bool is_singularity =
true;
451 for (
uint k = 0; k < orig_mpoly[face].
totloop; k++) {
452 if (vm[orig_mloop[((
uint)orig_mpoly[face].loopstart) + k].
v] !=
v1) {
453 is_singularity =
false;
457 if (is_singularity) {
458 face_singularity[face] =
true;
468 numNewLoops -= edge_adj_faces_len[i] * 2;
471 edge_adj_faces_len[i] = 0;
473 MEM_freeN(edge_adj_faces[i]->faces_reversed);
475 edge_adj_faces[i] =
NULL;
486 for (
uint i = 0; i < numEdges; i++, ed++) {
487 if (edge_adj_faces_len[i] > 0) {
488 const uint vs[2] = {vm[ed->
v1], vm[ed->
v2]};
489 uint invalid_edge_index = 0;
490 bool invalid_edge_reversed =
false;
491 for (
uint j = 0; j < 2; j++) {
492 const uint vert = vs[j];
493 const uint len = vert_adj_edges_len[vert];
496 if (old_edge_vert_ref ==
NULL) {
498 len,
sizeof(*adj_edges),
"OldVertEdgeRef::edges in solidify");
500 for (
uint k = 1; k <
len; k++) {
505 vert_adj_edges[vert] = ref;
508 const uint *f = old_edge_vert_ref->
edges;
510 const uint edge = old_edge_vert_ref->
edges[k];
512 old_edge_vert_ref->
edges[k] = i;
516 if (vm[orig_medge[edge].
v1] == vs[1 - j]) {
517 invalid_edge_index = edge + 1;
518 invalid_edge_reversed = (j == 0);
521 if (vm[orig_medge[edge].
v2] == vs[1 - j]) {
522 invalid_edge_index = edge + 1;
523 invalid_edge_reversed = (j == 1);
527 if (invalid_edge_index) {
538 if (invalid_edge_index) {
539 const uint tmp = invalid_edge_index - 1;
540 invalid_edge_index = i;
543 OldEdgeFaceRef *invalid_adj_faces = edge_adj_faces[invalid_edge_index];
547 if (i_adj_faces->
faces[k] == invalid_adj_faces->
faces[
l] &&
557 numNewPolys -= 2 * j;
558 numNewLoops -= 4 * j;
562 len,
sizeof(*adj_faces),
"OldEdgeFaceRef::faces in solidify");
564 len,
sizeof(*adj_faces_loops_reversed),
"OldEdgeFaceRef::reversed in solidify");
569 adj_faces[j] = i_adj_faces->
faces[k];
575 adj_faces[j] = invalid_adj_faces->
faces[k];
576 adj_faces_loops_reversed[j++] = (invalid_edge_reversed !=
581 edge_adj_faces_len[invalid_edge_index] = 0;
582 edge_adj_faces_len[i] =
len;
586 i_adj_faces->
faces = adj_faces;
588 i_adj_faces->
used += invalid_adj_faces->
used;
592 edge_adj_faces[invalid_edge_index] = i_adj_faces;
594 i = invalid_edge_index;
607 for (
uint i = 0; i < numEdges; i++, ed++) {
608 if (edge_adj_faces_len[i] > 0) {
615 for (
uint j = 0; j < adj_len; j++) {
617 const int j_loopstart = orig_mpoly[face].
loopstart;
618 const int totloop = orig_mpoly[face].
totloop;
619 const uint j_first_v = vm[orig_mloop[j_loopstart].
v];
620 for (
uint k = j + 1; k < adj_len; k++) {
621 if (orig_mpoly[adj_faces->
faces[k]].
totloop != totloop) {
625 const int k_loopstart = orig_mpoly[adj_faces->
faces[k]].
loopstart;
627 ml = orig_mloop + k_loopstart;
628 for (
l = 0;
l < totloop && vm[ml->
v] != j_first_v;
l++, ml++) {
636 const int count_dir = reversed ? -1 : 1;
637 bool has_diff =
false;
638 ml = orig_mloop + j_loopstart;
639 for (
int m = 0, n =
l + totloop; m < totloop && !has_diff;
640 m++, n += count_dir, ml++) {
641 has_diff = has_diff || vm[ml->
v] != vm[orig_mloop[k_loopstart + n % totloop].v];
645 ml = orig_mloop + j_loopstart;
647 for (
uint m = 0; m < totloop; m++, ml++) {
652 uint *e_adj_faces_faces = e_adj_faces->
faces;
655 if (e_adj_faces_faces != adj_faces->
faces) {
658 face_index < faces_len && e_adj_faces_faces[face_index] != face;
663 if (face_index == faces_len) {
671 memmove(e_adj_faces_faces + face_index,
672 e_adj_faces_faces + face_index + 1,
673 (faces_len - face_index - 1) *
sizeof(*e_adj_faces_faces));
674 memmove(e_adj_faces_reversed + face_index,
675 e_adj_faces_reversed + face_index + 1,
676 (faces_len - face_index - 1) *
sizeof(*e_adj_faces_reversed));
678 if (edge_adj_faces_len[
e] > 0) {
679 edge_adj_faces_len[
e]--;
680 if (edge_adj_faces_len[
e] == 0) {
682 edge_adj_faces[
e] =
NULL;
685 else if (e_adj_faces->
used > 1) {
686 for (
uint n = 0; n < numEdges; n++) {
687 if (edge_adj_faces[n] == e_adj_faces && edge_adj_faces_len[n] > 0) {
688 edge_adj_faces_len[n]--;
689 if (edge_adj_faces_len[n] == 0) {
690 edge_adj_faces[n]->
used--;
691 edge_adj_faces[n] =
NULL;
702 numNewLoops -= 2 * (
uint)del_loops;
716 for (
uint i = 0; i < numEdges; i++, ed++) {
719 if (edge_adj_faces_len[i] > 0) {
720 if (
LIKELY(orig_edge_lengths[i] > FLT_EPSILON)) {
722 mul_v3_fl(edgedir, 1.0f / orig_edge_lengths[i]);
734 for (
int j = 0; j < link1->
edges_len; j++) {
736 if (edge_adj_faces_len[
e] > 0 &&
e != i) {
738 vm[vm[orig_medge[
e].
v1] ==
v1 ? orig_medge[
e].v2 : orig_medge[
e].v1];
746 for (
int j = 0; j < link2->
edges_len; j++) {
748 if (edge_adj_faces_len[
e] > 0 &&
e != i) {
750 vm[vm[orig_medge[
e].
v1] ==
v2 ? orig_medge[
e].v2 : orig_medge[
e].v1];
766 const uint *adj_faces_faces = adj_faces->
faces;
768 uint new_edges_len = 0;
770 adj_len,
sizeof(*sorted_faces),
"sorted_faces in solidify");
772 new_edges_len = adj_len;
774 float ref_nor[3] = {0, 0, 0};
776 for (
uint j = 0; j < adj_len; j++) {
777 const bool reverse = adj_faces_reversed[j];
778 const uint face_i = adj_faces_faces[j];
786 if (orig_mpoly[face_i].totloop > 3) {
796 sorted_faces[j].
angle = 0.0f;
800 sorted_faces[j].
angle = 0.0f;
806 sorted_faces[j].
face = face_sides_arr + adj_faces_faces[j] * 2 +
807 (adj_faces_reversed[j] ? 1 : 0);
815 sorted_faces[0].
face = face_sides_arr + adj_faces_faces[0] * 2 +
816 (adj_faces_reversed[0] ? 1 : 0);
826 new_edges_len + 1,
sizeof(*new_edges),
"new_edges in solidify");
827 new_edges[new_edges_len] =
NULL;
829 for (
uint j = 0; j < new_edges_len; j++) {
832 const uint next_j = j + 1 == adj_len ? 0 : j + 1;
835 sorted_faces[next_j].
face + 1;
843 sorted_faces[0].
face + j;
849 if (do_shell || (adj_len == 1 && do_rim)) {
850 edge_data_edge_index = 0;
856 .new_edge = edge_data_edge_index};
857 new_edges[j] = edge_data;
858 for (
uint k = 0; k < 2; k++) {
860 ml = orig_mloop +
faces[k]->face->loopstart;
861 for (
int l = 0;
l <
faces[k]->face->totloop;
l++, ml++) {
862 if (edge_adj_faces[ml->
e] == edge_adj_faces[i]) {
863 if (ml->
e != i && orig_edge_data_arr[ml->
e] ==
NULL) {
864 orig_edge_data_arr[ml->
e] = new_edges;
866 faces[k]->link_edges[
l] = edge_data;
874 orig_edge_data_arr[i] = new_edges;
875 if (do_shell || (adj_len == 1 && do_rim)) {
876 numNewEdges += new_edges_len;
882 for (
uint i = 0; i < numEdges; i++) {
883 if (edge_adj_faces[i]) {
884 if (edge_adj_faces[i]->used > 1) {
885 edge_adj_faces[i]->
used--;
889 MEM_freeN(edge_adj_faces[i]->faces_reversed);
900 for (
uint i = 0; i < numVerts; i++, adj_edges_ptr++) {
901 if (*adj_edges_ptr !=
NULL && (*adj_edges_ptr)->edges_len >= 2) {
905 bool contains_long_groups =
false;
906 uint topo_groups = 0;
910 const uint *adj_edges = (*adj_edges_ptr)->
edges;
911 const uint tot_adj_edges = (*adj_edges_ptr)->edges_len;
913 uint unassigned_edges_len = 0;
914 for (
uint j = 0; j < tot_adj_edges; j++) {
915 NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]];
921 unassigned_edges_len++;
927 unassigned_edges_len,
sizeof(*unassigned_edges),
"unassigned_edges in solidify");
928 for (
uint j = 0, k = 0; j < tot_adj_edges; j++) {
929 NewEdgeRef **new_edges = orig_edge_data_arr[adj_edges[j]];
932 unassigned_edges[k++] = *new_edges;
940 uint edge_groups_len = unassigned_edges_len / 2;
942 edge_groups_len + 1,
sizeof(*edge_groups),
"edge_groups in solidify");
944 uint assigned_edges_len = 0;
946 uint found_edge_index = 0;
947 bool insert_at_start =
false;
948 uint eg_capacity = 5;
952 while (assigned_edges_len < unassigned_edges_len) {
954 insert_at_start =
false;
955 if (eg_index >= 0 && edge_groups[eg_index].edges_len == 0) {
961 while (!edge && j < unassigned_edges_len) {
962 edge = unassigned_edges[j++];
963 if (edge && last_open_edge_track &&
964 (edge->
faces[0] != last_open_edge_track || edge->
faces[1] !=
NULL)) {
968 if (!edge && last_open_edge_track) {
970 last_open_edge_track =
NULL;
973 while (!edge && j < unassigned_edges_len) {
974 edge = unassigned_edges[j++];
977 else if (!last_open_edge_track && eg_index > 0) {
982 found_edge_index = j - 1;
984 if (!last_open_edge_track && vm[orig_medge[edge->
old_edge].
v1] == i) {
985 eg_track_faces[0] = edge->
faces[0];
986 eg_track_faces[1] = edge->
faces[1];
993 eg_track_faces[0] = edge->
faces[1];
994 eg_track_faces[1] = edge->
faces[0];
997 else if (eg_index >= 0) {
999 for (found_edge_index = 0; found_edge_index < unassigned_edges_len;
1000 found_edge_index++, edge_ptr++) {
1003 if (edge->
faces[0] == eg_track_faces[1]) {
1004 insert_at_start =
false;
1005 eg_track_faces[1] = edge->
faces[1];
1014 if (edge->
faces[0] == eg_track_faces[0]) {
1015 insert_at_start =
true;
1016 eg_track_faces[0] = edge->
faces[1];
1024 if (edge->
faces[1] == eg_track_faces[1]) {
1025 insert_at_start =
false;
1026 eg_track_faces[1] = edge->
faces[0];
1030 if (edge->
faces[1] == eg_track_faces[0]) {
1031 insert_at_start =
true;
1032 eg_track_faces[0] = edge->
faces[0];
1041 unassigned_edges[found_edge_index] =
NULL;
1042 assigned_edges_len++;
1043 const uint needed_capacity = edge_groups[eg_index].
edges_len + 1;
1044 if (needed_capacity > eg_capacity) {
1045 eg_capacity = needed_capacity + 1;
1047 eg_capacity,
sizeof(*new_eg),
"edge_group realloc in solidify");
1048 if (insert_at_start) {
1050 edge_groups[eg_index].edges,
1051 edge_groups[eg_index].edges_len *
sizeof(*new_eg));
1055 edge_groups[eg_index].edges,
1056 edge_groups[eg_index].edges_len *
sizeof(*new_eg));
1059 edge_groups[eg_index].
edges = new_eg;
1061 else if (insert_at_start) {
1062 memmove(edge_groups[eg_index].edges + 1,
1063 edge_groups[eg_index].edges,
1064 edge_groups[eg_index].edges_len *
sizeof(*edge_groups[eg_index].edges));
1066 edge_groups[eg_index].
edges[insert_at_start ? 0 : edge_groups[eg_index].
edges_len] =
1069 if (edge_groups[eg_index].edges[edge_groups[eg_index].edges_len - 1]->
faces[1] !=
1071 last_open_edge_track =
NULL;
1073 if (edge_groups[eg_index].edges_len > 3) {
1074 contains_long_groups =
true;
1084 eg_capacity,
sizeof(*edges),
"edge_group in solidify");
1090 .is_orig_closed =
true,
1091 .is_even_split =
false,
1093 .is_singularity =
false,
1094 .topo_group = topo_groups,
1095 .co = {0.0f, 0.0f, 0.0f},
1096 .no = {0.0f, 0.0f, 0.0f},
1099 eg_track_faces[0] =
NULL;
1100 eg_track_faces[1] =
NULL;
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 edges_len,
sizeof(*doubles),
"doubles in solidify");
1125 EdgeGroup g = edge_groups[j + add_index];
1126 for (
uint k = 0; k < edges_len; k++) {
1127 for (
uint l = k + 1;
l < edges_len;
l++) {
1136 const uint prior_splits = splits;
1137 const uint prior_index = add_index;
1138 int unique_start = -1;
1139 int first_unique_end = -1;
1140 int last_split = -1;
1141 int first_split = -1;
1142 bool first_even_split =
false;
1144 while (real_k < edges_len ||
1147 (first_unique_end == -1 ? 0 : first_unique_end) + (
int)edges_len ||
1148 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) {
1172 size,
sizeof(*edges),
"edge_group split in solidify");
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));
1179 edge_groups[j + add_index] = (
EdgeGroup){
1185 .is_even_split = is_even_split,
1187 .is_singularity =
false,
1189 .co = {0.0f, 0.0f, 0.0f},
1190 .no = {0.0f, 0.0f, 0.0f},
1197 size,
sizeof(*edges),
"edge_group split in solidify");
1198 memcpy(edges, g.
edges + last_split,
size *
sizeof(*edges));
1199 edge_groups[j + add_index] = (
EdgeGroup){
1205 .is_even_split = is_even_split,
1207 .is_singularity =
false,
1209 .co = {0.0f, 0.0f, 0.0f},
1210 .no = {0.0f, 0.0f, 0.0f},
1216 last_split = (int)
split;
1217 if (first_split == -1) {
1218 first_split = (int)
split;
1219 first_even_split = is_even_split;
1225 if (first_split != -1) {
1226 if (!g.is_orig_closed) {
1227 if (prior_splits != splits) {
1228 memmove(edge_groups + (j + prior_index + 1),
1229 edge_groups + (j + prior_index),
1230 ((
uint)eg_index + add_index - (j + prior_index)) *
1231 sizeof(*edge_groups));
1232 memmove(edge_groups + (j + add_index + 2),
1233 edge_groups + (j + add_index + 1),
1234 ((
uint)eg_index - j) *
sizeof(*edge_groups));
1238 memmove(edge_groups + (j + add_index + 2),
1239 edge_groups + (j + add_index + 1),
1240 ((
uint)eg_index - j - 1) *
sizeof(*edge_groups));
1243 (
uint)first_split,
sizeof(*edges),
"edge_group split in solidify");
1244 memcpy(edges, g.edges, (
uint)first_split *
sizeof(*edges));
1245 edge_groups[j + prior_index] = (
EdgeGroup){
1248 .edges_len = (
uint)first_split,
1250 .is_orig_closed = g.is_orig_closed,
1251 .is_even_split = first_even_split,
1253 .is_singularity =
false,
1254 .topo_group = g.topo_group,
1255 .co = {0.0f, 0.0f, 0.0f},
1256 .no = {0.0f, 0.0f, 0.0f},
1263 "edge_group split in solidify");
1265 g.edges + last_split,
1266 (edges_len - (
uint)last_split) *
sizeof(*edges));
1267 edge_groups[j + add_index] = (
EdgeGroup){
1270 .edges_len = (edges_len - (
uint)last_split),
1272 .is_orig_closed = g.is_orig_closed,
1273 .is_even_split =
false,
1274 .split = add_index - prior_index + 1,
1275 .is_singularity =
false,
1276 .topo_group = g.topo_group,
1277 .co = {0.0f, 0.0f, 0.0f},
1278 .no = {0.0f, 0.0f, 0.0f},
1282 if (prior_splits != splits) {
1286 if (first_unique_end != -1 && prior_splits == splits) {
1287 has_singularities =
true;
1297 orig_vert_groups_arr[i] = edge_groups;
1301 bool contains_open_splits =
false;
1302 uint open_edges = 0;
1303 uint contains_splits = 0;
1304 uint last_added = 0;
1305 uint first_added = 0;
1306 bool first_set =
false;
1309 for (
uint j = 0; j < g->edges_len; j++,
e++) {
1310 const uint flip = (
uint)(vm[orig_medge[(*e)->old_edge].
v2] == i);
1311 BLI_assert(flip || vm[orig_medge[(*e)->old_edge].
v1] == i);
1312 (*e)->link_edge_groups[flip] = g;
1315 if (do_shell || (do_rim && !g->is_orig_closed)) {
1317 g->new_vert = numNewVerts++;
1318 if (do_rim || (do_shell && g->split)) {
1320 contains_splits += (g->split != 0);
1321 contains_open_splits |= g->split && !g->is_orig_closed;
1325 open_edges += (
uint)(added < last_added);
1328 first_added = added;
1331 if (!(g + 1)->valid || g->topo_group != (g + 1)->topo_group) {
1332 if (new_verts > 2) {
1334 numNewEdges += new_verts;
1335 open_edges += (
uint)(first_added < last_added);
1336 open_edges -= (
uint)(open_edges && !contains_open_splits);
1337 if (do_shell && do_rim) {
1338 numNewLoops += new_verts * 2;
1340 else if (do_shell) {
1341 numNewLoops += new_verts * 2 - open_edges;
1344 numNewLoops += new_verts * 2 + open_edges - contains_splits;
1347 else if (new_verts == 2) {
1349 numNewLoops += 2u - (
uint)(!(do_rim && do_shell) && contains_open_splits);
1352 contains_open_splits =
false;
1353 contains_splits = 0;
1368 for (
OldVertEdgeRef **p = vert_adj_edges; i < numVerts; i++, p++) {
1384 float *face_weight =
NULL;
1386 if (do_flat_faces) {
1387 face_weight =
MEM_malloc_arrayN(numPolys,
sizeof(*face_weight),
"face_weight in solidify");
1390 for (
uint i = 0; i < numPolys; i++, mp++) {
1391 float scalar_vgroup = 1.0f;
1392 int loopend = mp->loopstart + mp->totloop;
1393 ml = orig_mloop + mp->loopstart;
1394 for (
int j = mp->loopstart; j < loopend; j++, ml++) {
1396 if (defgrp_invert) {
1404 scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv);
1405 face_weight[i] = scalar_vgroup;
1410 gs_ptr = orig_vert_groups_arr;
1411 for (
uint i = 0; i < numVerts; i++,
mv++, gs_ptr++) {
1417 float move_nor[3] = {0, 0, 0};
1418 bool disable_boundary_fix = (smd->nonmanifold_boundary_mode ==
1427 g->
edges_len + 1,
sizeof(*normals_queue),
"normals_queue in solidify");
1430 float face_nors[3][3];
1435 if (!(k & 1) || (!cycle && k == g->
edges_len - 1)) {
1437 for (
uint l = 0;
l < 2;
l++) {
1439 if (face && (first_edge ==
NULL ||
1440 (first_edge->
faces[0] != face && first_edge->
faces[1] != face))) {
1441 float ofs = face->
reversed ? ofs_back_clamped : ofs_front_clamped;
1443 if (do_flat_faces) {
1444 ofs *= face_weight[face->
index];
1447 if (!null_faces[face->
index]) {
1450 poly_nors[face->
index],
1462 if ((cycle && k == 0) || (!cycle && k + 3 >= g->
edges_len)) {
1467 uint face_nors_len = 0;
1468 const float stop_explosion = 0.999f -
fabsf(smd->offset_fac) * 0.05f;
1470 if (face_nors_len == 0) {
1474 nor_ofs[k] = normals_queue[k][3];
1486 float p =
dot_v3v3(normals_queue[k], normals_queue[m]);
1487 if (p <= min_p + FLT_EPSILON) {
1494 copy_v3_v3(face_nors[0], normals_queue[min_n0]);
1495 copy_v3_v3(face_nors[1], normals_queue[min_n1]);
1496 nor_ofs[0] = normals_queue[min_n0][3];
1497 nor_ofs[1] = normals_queue[min_n1][3];
1500 memmove(normals_queue + min_n0,
1501 normals_queue + min_n0 + 1,
1504 memmove(normals_queue + min_n1,
1505 normals_queue + min_n1 + 1,
1512 for (
uint m = 0; m < face_nors_len; m++) {
1513 float p =
dot_v3v3(face_nors[m], normals_queue[k]);
1514 if (p > max_p + FLT_EPSILON) {
1518 if (max_p <= min_p + FLT_EPSILON) {
1524 copy_v3_v3(face_nors[2], normals_queue[min_n1]);
1525 nor_ofs[2] = normals_queue[min_n1][3];
1528 memmove(normals_queue + min_n1,
1529 normals_queue + min_n1 + 1,
1536 uint best_group = 0;
1537 float best_p = -1.0f;
1539 for (
uint m = 0; m < face_nors_len; m++) {
1540 float p =
dot_v3v3(face_nors[m], normals_queue[k]);
1541 if (p > best_p + FLT_EPSILON) {
1548 add_v3_v3(face_nors[best], normals_queue[best_group]);
1550 nor_ofs[best] = (nor_ofs[best] + normals_queue[best_group][3]) * 0.5f;
1552 memmove(normals_queue + best_group,
1553 normals_queue + best_group + 1,
1554 (
queue_index - best_group) *
sizeof(*normals_queue));
1560 if (
ELEM(face_nors_len, 2, 3)) {
1561 const float q =
dot_v3v3(face_nors[0], face_nors[1]);
1562 float d = 1.0f - q * q;
1564 if (d > FLT_EPSILON * 10 && q < stop_explosion) {
1566 mul_v3_fl(face_nors[0], (nor_ofs[0] - nor_ofs[1] * q) * d);
1567 mul_v3_fl(face_nors[1], (nor_ofs[1] - nor_ofs[0] * q) * d);
1570 d = 1.0f / (
fabsf(q) + 1.0f);
1571 mul_v3_fl(face_nors[0], nor_ofs[0] * d);
1572 mul_v3_fl(face_nors[1], nor_ofs[1] * d);
1575 if (face_nors_len == 3) {
1576 float *free_nor = move_nor;
1578 d =
dot_v3v3(face_nors[2], free_nor);
1584 disable_boundary_fix =
true;
1590 disable_boundary_fix =
true;
1595 float total_angle = 0;
1596 float total_angle_back = 0;
1600 float nor_back[3] = {0, 0, 0};
1601 bool has_back =
false;
1602 bool has_front =
false;
1605 if (!(k & 1) || (!cycle && k == g->
edges_len - 1)) {
1607 for (
uint l = 0;
l < 2;
l++) {
1609 if (face && (first_edge ==
NULL ||
1610 (first_edge->
faces[0] != face && first_edge->
faces[1] != face))) {
1612 float ofs = face->
reversed ? -ofs_back_clamped : ofs_front_clamped;
1614 if (do_flat_faces) {
1615 ofs *= face_weight[face->
index];
1618 if (smd->nonmanifold_offset_mode ==
1622 MLoop *ml_prev = ml - 1;
1623 for (
int m = 0; m < face->
face->
totloop && vm[ml->v] != i;
1630 orig_mvert_co[vm[ml_next->
v]]);
1632 total_angle_back +=
angle * ofs * ofs;
1635 total_angle +=
angle * ofs * ofs;
1657 if ((cycle && k == 0) || (!cycle && k + 3 >= g->
edges_len)) {
1667 if (
LIKELY(length_sq > FLT_EPSILON)) {
1673 if (
LIKELY(length_sq > FLT_EPSILON)) {
1674 mul_v3_fl(nor_back, total_angle_back / length_sq);
1680 if (has_front && has_back) {
1682 float nor_back_length =
len_v3(nor_back);
1685 q /= nor_length * nor_back_length;
1687 float d = 1.0f - q * q;
1688 if (
LIKELY(d > FLT_EPSILON)) {
1690 if (
LIKELY(nor_length > FLT_EPSILON)) {
1691 mul_v3_fl(
nor, (1 - nor_back_length * q / nor_length) * d);
1693 if (
LIKELY(nor_back_length > FLT_EPSILON)) {
1694 mul_v3_fl(nor_back, (1 - nor_length * q / nor_back_length) * d);
1706 if (has_front && total_angle > FLT_EPSILON) {
1709 if (has_back && total_angle_back > FLT_EPSILON) {
1710 mul_v3_fl(nor_back, 1.0f / total_angle_back);
1712 if (has_front && total_angle > FLT_EPSILON) {
1718 if (!disable_boundary_fix && g->
edges_len > 2) {
1719 edge_ptr = g->
edges + 1;
1722 for (k = 1; k + 1 < g->
edges_len; k++, edge_ptr++) {
1723 MEdge *
e = orig_medge + (*edge_ptr)->old_edge;
1725 tmp, orig_mvert_co[vm[
e->v1] == i ?
e->v2 :
e->v1], orig_mvert_co[i]);
1729 disable_boundary_fix =
true;
1736 disable_boundary_fix =
true;
1740 if (!disable_boundary_fix) {
1742 float constr_nor[3];
1748 orig_mvert_co[vm[e0_edge->
v1] == i ? e0_edge->
v2 : e0_edge->
v1],
1751 orig_mvert_co[vm[e1_edge->
v1] == i ? e1_edge->
v2 : e1_edge->
v1],
1779 float d =
dot_v3v3(constr_nor, move_nor);
1785 float scalar_vgroup = 1;
1787 if (dvert && !do_flat_faces) {
1789 if (defgrp_invert) {
1795 scalar_vgroup = offset_fac_vg + (scalar_vgroup * offset_fac_vg_inv);
1799 if (do_angle_clamp) {
1801 float min_length = 0;
1805 float length = orig_edge_lengths[(*p)->old_edge];
1806 float e_ang = (*p)->angle;
1807 if (e_ang >
angle) {
1810 if (
length < min_length || k == 0) {
1816 float max_off = min_length * 0.5f / cos_ang;
1817 if (max_off < offset * 0.5f) {
1818 scalar_vgroup *= max_off / offset * 2;
1824 float min_length = 0;
1827 float length = orig_edge_lengths[(*p)->old_edge];
1828 if (
length < min_length || k == 0) {
1832 if (min_length < offset) {
1833 scalar_vgroup *= min_length / offset;
1847 if (do_flat_faces) {
1861 uint(*singularity_edges)[2] =
NULL;
1862 uint totsingularity = 0;
1863 if (has_singularities) {
1864 has_singularities =
false;
1866 uint singularity_edges_len = 1;
1868 singularity_edges_len,
sizeof(*singularity_edges),
"singularity_edges in solidify");
1869 for (
NewEdgeRef ***new_edges = orig_edge_data_arr; i < numEdges; i++, new_edges++) {
1870 if (*new_edges && (do_shell || edge_adj_faces_len[i] == 1) && (**new_edges)->old_edge == i) {
1872 if ((*l)->link_edge_groups[0]->is_singularity &&
1873 (*l)->link_edge_groups[1]->is_singularity) {
1874 const uint v1 = (*l)->link_edge_groups[0]->new_vert;
1875 const uint v2 = (*l)->link_edge_groups[1]->new_vert;
1876 bool exists_already =
false;
1878 for (
uint(*p)[2] = singularity_edges; j < totsingularity; p++, j++) {
1879 if (((*p)[0] ==
v1 && (*p)[1] ==
v2) || ((*p)[0] ==
v2 && (*p)[1] ==
v1)) {
1880 exists_already =
true;
1884 if (!exists_already) {
1885 has_singularities =
true;
1886 if (singularity_edges_len <= totsingularity) {
1887 singularity_edges_len = totsingularity + 1;
1889 singularity_edges_len *
1890 sizeof(*singularity_edges),
1891 "singularity_edges in solidify");
1893 singularity_edges[totsingularity][0] =
v1;
1894 singularity_edges[totsingularity][1] =
v2;
1896 if (edge_adj_faces_len[i] == 1 && do_rim) {
1912 mesh, (
int)(numNewVerts), (
int)(numNewEdges), 0, (
int)(numNewLoops), (
int)(numNewPolys));
1922 if (bevel_convex != 0.0f) {
1928 if (shell_defgrp_index != -1 || rim_defgrp_index != -1) {
1931 if (dvert ==
NULL) {
1941 gs_ptr = orig_vert_groups_arr;
1942 for (
uint i = 0; i < numVerts; i++, gs_ptr++) {
1950 mvert[g->
new_vert].flag = orig_mvert[i].flag;
1962 edge_index += totsingularity;
1963 for (
NewEdgeRef ***new_edges = orig_edge_data_arr; i < numEdges; i++, new_edges++) {
1964 if (*new_edges && (do_shell || edge_adj_faces_len[i] == 1) && (**new_edges)->old_edge == i) {
1967 const uint v1 = (*l)->link_edge_groups[0]->new_vert;
1968 const uint v2 = (*l)->link_edge_groups[1]->new_vert;
1970 if (has_singularities && ((*l)->link_edge_groups[0]->is_singularity &&
1971 (*l)->link_edge_groups[1]->is_singularity)) {
1973 for (
uint(*p)[2] = singularity_edges; j < totsingularity; p++, j++) {
1974 if (((*p)[0] ==
v1 && (*p)[1] ==
v2) || ((*p)[0] ==
v2 && (*p)[1] ==
v1)) {
1990 medge[
insert].crease = orig_medge[(*l)->old_edge].crease;
1991 medge[
insert].bweight = orig_medge[(*l)->old_edge].bweight;
1992 if (bevel_convex != 0.0f && (*l)->faces[1] !=
NULL) {
1994 (
int)medge[
insert].bweight + (int)(((*l)->angle >
M_PI + FLT_EPSILON ?
1995 clamp_f(bevel_convex, 0.0f, 1.0f) :
1996 ((*l)->angle <
M_PI - FLT_EPSILON ?
1997 clamp_f(bevel_convex, -1.0f, 0.0f) :
2009 if (singularity_edges) {
2033 gs_ptr = orig_vert_groups_arr;
2034 for (
uint i = 0; i < numVerts; i++, gs_ptr++) {
2042 printf(
"%u/%d, ", (*e)->old_edge, (
int)(*e)->new_edge);
2053 gs_ptr = orig_vert_groups_arr;
2055 for (
uint i = 0; i < numVerts; i++, gs_ptr++,
mv++) {
2064 char last_max_crease = 0;
2065 char first_max_crease = 0;
2067 char last_max_bweight = 0;
2068 char first_max_bweight = 0;
2070 short last_flag = 0;
2071 short first_flag = 0;
2087 if (ed->crease > max_crease) {
2088 max_crease = ed->crease;
2092 if (bweight > max_bweight) {
2093 max_bweight = bweight;
2100 const char bweight_open_edge =
min_cc(
2103 if (bweight_open_edge > 0) {
2104 max_bweight =
min_cc(bweight_open_edge, max_bweight);
2107 if (bevel_convex < 0.0f) {
2113 first_max_crease = max_crease;
2114 first_max_bweight = max_bweight;
2124 if (origindex_edge) {
2127 medge[edge_index].v1 = last_g->
new_vert;
2128 medge[edge_index].v2 = g->
new_vert;
2131 medge[edge_index].crease =
min_cc(last_max_crease, max_crease);
2132 medge[edge_index++].bweight =
max_cc(
mv->bweight,
2133 min_cc(last_max_bweight, max_bweight));
2136 last_max_crease = max_crease;
2137 last_max_bweight = max_bweight;
2141 if (!(g + 1)->valid || g->
topo_group != (g + 1)->topo_group) {
2151 if (origindex_edge) {
2155 medge[edge_index].v1 = last_g->
new_vert;
2156 medge[edge_index].v2 = first_g->
new_vert;
2159 medge[edge_index].crease =
min_cc(last_max_crease, first_max_crease);
2160 medge[edge_index++].bweight =
max_cc(
mv->bweight,
2161 min_cc(last_max_bweight, first_max_bweight));
2166 short most_mat_nr = 0;
2167 uint most_mat_nr_face = 0;
2168 uint most_mat_nr_count = 0;
2169 for (
short l = 0;
l < mat_nrs;
l++) {
2174 if ((do_rim && !g3->is_orig_closed) || (do_shell && g3->split)) {
2176 if (g3->edges[0]->faces[0]->face->mat_nr ==
l) {
2177 face = g3->edges[0]->faces[0]->
index;
2180 NewEdgeRef *le = g3->edges[g3->edges_len - 1];
2192 if (
count > most_mat_nr_count) {
2194 most_mat_nr_face = face;
2195 most_mat_nr_count =
count;
2199 &
mesh->pdata, &
result->pdata, (
int)most_mat_nr_face, (
int)poly_index, 1);
2200 if (origindex_poly) {
2203 mpoly[poly_index].loopstart = (int)loop_index;
2204 mpoly[poly_index].totloop = (int)j;
2205 mpoly[poly_index].mat_nr = most_mat_nr +
2207 CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max);
2208 mpoly[poly_index].flag = orig_mpoly[most_mat_nr_face].flag;
2211 for (
uint k = 0; g2->
valid && k < j; g2++) {
2215 for (
int l = 0;
l < face->
totloop;
l++, ml++) {
2216 if (vm[ml->v] == i) {
2226 for (
uint k = 0; k < j; k++) {
2228 mloop[loop_index].v = medge[edge_index - j + k].v1;
2229 mloop[loop_index++].e = edge_index - j + k;
2233 for (
uint k = 1; k <= j; k++) {
2236 mloop[loop_index].v = medge[edge_index - k].v2;
2237 mloop[loop_index++].e = edge_index - k;
2246 last_max_crease = 0;
2247 first_max_crease = 0;
2248 last_max_bweight = 0;
2249 first_max_bweight = 0;
2260 for (
uint i = 0; i < numEdges; i++) {
2261 if (edge_adj_faces_len[i] == 1 && orig_edge_data_arr[i] &&
2262 (*orig_edge_data_arr[i])->old_edge == i) {
2263 NewEdgeRef **new_edges = orig_edge_data_arr[i];
2271 if (v1_singularity && v2_singularity) {
2275 MPoly *face = (*new_edges)->faces[0]->face;
2277 &
mesh->pdata, &
result->pdata, (
int)(*new_edges)->faces[0]->index, (
int)poly_index, 1);
2278 mpoly[poly_index].loopstart = (int)loop_index;
2279 mpoly[poly_index].totloop = 4 - (int)(v1_singularity || v2_singularity);
2280 mpoly[poly_index].mat_nr = face->
mat_nr + mat_ofs_rim;
2281 CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max);
2282 mpoly[poly_index].flag = face->
flag;
2288 const uint old_v1 = vm[orig_medge[edge1->
old_edge].v1];
2289 const uint old_v2 = vm[orig_medge[edge1->
old_edge].v2];
2291 if (vm[ml->v] == old_v1) {
2294 else if (vm[ml->v] == old_v2) {
2299 MEdge *open_face_edge;
2300 uint open_face_edge_index;
2302 if (rim_defgrp_index != -1) {
2307 mloop[loop_index].v = medge[edge1->
new_edge].v1;
2308 mloop[loop_index++].e = edge1->
new_edge;
2310 if (!v2_singularity) {
2312 if (rim_defgrp_index != -1) {
2317 mloop[loop_index].v = medge[edge1->
new_edge].v2;
2318 open_face_edge = medge + open_face_edge_index;
2319 if (
ELEM(medge[edge2->
new_edge].v2, open_face_edge->
v1, open_face_edge->
v2)) {
2320 mloop[loop_index++].e = open_face_edge_index;
2327 if (rim_defgrp_index != -1) {
2332 mloop[loop_index].v = medge[edge2->
new_edge].v2;
2333 mloop[loop_index++].e = edge2->
new_edge;
2335 if (!v1_singularity) {
2337 if (rim_defgrp_index != -1) {
2342 mloop[loop_index].v = medge[edge2->
new_edge].v1;
2343 open_face_edge = medge + open_face_edge_index;
2344 if (
ELEM(medge[edge1->
new_edge].v1, open_face_edge->
v1, open_face_edge->
v2)) {
2345 mloop[loop_index++].e = open_face_edge_index;
2353 if (!v1_singularity) {
2355 if (rim_defgrp_index != -1) {
2360 mloop[loop_index].v = medge[edge1->
new_edge].v1;
2361 open_face_edge = medge + open_face_edge_index;
2362 if (
ELEM(medge[edge2->
new_edge].v1, open_face_edge->
v1, open_face_edge->
v2)) {
2363 mloop[loop_index++].e = open_face_edge_index;
2370 if (rim_defgrp_index != -1) {
2375 mloop[loop_index].v = medge[edge2->
new_edge].v1;
2376 mloop[loop_index++].e = edge2->
new_edge;
2378 if (!v2_singularity) {
2380 if (rim_defgrp_index != -1) {
2385 mloop[loop_index].v = medge[edge2->
new_edge].v2;
2386 open_face_edge = medge + open_face_edge_index;
2387 if (
ELEM(medge[edge1->
new_edge].v2, open_face_edge->
v1, open_face_edge->
v2)) {
2388 mloop[loop_index++].e = open_face_edge_index;
2395 if (rim_defgrp_index != -1) {
2400 mloop[loop_index].v = medge[edge1->
new_edge].v2;
2401 mloop[loop_index++].e = edge1->
new_edge;
2411 largest_ngon * 2,
sizeof(*face_loops),
"face_loops in solidify");
2413 largest_ngon * 2,
sizeof(*face_verts),
"face_verts in solidify");
2415 largest_ngon * 2,
sizeof(*face_edges),
"face_edges in solidify");
2416 for (
uint i = 0; i < numPolys * 2; i++, fr++) {
2419 uint valid_edges = 0;
2421 while (totloop > 0 && (!fr->
link_edges[totloop - 1] ||
2428 vm[orig_mloop[loopstart + (totloop - 1)].v]);
2429 for (
uint j = 0; j < totloop; j++) {
2434 vm[orig_mloop[loopstart + j].v]);
2436 vm[orig_medge[new_edge->
old_edge].v1] == vm[orig_mloop[loopstart + j].v]);
2441 if (k == 0 || face_verts[k - 1] != new_v1) {
2442 face_loops[k] = loopstart + j;
2449 BLI_assert(k == 0 || medge[face_edges[k]].
v2 == face_verts[k - 1] ||
2450 medge[face_edges[k]].
v1 == face_verts[k - 1]);
2452 medge[face_edges[k]].
v2 == new_v1 || medge[face_edges[k]].
v1 == new_v1);
2453 face_verts[k++] = new_v1;
2455 prior_edge = new_edge;
2456 prior_flip = 1 - flip;
2457 if (j < totloop - 1 || face_verts[0] != new_v2) {
2458 face_loops[k] = loopstart + (j + 1) % totloop;
2459 face_edges[k] = new_edge->
new_edge;
2460 face_verts[k++] = new_v2;
2463 face_edges[0] = new_edge->
new_edge;
2467 if (k > 2 && valid_edges > 2) {
2469 mpoly[poly_index].loopstart = (int)loop_index;
2470 mpoly[poly_index].totloop = (int)k;
2471 mpoly[poly_index].mat_nr = fr->
face->
mat_nr + (fr->
reversed != do_flip ? mat_ofs : 0);
2472 CLAMP(mpoly[poly_index].mat_nr, 0, mat_nr_max);
2473 mpoly[poly_index].flag = fr->
face->
flag;
2475 for (
int l = (
int)k - 1;
l >= 0;
l--) {
2476 if (shell_defgrp_index != -1) {
2482 mloop[loop_index].v = face_verts[
l];
2483 mloop[loop_index++].e = face_edges[
l];
2488 for (
uint next_l = 0; next_l < k; next_l++) {
2491 mloop[loop_index].v = face_verts[
l];
2492 mloop[loop_index++].e = face_edges[next_l];
2504 if (edge_index != numNewEdges) {
2507 "Internal Error: edges array wrong size: %u instead of %u",
2511 if (poly_index != numNewPolys) {
2514 "Internal Error: polys array wrong size: %u instead of %u",
2518 if (loop_index != numNewLoops) {
2521 "Internal Error: loops array wrong size: %u instead of %u",
2534 for (
EdgeGroup **p = orig_vert_groups_arr; i < numVerts; i++, p++) {
2544 for (
NewEdgeRef ***p = orig_edge_data_arr + (numEdges - 1); i > 0; i--, p--) {
2545 if (*p && (**p)->old_edge == i - 1) {
2555 for (
NewFaceRef *p = face_sides_arr; i < numPolys * 2; i++, p++) {
2562 #undef MOD_SOLIDIFY_EMPTY_TAG
typedef float(TangentPoint)[2]
void * CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const 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_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
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_mesh_calc_normals_poly(struct MVert *mverts, float(*r_vertnors)[3], int numVerts, const struct MLoop *mloop, const struct MPoly *mpolys, int numLoops, int numPolys, float(*r_polyNors)[3], const bool only_face_normals)
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
void BLI_kdtree_nd_() insert(KDTree *tree, int index, const float co[KD_DIMS]) ATTR_NONNULL(1
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)
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
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 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_OFFSET_MODE_EVEN
@ MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS
@ MOD_SOLIDIFY_OFFSET_ANGLE_CLAMP
@ MOD_SOLIDIFY_NONMANIFOLD_FLAT_FACES
@ MOD_SOLIDIFY_VGROUP_INV
@ MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_FLAT
@ MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_NONE
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
#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 RGB to Bright Vector Camera 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 length(const btQuaternion &q)
Return the length of a quaternion.
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int * queue_index
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)
void split(const std::string &s, const char delim, std::vector< std::string > &tokens)
struct CustomData pdata ldata
struct EdgeGroup * link_edge_groups[2]
struct NewEdgeRef ** link_edges
char nonmanifold_offset_mode
char shell_defgrp_name[64]
__forceinline avxf cross(const avxf &a, const avxf &b)