157 uint newLoops = 0, newPolys = 0, newEdges = 0, newVerts = 0, rimVerts = 0;
161 const short mat_ofs = mat_nr_max ? smd->
mat_ofs : 0;
162 const short mat_ofs_rim = mat_nr_max ? smd->
mat_ofs_rim : 0;
166 uint *new_vert_arr =
nullptr;
169 uint *new_edge_arr =
nullptr;
174 uint *edge_users =
nullptr;
175 int *edge_order =
nullptr;
177 float (*vert_nors)[3] =
nullptr;
186 const float ofs_new = smd->
offset + ofs_orig;
193 const bool do_bevel_convex = bevel_convex != 0.0f;
205 const uint stride = do_shell ? 2 : 1;
218 if (need_face_normals) {
220 face_normals = mesh->face_normals_true();
231#define INVALID_UNUSED uint(-1)
232#define INVALID_PAIR uint(-2)
245 for (eidx = 0; eidx < edges_num; eidx++) {
253 int corner_i_prev = face.
last();
255 for (j = 0; j < face.
size(); j++) {
256 const int corner_i = face[j];
257 const int vert_i = orig_corner_verts[corner_i];
258 const int prev_vert_i = orig_corner_verts[corner_i_prev];
260 eidx = int(orig_corner_edges[corner_i_prev]);
264 edge_users[eidx] = (prev_vert_i > vert_i) == (edge[0] < edge[1]) ?
uint(
i) :
265 (
uint(
i) + faces_num);
266 edge_order[eidx] = j;
271 corner_i_prev = corner_i;
275 for (eidx = 0; eidx < edges_num; eidx++) {
285 for (
i = 0;
i < verts_num;
i++) {
299 if (do_shell ==
false) {
311#ifdef USE_NONMANIFOLD_WORKAROUND
328 int((verts_num * stride) + newVerts),
329 int((edges_num * stride) + newEdges + rimVerts),
330 int((faces_num * stride) + newPolys),
331 int((loops_num * stride) + newLoops));
358 face_offsets[faces_num +
i] = orig_faces[
i].start() + mesh->
corners_num;
364 for (
i = 0, j =
int(verts_num);
i < verts_num;
i++) {
373 for (
i = 0, j =
int(edges_num);
i < edges_num;
i++) {
380 (*ed_dst)[0] = old_vert_arr[(*ed_src)[0]] + verts_num;
381 (*ed_dst)[1] = old_vert_arr[(*ed_src)[1]] + verts_num;
392 const VArraySpan orig_vert_bweight = *orig_attributes.
lookup<
float>(
"bevel_weight_vert",
395 if (orig_attributes.
contains(
"bevel_weight_edge") ||
396 (do_bevel_convex || !orig_vert_bweight.
is_empty()))
403#define INIT_VERT_ARRAY_OFFSETS(test) \
404 if (((ofs_new >= ofs_orig) == do_flip) == test) { \
406 do_shell_align = true; \
412 do_shell_align = true; \
416 do_shell_align = false; \
418 vert_index = verts_num; \
430 const int loop_end = face.
size() - 1;
438 for (j = 0; j < face.
size(); j++) {
449 for (
int j_prev = loop_end; j < face.
size(); j_prev = j++) {
459 dst_material_index.
span[faces_num +
i] += mat_ofs;
460 CLAMP(dst_material_index.
span[faces_num +
i], 0, mat_nr_max);
463 e = corner_edges[corner_2 + 0];
464 for (j = 0; j < loop_end; j++) {
465 corner_edges[corner_2 + j] = corner_edges[corner_2 + j + 1];
467 corner_edges[corner_2 + loop_end] =
e;
469 for (j = 0; j < face.
size(); j++) {
470 corner_verts[corner_2 + j] += verts_num;
471 corner_edges[corner_2 + j] += edges_num;
483 float ofs_new_vgroup;
486 float *vert_lens =
nullptr;
487 float *vert_angs =
nullptr;
489 const float offset_sq = offset * offset;
492 float *edge_angs =
nullptr;
497 for (
uint i = 0;
i < edges_num;
i++) {
499 vert_positions[edges[
i][1]]);
500 vert_lens[edges[
i][0]] =
min_ff(vert_lens[edges[
i][0]], ed_len_sq);
501 vert_lens[edges[
i][1]] =
min_ff(vert_lens[edges[
i][1]], ed_len_sq);
505 if (do_angle_clamp || do_bevel_convex) {
507 if (do_angle_clamp) {
511 if (do_bevel_convex) {
518 for (eidx = 0; eidx < edges_num; eidx++) {
524 int prev_corner_i = face.
last();
525 for (
const int corner_i : face) {
526 const int vert_i = orig_corner_verts[corner_i];
527 const int prev_vert_i = orig_corner_verts[prev_corner_i];
529 eidx = orig_corner_edges[prev_corner_i];
532 char flip = char((prev_vert_i > vert_i) == (
ed[0] <
ed[1]));
534 edge_user_pairs[eidx][flip] =
uint(
i);
540 prev_corner_i = corner_i;
544 for (
uint i = 0;
i < edges_num;
i++) {
549 const float *n0 = face_normals[edge_user_pairs[
i][0]];
550 const float *n1 = face_normals[edge_user_pairs[
i][1]];
551 sub_v3_v3v3(
e, orig_vert_positions[edge[0]], orig_vert_positions[edge[1]]);
554 if (do_angle_clamp) {
555 vert_angs[edge[0]] =
max_ff(vert_angs[edge[0]],
angle);
556 vert_angs[edge[1]] =
max_ff(vert_angs[edge[1]],
angle);
558 if (do_bevel_convex) {
569 if (ofs_new != 0.0f) {
573 ofs_new_vgroup = ofs_new;
578 for (i_orig = 0; i_orig < i_end; i_orig++, vert_index++) {
579 const uint i = do_shell_align ? i_orig : new_vert_arr[i_orig];
588 ofs_new_vgroup = (offset_fac_vg + (ofs_new_vgroup * offset_fac_vg_inv)) * ofs_new;
590 if (do_clamp && offset > FLT_EPSILON) {
592 if (dvert ==
nullptr) {
593 ofs_new_vgroup = ofs_new;
595 if (do_angle_clamp) {
596 float cos_ang =
cosf(((2 *
M_PI) - vert_angs[
i]) * 0.5f);
598 float max_off =
sqrtf(vert_lens[
i]) * 0.5f / cos_ang;
599 if (max_off < offset * 0.5f) {
600 ofs_new_vgroup *= max_off / offset * 2;
605 if (vert_lens[
i] < offset_sq) {
606 float scalar =
sqrtf(vert_lens[
i]) / offset;
607 ofs_new_vgroup *= scalar;
612 madd_v3_v3fl(vert_positions[vert_index], vert_nors[
i], ofs_new_vgroup);
615 madd_v3_v3fl(vert_positions[vert_index], vert_normals[
i], ofs_new_vgroup);
620 if (ofs_orig != 0.0f) {
624 ofs_new_vgroup = ofs_orig;
630 for (i_orig = 0; i_orig < i_end; i_orig++, vert_index++) {
631 const uint i = do_shell_align ? i_orig : new_vert_arr[i_orig];
640 ofs_new_vgroup = (offset_fac_vg + (ofs_new_vgroup * offset_fac_vg_inv)) * ofs_orig;
642 if (do_clamp && offset > FLT_EPSILON) {
644 if (dvert ==
nullptr) {
645 ofs_new_vgroup = ofs_orig;
647 if (do_angle_clamp) {
648 float cos_ang =
cosf(vert_angs[i_orig] * 0.5f);
650 float max_off =
sqrtf(vert_lens[
i]) * 0.5f / cos_ang;
651 if (max_off < offset * 0.5f) {
652 ofs_new_vgroup *= max_off / offset * 2;
657 if (vert_lens[
i] < offset_sq) {
658 float scalar =
sqrtf(vert_lens[
i]) / offset;
659 ofs_new_vgroup *= scalar;
664 madd_v3_v3fl(vert_positions[vert_index], vert_nors[
i], ofs_new_vgroup);
667 madd_v3_v3fl(vert_positions[vert_index], vert_normals[
i], ofs_new_vgroup);
672 if (do_bevel_convex) {
673 for (
uint i = 0;
i < edges_num;
i++) {
675 float angle = edge_angs[
i];
676 result_edge_bweight.span[
i] =
clamp_f(
677 result_edge_bweight.span[
i] + (
angle <
M_PI ?
clamp_f(bevel_convex, 0.0f, 1.0f) :
678 clamp_f(bevel_convex, -1.0f, 0.0f)),
682 result_edge_bweight.span[
i + edges_num] =
clamp_f(
683 result_edge_bweight.span[
i + edges_num] + (
angle >
M_PI ?
684 clamp_f(bevel_convex, 0.0f, 1.0f) :
685 clamp_f(bevel_convex, -1.0f, 0.0f)),
699 if (do_angle_clamp) {
705#ifdef USE_NONMANIFOLD_WORKAROUND
710 float *vert_accum = vert_angles + verts_num;
714 if (vert_nors ==
nullptr) {
716 for (
i = 0;
i < verts_num;
i++) {
727 int i_curr = face.
size() - 1;
730 const int *face_verts = &corner_verts[face.
start()];
731 const int *face_edges = &corner_edges[face.
start()];
734 nor_prev, vert_positions[face_verts[i_curr - 1]], vert_positions[face_verts[i_curr]]);
737 while (i_next < face.
size()) {
740 nor_next, vert_positions[face_verts[i_curr]], vert_positions[face_verts[i_next]]);
747 vidx = face_verts[i_curr];
748 vert_accum[vidx] +=
angle;
750#ifdef USE_NONMANIFOLD_WORKAROUND
752 if ((check_non_manifold ==
false) ||
760 vert_angles[vidx] +=
angle;
781 for (
i = 0;
i < verts_num;
i++, dv++) {
783 scalar = offset_fac_vg + (scalar * offset_fac_vg_inv);
784 vert_angles[
i] *= scalar;
788 for (
i = 0;
i < verts_num;
i++, dv++) {
790 scalar = offset_fac_vg + (scalar * offset_fac_vg_inv);
791 vert_angles[
i] *= scalar;
797 float *vert_angs =
nullptr;
799 float *edge_angs =
nullptr;
801 if (do_angle_clamp || do_bevel_convex) {
803 if (do_angle_clamp) {
807 if (do_bevel_convex) {
814 for (eidx = 0; eidx < edges_num; eidx++) {
820 int prev_corner_i = face.
start() + face.
size() - 1;
821 for (
int j = 0; j < face.
size(); j++) {
822 const int corner_i = face.
start() + j;
823 const int vert_i = orig_corner_verts[corner_i];
824 const int prev_vert_i = orig_corner_verts[prev_corner_i];
827 eidx = orig_corner_edges[prev_corner_i];
830 char flip = char((prev_vert_i > vert_i) == (edge[0] < edge[1]));
832 edge_user_pairs[eidx][flip] =
uint(
i);
838 prev_corner_i = corner_i;
842 for (
i = 0;
i < edges_num;
i++) {
847 const float *n0 = face_normals[edge_user_pairs[
i][0]];
848 const float *n1 = face_normals[edge_user_pairs[
i][1]];
849 if (do_angle_clamp) {
851 vert_angs[edge[0]] =
max_ff(vert_angs[edge[0]],
angle);
852 vert_angs[edge[1]] =
max_ff(vert_angs[edge[1]],
angle);
854 if (do_bevel_convex) {
855 sub_v3_v3v3(
e, orig_vert_positions[edge[0]], orig_vert_positions[edge[1]]);
868 const float clamp_fac = 1 + (do_angle_clamp ?
fabsf(smd->
offset_fac) : 0);
870 if (offset > FLT_EPSILON) {
872 const float offset_sq = offset * offset;
874 for (
i = 0;
i < edges_num;
i++) {
876 vert_positions[edges[
i][1]]);
877 vert_lens_sq[edges[
i][0]] =
min_ff(vert_lens_sq[edges[
i][0]], ed_len);
878 vert_lens_sq[edges[
i][1]] =
min_ff(vert_lens_sq[edges[
i][1]], ed_len);
880 if (do_angle_clamp) {
881 for (
i = 0;
i < verts_num;
i++) {
882 float cos_ang =
cosf(vert_angs[
i] * 0.5f);
884 float max_off =
sqrtf(vert_lens_sq[
i]) * 0.5f / cos_ang;
885 if (max_off < offset * 0.5f) {
886 vert_angles[
i] *= max_off / offset * 2;
893 for (
i = 0;
i < verts_num;
i++) {
894 if (vert_lens_sq[
i] < offset_sq) {
895 float scalar =
sqrtf(vert_lens_sq[
i]) / offset;
896 vert_angles[
i] *= scalar;
904 if (do_bevel_convex) {
905 for (
i = 0;
i < edges_num;
i++) {
907 float angle = edge_angs[
i];
908 result_edge_bweight.span[
i] =
clamp_f(
909 result_edge_bweight.span[
i] + (
angle <
M_PI ?
clamp_f(bevel_convex, 0.0f, 1.0f) :
910 clamp_f(bevel_convex, -1.0f, 0.0f)),
914 result_edge_bweight.span[
i + edges_num] =
clamp_f(
915 result_edge_bweight.span[
i + edges_num] +
931 if (ofs_new != 0.0f) {
938 for (i_orig = 0; i_orig < i_end; i_orig++, vert_index++) {
939 const uint i_other = do_shell_align ? i_orig : new_vert_arr[i_orig];
940 if (vert_accum[i_other]) {
943 ofs_new * (vert_angles[i_other] / vert_accum[i_other]));
948 if (ofs_orig != 0.0f) {
956 for (i_orig = 0; i_orig < i_end; i_orig++, vert_index++) {
957 const uint i_other = do_shell_align ? i_orig : new_vert_arr[i_orig];
958 if (vert_accum[i_other]) {
961 ofs_orig * (vert_angles[i_other] / vert_accum[i_other]));
969#ifdef USE_NONMANIFOLD_WORKAROUND
978 if (shell_defgrp_index != -1 || rim_defgrp_index != -1) {
982 if (dst_dvert !=
nullptr) {
984 if (rim_defgrp_index != -1) {
985 for (
uint i = 0;
i < rimVerts;
i++) {
993 if (shell_defgrp_index != -1) {
1007 int *origindex_edge;
1012 if (crease_rim || crease_outer || crease_inner) {
1018 origindex_edge =
static_cast<int *
>(
1020 orig_ed = (origindex_edge) ? &origindex_edge[(edges_num * stride) + newEdges] :
nullptr;
1022 int new_edge_index = int(edges_num * stride + newEdges);
1023 for (
i = 0;
i < rimVerts;
i++) {
1024 edges[new_edge_index][0] = new_vert_arr[
i];
1025 edges[new_edge_index][1] = (do_shell ? new_vert_arr[
i] :
i) + verts_num;
1027 if (result_edge_bweight && !orig_vert_bweight.
is_empty()) {
1028 result_edge_bweight.span[new_edge_index] = orig_vert_bweight[new_vert_arr[
i]];
1036 if (result_edge_crease && crease_rim) {
1037 result_edge_crease.
span[new_edge_index] = crease_rim;
1043 int new_face_index = int(faces_num * stride);
1047 for (
i = 0;
i < newPolys;
i++) {
1048 uint eidx = new_edge_arr[
i];
1049 uint pidx = edge_users[eidx];
1053 if (pidx >= faces_num) {
1065 &mesh->
face_data, &
result->face_data,
int(pidx),
int((faces_num * stride) +
i), 1);
1067 const int old_face_size = orig_faces[pidx].
size();
1068 face_offsets[new_face_index] = int(j + (loops_num * stride));
1071 k1 = face_offsets[pidx] + (((edge_order[eidx] - 1) + old_face_size) % old_face_size);
1073 k2 = face_offsets[pidx] + (edge_order[eidx]);
1076 &mesh->
corner_data, &
result->corner_data, k2,
int((loops_num * stride) + j + 0), 1);
1078 &mesh->
corner_data, &
result->corner_data, k1,
int((loops_num * stride) + j + 1), 1);
1080 &mesh->
corner_data, &
result->corner_data, k1,
int((loops_num * stride) + j + 2), 1);
1082 &mesh->
corner_data, &
result->corner_data, k2,
int((loops_num * stride) + j + 3), 1);
1084 if (flip ==
false) {
1085 new_corner_verts[j] = edge[0];
1086 new_corner_edges[j++] = eidx;
1088 new_corner_verts[j] = edge[1];
1089 new_corner_edges[j++] = (edges_num * stride) + old_vert_arr[edge[1]] + newEdges;
1091 new_corner_verts[j] = (do_shell ? edge[1] : old_vert_arr[edge[1]]) + verts_num;
1092 new_corner_edges[j++] = (do_shell ? eidx :
i) + edges_num;
1094 new_corner_verts[j] = (do_shell ? edge[0] : old_vert_arr[edge[0]]) + verts_num;
1095 new_corner_edges[j++] = (edges_num * stride) + old_vert_arr[edge[0]] + newEdges;
1098 new_corner_verts[j] = edge[1];
1099 new_corner_edges[j++] = eidx;
1101 new_corner_verts[j] = edge[0];
1102 new_corner_edges[j++] = (edges_num * stride) + old_vert_arr[edge[0]] + newEdges;
1104 new_corner_verts[j] = (do_shell ? edge[0] : old_vert_arr[edge[0]]) + verts_num;
1105 new_corner_edges[j++] = (do_shell ? eidx :
i) + edges_num;
1107 new_corner_verts[j] = (do_shell ? edge[1] : old_vert_arr[edge[1]]) + verts_num;
1108 new_corner_edges[j++] = (edges_num * stride) + old_vert_arr[edge[1]] + newEdges;
1111 if (origindex_edge) {
1118 dst_material_index.
span[new_face_index] += mat_ofs_rim;
1119 CLAMP(dst_material_index.
span[new_face_index], 0, mat_nr_max);
1121 if (result_edge_crease && crease_outer) {
1123 float *cr = &(result_edge_crease.
span[eidx]);
1124 float tcr = *cr + crease_outer;
1125 *cr = tcr > 1.0f ? 1.0f : tcr;
1128 if (result_edge_crease && crease_inner) {
1130 float *cr = &(result_edge_crease.
span[edges_num + (do_shell ? eidx :
i)]);
1131 float tcr = *cr + crease_inner;
1132 *cr = tcr > 1.0f ? 1.0f : tcr;
1144 result_edge_crease.
finish();
1151 result_edge_bweight.finish();
1152 dst_material_index.
finish();