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;
217 if (need_face_normals) {
219 face_normals = mesh->face_normals_true();
230#define INVALID_UNUSED uint(-1)
231#define INVALID_PAIR uint(-2)
244 for (eidx = 0; eidx < edges_num; eidx++) {
252 int corner_i_prev = face.
last();
254 for (j = 0; j < face.
size(); j++) {
255 const int corner_i = face[j];
256 const int vert_i = orig_corner_verts[corner_i];
257 const int prev_vert_i = orig_corner_verts[corner_i_prev];
259 eidx = int(orig_corner_edges[corner_i_prev]);
263 edge_users[eidx] = (prev_vert_i > vert_i) == (edge[0] < edge[1]) ?
uint(
i) :
264 (
uint(
i) + faces_num);
265 edge_order[eidx] = j;
270 corner_i_prev = corner_i;
274 for (eidx = 0; eidx < edges_num; eidx++) {
284 for (
i = 0;
i < verts_num;
i++) {
298 if (do_shell ==
false) {
310#ifdef USE_NONMANIFOLD_WORKAROUND
327 int((verts_num * stride) + newVerts),
328 int((edges_num * stride) + newEdges + rimVerts),
329 int((faces_num * stride) + newPolys),
330 int((loops_num * stride) + newLoops));
356 face_offsets[faces_num +
i] = orig_faces[
i].start() + mesh->
corners_num;
362 for (
i = 0, j =
int(verts_num);
i < verts_num;
i++) {
371 for (
i = 0, j =
int(edges_num);
i < edges_num;
i++) {
378 (*ed_dst)[0] = old_vert_arr[(*ed_src)[0]] + verts_num;
379 (*ed_dst)[1] = old_vert_arr[(*ed_src)[1]] + verts_num;
390 const float *orig_vert_bweight =
static_cast<const float *
>(
394 if (!result_edge_bweight && (do_bevel_convex || orig_vert_bweight)) {
399 "bevel_weight_edge"));
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; \
431 const int loop_end = face.
size() - 1;
439 for (j = 0; j < face.
size(); j++) {
450 for (
int j_prev = loop_end; j < face.
size(); j_prev = j++) {
460 dst_material_index.
span[faces_num +
i] += mat_ofs;
461 CLAMP(dst_material_index.
span[faces_num +
i], 0, mat_nr_max);
464 e = corner_edges[corner_2 + 0];
465 for (j = 0; j < loop_end; j++) {
466 corner_edges[corner_2 + j] = corner_edges[corner_2 + j + 1];
468 corner_edges[corner_2 + loop_end] =
e;
470 for (j = 0; j < face.
size(); j++) {
471 corner_verts[corner_2 + j] += verts_num;
472 corner_edges[corner_2 + j] += edges_num;
484 float ofs_new_vgroup;
487 float *vert_lens =
nullptr;
488 float *vert_angs =
nullptr;
490 const float offset_sq = offset * offset;
493 float *edge_angs =
nullptr;
498 for (
uint i = 0;
i < edges_num;
i++) {
500 vert_positions[edges[
i][1]]);
501 vert_lens[edges[
i][0]] =
min_ff(vert_lens[edges[
i][0]], ed_len_sq);
502 vert_lens[edges[
i][1]] =
min_ff(vert_lens[edges[
i][1]], ed_len_sq);
506 if (do_angle_clamp || do_bevel_convex) {
508 if (do_angle_clamp) {
512 if (do_bevel_convex) {
519 for (eidx = 0; eidx < edges_num; eidx++) {
525 int prev_corner_i = face.
last();
526 for (
const int corner_i : face) {
527 const int vert_i = orig_corner_verts[corner_i];
528 const int prev_vert_i = orig_corner_verts[prev_corner_i];
530 eidx = orig_corner_edges[prev_corner_i];
533 char flip = char((prev_vert_i > vert_i) == (
ed[0] <
ed[1]));
535 edge_user_pairs[eidx][flip] =
uint(
i);
541 prev_corner_i = corner_i;
545 for (
uint i = 0;
i < edges_num;
i++) {
550 const float *n0 = face_normals[edge_user_pairs[
i][0]];
551 const float *n1 = face_normals[edge_user_pairs[
i][1]];
552 sub_v3_v3v3(
e, orig_vert_positions[edge[0]], orig_vert_positions[edge[1]]);
555 if (do_angle_clamp) {
556 vert_angs[edge[0]] =
max_ff(vert_angs[edge[0]],
angle);
557 vert_angs[edge[1]] =
max_ff(vert_angs[edge[1]],
angle);
559 if (do_bevel_convex) {
570 if (ofs_new != 0.0f) {
574 ofs_new_vgroup = ofs_new;
579 for (i_orig = 0; i_orig < i_end; i_orig++, vert_index++) {
580 const uint i = do_shell_align ? i_orig : new_vert_arr[i_orig];
589 ofs_new_vgroup = (offset_fac_vg + (ofs_new_vgroup * offset_fac_vg_inv)) * ofs_new;
591 if (do_clamp && offset > FLT_EPSILON) {
593 if (dvert ==
nullptr) {
594 ofs_new_vgroup = ofs_new;
596 if (do_angle_clamp) {
597 float cos_ang =
cosf(((2 *
M_PI) - vert_angs[
i]) * 0.5f);
599 float max_off =
sqrtf(vert_lens[
i]) * 0.5f / cos_ang;
600 if (max_off < offset * 0.5f) {
601 ofs_new_vgroup *= max_off / offset * 2;
606 if (vert_lens[
i] < offset_sq) {
607 float scalar =
sqrtf(vert_lens[
i]) / offset;
608 ofs_new_vgroup *= scalar;
613 madd_v3_v3fl(vert_positions[vert_index], vert_nors[
i], ofs_new_vgroup);
616 madd_v3_v3fl(vert_positions[vert_index], vert_normals[
i], ofs_new_vgroup);
621 if (ofs_orig != 0.0f) {
625 ofs_new_vgroup = ofs_orig;
631 for (i_orig = 0; i_orig < i_end; i_orig++, vert_index++) {
632 const uint i = do_shell_align ? i_orig : new_vert_arr[i_orig];
641 ofs_new_vgroup = (offset_fac_vg + (ofs_new_vgroup * offset_fac_vg_inv)) * ofs_orig;
643 if (do_clamp && offset > FLT_EPSILON) {
645 if (dvert ==
nullptr) {
646 ofs_new_vgroup = ofs_orig;
648 if (do_angle_clamp) {
649 float cos_ang =
cosf(vert_angs[i_orig] * 0.5f);
651 float max_off =
sqrtf(vert_lens[
i]) * 0.5f / cos_ang;
652 if (max_off < offset * 0.5f) {
653 ofs_new_vgroup *= max_off / offset * 2;
658 if (vert_lens[
i] < offset_sq) {
659 float scalar =
sqrtf(vert_lens[
i]) / offset;
660 ofs_new_vgroup *= scalar;
665 madd_v3_v3fl(vert_positions[vert_index], vert_nors[
i], ofs_new_vgroup);
668 madd_v3_v3fl(vert_positions[vert_index], vert_normals[
i], ofs_new_vgroup);
673 if (do_bevel_convex) {
674 for (
uint i = 0;
i < edges_num;
i++) {
676 float angle = edge_angs[
i];
677 result_edge_bweight[
i] =
clamp_f(result_edge_bweight[
i] +
679 clamp_f(bevel_convex, -1.0f, 0.0f)),
683 result_edge_bweight[
i + edges_num] =
clamp_f(
684 result_edge_bweight[
i + edges_num] + (
angle >
M_PI ?
685 clamp_f(bevel_convex, 0.0f, 1.0f) :
686 clamp_f(bevel_convex, -1.0f, 0.0f)),
700 if (do_angle_clamp) {
706#ifdef USE_NONMANIFOLD_WORKAROUND
711 float *vert_accum = vert_angles + verts_num;
715 if (vert_nors ==
nullptr) {
717 for (
i = 0;
i < verts_num;
i++) {
728 int i_curr = face.
size() - 1;
731 const int *face_verts = &corner_verts[face.
start()];
732 const int *face_edges = &corner_edges[face.
start()];
735 nor_prev, vert_positions[face_verts[i_curr - 1]], vert_positions[face_verts[i_curr]]);
738 while (i_next < face.
size()) {
741 nor_next, vert_positions[face_verts[i_curr]], vert_positions[face_verts[i_next]]);
748 vidx = face_verts[i_curr];
749 vert_accum[vidx] +=
angle;
751#ifdef USE_NONMANIFOLD_WORKAROUND
753 if ((check_non_manifold ==
false) ||
761 vert_angles[vidx] +=
angle;
782 for (
i = 0;
i < verts_num;
i++, dv++) {
784 scalar = offset_fac_vg + (scalar * offset_fac_vg_inv);
785 vert_angles[
i] *= scalar;
789 for (
i = 0;
i < verts_num;
i++, dv++) {
791 scalar = offset_fac_vg + (scalar * offset_fac_vg_inv);
792 vert_angles[
i] *= scalar;
798 float *vert_angs =
nullptr;
800 float *edge_angs =
nullptr;
802 if (do_angle_clamp || do_bevel_convex) {
804 if (do_angle_clamp) {
808 if (do_bevel_convex) {
815 for (eidx = 0; eidx < edges_num; eidx++) {
821 int prev_corner_i = face.
start() + face.
size() - 1;
822 for (
int j = 0; j < face.
size(); j++) {
823 const int corner_i = face.
start() + j;
824 const int vert_i = orig_corner_verts[corner_i];
825 const int prev_vert_i = orig_corner_verts[prev_corner_i];
828 eidx = orig_corner_edges[prev_corner_i];
831 char flip = char((prev_vert_i > vert_i) == (edge[0] < edge[1]));
833 edge_user_pairs[eidx][flip] =
uint(
i);
839 prev_corner_i = corner_i;
843 for (
i = 0;
i < edges_num;
i++) {
848 const float *n0 = face_normals[edge_user_pairs[
i][0]];
849 const float *n1 = face_normals[edge_user_pairs[
i][1]];
850 if (do_angle_clamp) {
852 vert_angs[edge[0]] =
max_ff(vert_angs[edge[0]],
angle);
853 vert_angs[edge[1]] =
max_ff(vert_angs[edge[1]],
angle);
855 if (do_bevel_convex) {
856 sub_v3_v3v3(
e, orig_vert_positions[edge[0]], orig_vert_positions[edge[1]]);
869 const float clamp_fac = 1 + (do_angle_clamp ?
fabsf(smd->
offset_fac) : 0);
871 if (offset > FLT_EPSILON) {
873 const float offset_sq = offset * offset;
875 for (
i = 0;
i < edges_num;
i++) {
877 vert_positions[edges[
i][1]]);
878 vert_lens_sq[edges[
i][0]] =
min_ff(vert_lens_sq[edges[
i][0]], ed_len);
879 vert_lens_sq[edges[
i][1]] =
min_ff(vert_lens_sq[edges[
i][1]], ed_len);
881 if (do_angle_clamp) {
882 for (
i = 0;
i < verts_num;
i++) {
883 float cos_ang =
cosf(vert_angs[
i] * 0.5f);
885 float max_off =
sqrtf(vert_lens_sq[
i]) * 0.5f / cos_ang;
886 if (max_off < offset * 0.5f) {
887 vert_angles[
i] *= max_off / offset * 2;
894 for (
i = 0;
i < verts_num;
i++) {
895 if (vert_lens_sq[
i] < offset_sq) {
896 float scalar =
sqrtf(vert_lens_sq[
i]) / offset;
897 vert_angles[
i] *= scalar;
905 if (do_bevel_convex) {
906 for (
i = 0;
i < edges_num;
i++) {
908 float angle = edge_angs[
i];
909 result_edge_bweight[
i] =
clamp_f(result_edge_bweight[
i] +
911 clamp_f(bevel_convex, -1.0f, 0.0f)),
915 result_edge_bweight[
i + edges_num] =
clamp_f(
916 result_edge_bweight[
i + edges_num] +
932 if (ofs_new != 0.0f) {
939 for (i_orig = 0; i_orig < i_end; i_orig++, vert_index++) {
940 const uint i_other = do_shell_align ? i_orig : new_vert_arr[i_orig];
941 if (vert_accum[i_other]) {
944 ofs_new * (vert_angles[i_other] / vert_accum[i_other]));
949 if (ofs_orig != 0.0f) {
957 for (i_orig = 0; i_orig < i_end; i_orig++, vert_index++) {
958 const uint i_other = do_shell_align ? i_orig : new_vert_arr[i_orig];
959 if (vert_accum[i_other]) {
962 ofs_orig * (vert_angles[i_other] / vert_accum[i_other]));
970#ifdef USE_NONMANIFOLD_WORKAROUND
979 if (shell_defgrp_index != -1 || rim_defgrp_index != -1) {
983 if (dst_dvert !=
nullptr) {
985 if (rim_defgrp_index != -1) {
986 for (
uint i = 0;
i < rimVerts;
i++) {
994 if (shell_defgrp_index != -1) {
1008 int *origindex_edge;
1012 float *result_edge_crease =
nullptr;
1013 if (crease_rim || crease_outer || crease_inner) {
1016 if (!result_edge_crease) {
1023 origindex_edge =
static_cast<int *
>(
1025 orig_ed = (origindex_edge) ? &origindex_edge[(edges_num * stride) + newEdges] :
nullptr;
1027 int new_edge_index = int(edges_num * stride + newEdges);
1028 for (
i = 0;
i < rimVerts;
i++) {
1029 edges[new_edge_index][0] = new_vert_arr[
i];
1030 edges[new_edge_index][1] = (do_shell ? new_vert_arr[
i] :
i) + verts_num;
1032 if (orig_vert_bweight) {
1033 result_edge_bweight[new_edge_index] = orig_vert_bweight[new_vert_arr[
i]];
1042 result_edge_crease[new_edge_index] = crease_rim;
1048 int new_face_index = int(faces_num * stride);
1052 for (
i = 0;
i < newPolys;
i++) {
1053 uint eidx = new_edge_arr[
i];
1054 uint pidx = edge_users[eidx];
1058 if (pidx >= faces_num) {
1070 &mesh->
face_data, &
result->face_data,
int(pidx),
int((faces_num * stride) +
i), 1);
1072 const int old_face_size = orig_faces[pidx].
size();
1073 face_offsets[new_face_index] = int(j + (loops_num * stride));
1076 k1 = face_offsets[pidx] + (((edge_order[eidx] - 1) + old_face_size) % old_face_size);
1078 k2 = face_offsets[pidx] + (edge_order[eidx]);
1081 &mesh->
corner_data, &
result->corner_data, k2,
int((loops_num * stride) + j + 0), 1);
1083 &mesh->
corner_data, &
result->corner_data, k1,
int((loops_num * stride) + j + 1), 1);
1085 &mesh->
corner_data, &
result->corner_data, k1,
int((loops_num * stride) + j + 2), 1);
1087 &mesh->
corner_data, &
result->corner_data, k2,
int((loops_num * stride) + j + 3), 1);
1089 if (flip ==
false) {
1090 new_corner_verts[j] = edge[0];
1091 new_corner_edges[j++] = eidx;
1093 new_corner_verts[j] = edge[1];
1094 new_corner_edges[j++] = (edges_num * stride) + old_vert_arr[edge[1]] + newEdges;
1096 new_corner_verts[j] = (do_shell ? edge[1] : old_vert_arr[edge[1]]) + verts_num;
1097 new_corner_edges[j++] = (do_shell ? eidx :
i) + edges_num;
1099 new_corner_verts[j] = (do_shell ? edge[0] : old_vert_arr[edge[0]]) + verts_num;
1100 new_corner_edges[j++] = (edges_num * stride) + old_vert_arr[edge[0]] + newEdges;
1103 new_corner_verts[j] = edge[1];
1104 new_corner_edges[j++] = eidx;
1106 new_corner_verts[j] = edge[0];
1107 new_corner_edges[j++] = (edges_num * stride) + old_vert_arr[edge[0]] + newEdges;
1109 new_corner_verts[j] = (do_shell ? edge[0] : old_vert_arr[edge[0]]) + verts_num;
1110 new_corner_edges[j++] = (do_shell ? eidx :
i) + edges_num;
1112 new_corner_verts[j] = (do_shell ? edge[1] : old_vert_arr[edge[1]]) + verts_num;
1113 new_corner_edges[j++] = (edges_num * stride) + old_vert_arr[edge[1]] + newEdges;
1116 if (origindex_edge) {
1123 dst_material_index.
span[new_face_index] += mat_ofs_rim;
1124 CLAMP(dst_material_index.
span[new_face_index], 0, mat_nr_max);
1128 float *cr = &(result_edge_crease[eidx]);
1129 float tcr = *cr + crease_outer;
1130 *cr = tcr > 1.0f ? 1.0f : tcr;
1135 float *cr = &(result_edge_crease[edges_num + (do_shell ? eidx :
i)]);
1136 float tcr = *cr + crease_inner;
1137 *cr = tcr > 1.0f ? 1.0f : tcr;
1154 dst_material_index.
finish();