11#define DNA_DEPRECATED_ALLOW
82 if (x1->
v1 > x2->
v1) {
85 if (x1->
v1 < x2->
v1) {
88 if (x1->
v2 > x2->
v2) {
91 if (x1->
v2 < x2->
v2) {
101 const MFace *allface,
103 const MPoly *allpoly,
116 uint totedge_final = 0;
121 for (a = totface, mface = allface; a > 0; a--, mface++) {
125 else if (mface->
v3) {
141 for (a = totface, mface = allface; a > 0; a--, mface++) {
148 else if (mface->
v3) {
157 for (a = totedge, ed = edsort; a > 1; a--, ed++) {
159 if (ed->
v1 != (ed + 1)->v1 || ed->
v2 != (ed + 1)->v2) {
165 edges = (MEdge *)
MEM_callocN(
sizeof(MEdge) * totedge_final, __func__);
167 for (a = totedge, edge = edges, ed = edsort; a > 1; a--, ed++) {
169 if (ed->
v1 != (ed + 1)->v1 || ed->
v2 != (ed + 1)->
v2) {
175 if (ed->
v1 + 1 != ed->
v2) {
176 std::swap(edge->v1, edge->v2);
182 (ed + 1)->is_draw |= ed->
is_draw;
194 for (edge_index = 0, edge = edges; edge_index < totedge_final; edge_index++, edge++) {
195 hash.add({edge->v1, edge->v2}, edge_index);
199 for (a = 0; a < faces_num; a++, mpoly++) {
201 int i = mpoly->totloop;
203 ml_next = allloop + mpoly->loopstart;
204 ml = &ml_next[i - 1];
207 ml->e =
hash.lookup({ml->v, ml_next->v});
215 *r_totedge = totedge_final;
230 static_cast<MLoop *
>(
234 mesh->totface_legacy,
247 &mesh->edge_data, CD_MEDGE, edges, totedge,
nullptr);
248 mesh->edges_num = totedge;
250 mesh->tag_topology_changed();
259 MFace *mfaces = mesh->mface;
261 for (a =
b = 0, f = mfaces; a < mesh->totface_legacy; a++, f++) {
264 memcpy(&mfaces[
b], f,
sizeof(mfaces[
b]));
272 mesh->totface_legacy =
b;
296 for (
const MVert &vert :
verts) {
297 if (vert.bweight_legacy != 0) {
298 mesh->cd_flag |= ME_CDFLAG_VERT_BWEIGHT;
303 for (
const MEdge &edge : edges) {
304 if (edge.bweight_legacy != 0) {
305 mesh->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT;
306 if (mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) {
310 if (edge.crease_legacy != 0) {
311 mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE;
312 if (mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
325#define MESH_MLOOPCOL_FROM_MCOL(_mloopcol, _mcol) \
327 MLoopCol *mloopcol__tmp = _mloopcol; \
328 const MCol *mcol__tmp = _mcol; \
329 mloopcol__tmp->r = mcol__tmp->b; \
330 mloopcol__tmp->g = mcol__tmp->g; \
331 mloopcol__tmp->b = mcol__tmp->r; \
332 mloopcol__tmp->a = mcol__tmp->a; \
347 MFace *mf = mface + findex;
349 for (
int i = 0; i < numTex; i++) {
351 fdata_legacy,
CD_MTFACE, findex, i, totface);
368 for (
int i = 0; i < numCol; i++) {
372 fdata_legacy,
CD_MCOL, findex, i, totface);
391 const int max = mf->
v4 ? 4 : 3;
393 for (
int i = 0; i <
max; i++, loop_normals++, tessloop_normals++) {
401 fdata_legacy, findex,
CD_MDISPS, totface);
403 int tot = mf->
v4 ? 4 : 3;
422 const int side_sq = side * side;
424 for (
int i = 0; i < tot; i++, disps += side_sq, ld++) {
433 size_t(side_sq),
sizeof(
float[3]),
"converted loop mdisps");
435 memcpy(ld->
disps, disps,
size_t(side_sq) *
sizeof(
float[3]));
438 memset(ld->
disps, 0,
size_t(side_sq) *
sizeof(
float[3]));
447 for (
int i = 0; i < fdata_legacy->
totlayer; i++) {
484 int i, j, totloop, faces_num, *polyindex;
490 faces_num = totface_i;
492 int *material_indices =
static_cast<int *
>(
494 if (material_indices ==
nullptr) {
498 bool *sharp_faces =
static_cast<bool *
>(
501 sharp_faces =
static_cast<bool *
>(
510 for (i = 0; i < totface_i; i++, mf++) {
511 totloop += mf->
v4 ? 4 : 3;
528 for (i = 0; i < totedge_i; i++) {
538 for (i = 0; i < totface_i; i++, mf++, poly++) {
541 poly->totloop = mf->
v4 ? 4 : 3;
543 material_indices[i] = mf->
mat_nr;
544 sharp_faces[i] = (mf->
flag & ME_SMOOTH) == 0;
549 ml->e = eh.lookup({mf->v1, mf->v2}); \
568 id, fdata_legacy, totface_i, ldata, mface, totloop, i, poly->loopstart, numTex, numCol);
579 *r_faces_num = faces_num;
580 *r_totloop = totloop;
602 if (mesh.active_color_attribute !=
nullptr) {
607 if (mesh.default_color_attribute !=
nullptr) {
631 int a_num = 0, b_num = 0;
632# define LAYER_CMP(l_a, t_a, l_b, t_b) \
633 ((a_num += CustomData_number_of_layers(l_a, t_a)) == \
634 (b_num += CustomData_number_of_layers(l_b, t_b)))
656 return a_num ?
true : fallback;
665 for (
int i = 0; i < ldata->
totlayer; i++) {
693 if (
UNLIKELY((mesh->totface_legacy != 0) && (mesh->faces_num == 0))) {
707 if (tottex_tessface != tottex_original || totcol_tessface != totcol_original) {
710 add_mface_layers(*mesh, &mesh->fdata_legacy, &mesh->corner_data, mesh->totface_legacy);
719 "%s: warning! Tessellation uvs or vcol data got out of sync, "
720 "had to reset!\n CD_MTFACE: %d != CD_PROP_FLOAT2: %d || CD_MCOL: %d != "
721 "CD_PROP_BYTE_COLOR: "
740 mesh->totface_legacy,
743 mesh->edges_for_write().data(),
800 mesh->totface_legacy,
803 mesh->edges_for_write().data(),
823#define MESH_MLOOPCOL_TO_MCOL(_mloopcol, _mcol) \
825 const MLoopCol *mloopcol__tmp = _mloopcol; \
826 MCol *mcol__tmp = _mcol; \
827 mcol__tmp->b = mloopcol__tmp->r; \
828 mcol__tmp->g = mloopcol__tmp->g; \
829 mcol__tmp->r = mloopcol__tmp->b; \
830 mcol__tmp->a = mloopcol__tmp->a; \
846 const int *polyindices,
847 uint (*loopindices)[4],
863 for (i = 0; i < numUV; i++) {
869 for (findex = 0, pidx = polyindices, lidx = loopindices; findex < num_faces;
870 pidx++, lidx++, findex++, texface++)
872 for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
878 for (i = 0; i < numCol; i++) {
880 fdata_legacy,
CD_MCOL, i, num_faces);
884 for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, mcol++) {
885 for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
896 for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, of++) {
897 for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
909 for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, face_normals++) {
910 for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
916 if (hasLoopTangent) {
921 for (findex = 0, pidx = polyindices, lidx = loopindices; findex < num_faces;
922 pidx++, lidx++, findex++)
924 int nverts = (mface ? mface[findex].
v4 : (*lidx)[3]) ? 4 : 3;
925 for (j = nverts; j--;) {
926 copy_v4_v4(ftangents[findex * 4 + j], ltangents[(*lidx)[j]]);
935 if ((mface->
v3 || nr == 4) && mface->
v3 == mface->
v4) {
939 if ((mface->
v2 || mface->
v4) && mface->
v2 == mface->
v3) {
940 mface->
v3 = mface->
v4;
944 if (mface->
v1 == mface->
v2) {
945 mface->
v2 = mface->
v3;
946 mface->
v3 = mface->
v4;
956 mface->
v1 == mface->
v2 || mface->
v2 == mface->
v3 || mface->
v3 == mface->
v1)
964 mface->
v1 == mface->
v2 || mface->
v2 == mface->
v3 || mface->
v3 == mface->
v4 ||
965 mface->
v4 == mface->
v1 ||
967 mface->
v1 == mface->
v3 || mface->
v2 == mface->
v4)
975 if (mface->
v3 == 0) {
976 static int corner_indices[4] = {1, 2, 0, 3};
978 std::swap(mface->
v1, mface->
v2);
979 std::swap(mface->
v2, mface->
v3);
987 if (mface->
v3 == 0 || mface->
v4 == 0) {
988 static int corner_indices[4] = {2, 3, 0, 1};
990 std::swap(mface->
v1, mface->
v3);
991 std::swap(mface->
v2, mface->
v4);
1006 float (*positions)[3],
1011#define USE_TESSFACE_SPEEDUP
1012#define USE_TESSFACE_QUADS
1015#define TESSFACE_IS_QUAD 1
1021 int *mface_to_poly_map;
1023 int poly_index, mface_index;
1027 const Span<int> corner_verts = mesh.corner_verts();
1028 const int *material_indices =
static_cast<const int *
>(
1030 const bool *sharp_faces =
static_cast<const bool *
>(
1037 size_t(corner_tris_num),
sizeof(*mface_to_poly_map), __func__);
1042 for (poly_index = 0; poly_index < faces_num; poly_index++) {
1043 const uint mp_loopstart =
uint(faces[poly_index].start());
1044 const uint mp_totloop =
uint(faces[poly_index].
size());
1045 uint l1, l2, l3, l4;
1047 if (mp_totloop < 3) {
1051#ifdef USE_TESSFACE_SPEEDUP
1053# define ML_TO_MF(i1, i2, i3) \
1054 mface_to_poly_map[mface_index] = poly_index; \
1055 mf = &mface[mface_index]; \
1056 lidx = lindices[mface_index]; \
1058 l1 = mp_loopstart + i1; \
1059 l2 = mp_loopstart + i2; \
1060 l3 = mp_loopstart + i3; \
1061 mf->v1 = corner_verts[l1]; \
1062 mf->v2 = corner_verts[l2]; \
1063 mf->v3 = corner_verts[l3]; \
1069 mf->mat_nr = material_indices ? material_indices[poly_index] : 0; \
1070 mf->flag = (sharp_faces && sharp_faces[poly_index]) ? 0 : ME_SMOOTH; \
1075# define ML_TO_MF_QUAD() \
1076 mface_to_poly_map[mface_index] = poly_index; \
1077 mf = &mface[mface_index]; \
1078 lidx = lindices[mface_index]; \
1080 l1 = mp_loopstart + 0; \
1081 l2 = mp_loopstart + 1; \
1082 l3 = mp_loopstart + 2; \
1083 l4 = mp_loopstart + 3; \
1084 mf->v1 = corner_verts[l1]; \
1085 mf->v2 = corner_verts[l2]; \
1086 mf->v3 = corner_verts[l3]; \
1087 mf->v4 = corner_verts[l4]; \
1092 mf->mat_nr = material_indices ? material_indices[poly_index] : 0; \
1093 mf->flag = (sharp_faces && sharp_faces[poly_index]) ? 0 : ME_SMOOTH; \
1094 mf->edcode = TESSFACE_IS_QUAD; \
1097 else if (mp_totloop == 3) {
1101 else if (mp_totloop == 4) {
1102# ifdef USE_TESSFACE_QUADS
1114 const float *co_curr, *co_prev;
1118 float axis_mat[3][3];
1119 float(*projverts)[2];
1122 const uint totfilltri = mp_totloop - 2;
1134 co_prev = positions[corner_verts[mp_loopstart + mp_totloop - 1]];
1135 for (j = 0; j < mp_totloop; j++) {
1136 const int vert = corner_verts[mp_loopstart + j];
1137 co_curr = positions[vert];
1148 for (j = 0; j < mp_totloop; j++) {
1149 const int vert = corner_verts[mp_loopstart + j];
1150 mul_v2_m3v3(projverts[j], axis_mat, positions[vert]);
1156 for (j = 0; j < totfilltri; j++) {
1157 uint *tri = tris[j];
1158 lidx = lindices[mface_index];
1160 mface_to_poly_map[mface_index] = poly_index;
1161 mf = &mface[mface_index];
1164 l1 = mp_loopstart + tri[0];
1165 l2 = mp_loopstart + tri[1];
1166 l3 = mp_loopstart + tri[2];
1168 mf->
v1 = corner_verts[l1];
1169 mf->
v2 = corner_verts[l2];
1170 mf->
v3 = corner_verts[l3];
1178 mf->
mat_nr = material_indices ? material_indices[poly_index] : 0;
1194 totface = mface_index;
1199 if (
LIKELY(corner_tris_num != totface)) {
1201 mface_to_poly_map = (
int *)
MEM_reallocN(mface_to_poly_map,
1202 sizeof(*mface_to_poly_map) * size_t(totface));
1225#ifdef USE_TESSFACE_QUADS
1227 for (mface_index = 0; mface_index < totface; mface_index++, mf++) {
1239#undef USE_TESSFACE_SPEEDUP
1240#undef USE_TESSFACE_QUADS
1250 &mesh->fdata_legacy,
1253 reinterpret_cast<float(*)[3]
>(mesh->vert_positions_for_write().data()),
1254 mesh->totface_legacy,
1263 if (mesh->faces_num && mesh->totface_legacy == 0) {
1285 if (std::any_of(polys.
begin(), polys.
end(), [](
const MPoly &poly) {
1286 return !(poly.flag_legacy & ME_SMOOTH);
1290 "sharp_face", AttrDomain::Face);
1292 for (const int i : range) {
1293 sharp_faces.span[i] = !(polys[i].flag_legacy & ME_SMOOTH);
1299 attributes.remove(
"sharp_face");
1312 if (mesh->attributes().contains(
".sculpt_face_set")) {
1315 void *faceset_data =
nullptr;
1317 for (
const int i :
IndexRange(mesh->face_data.totlayer)) {
1319 if (layer.type == CD_SCULPT_FACE_SETS) {
1320 faceset_data = layer.
data;
1321 faceset_sharing_info = layer.sharing_info;
1322 layer.data =
nullptr;
1323 layer.sharing_info =
nullptr;
1328 if (faceset_data !=
nullptr) {
1334 faceset_sharing_info);
1336 if (faceset_sharing_info !=
nullptr) {
1350 if (mesh->attributes().contains(
"face_maps")) {
1353 int *data =
nullptr;
1355 for (
const int i :
IndexRange(mesh->face_data.totlayer)) {
1357 if (layer.type == CD_FACEMAP) {
1358 data =
static_cast<int *
>(layer.data);
1359 sharing_info = layer.sharing_info;
1360 layer.data =
nullptr;
1361 layer.sharing_info =
nullptr;
1371 &mesh->face_data,
CD_PROP_INT32, data, mesh->faces_num,
"face_maps", sharing_info);
1372 if (sharing_info !=
nullptr) {
1377 for (
const int i :
IndexRange(mesh->faces_num)) {
1378 if (data[i] == -1) {
1382 groups.
add(data[i], i);
1386 for (
const auto item : groups.items()) {
1388 ".temp_face_map_" + std::to_string(item.key), bke::AttrDomain::Face);
1390 attribute.
span.fill_indices(item.value.as_span(),
true);
1403 if (object->type !=
OB_MESH) {
1406 Mesh *mesh =
static_cast<Mesh *
>(
object->data);
1409 mesh->attributes_for_write().rename(
".temp_face_map_" + std::to_string(i), face_map->name);
1426 if (mesh->cd_flag & ME_CDFLAG_VERT_BWEIGHT) {
1427 float *weights =
static_cast<float *
>(
1429 for (
const int i :
verts.index_range()) {
1430 weights[i] =
verts[i].bweight_legacy / 255.0f;
1436 const Span<MEdge> edges(mesh->medge, mesh->edges_num);
1437 if (mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
1438 float *weights =
static_cast<float *
>(
1440 for (
const int i : edges.index_range()) {
1441 weights[i] = edges[i].bweight_legacy / 255.0f;
1450 const int elems_num,
1451 const char *new_name)
1454 void *data =
nullptr;
1458 if (layer.type == old_type) {
1460 sharing_info = layer.sharing_info;
1461 layer.data =
nullptr;
1462 layer.sharing_info =
nullptr;
1467 if (data !=
nullptr) {
1469 &custom_data, new_type, data, elems_num, new_name, sharing_info);
1471 if (sharing_info !=
nullptr) {
1478 if (!mesh->attributes().contains(
"bevel_weight_vert")) {
1480 mesh->vert_data, CD_BWEIGHT,
CD_PROP_FLOAT, mesh->verts_num,
"bevel_weight_vert");
1482 if (!mesh->attributes().contains(
"bevel_weight_edge")) {
1484 mesh->edge_data, CD_BWEIGHT,
CD_PROP_FLOAT, mesh->edges_num,
"bevel_weight_edge");
1503 const Span<MEdge> edges(mesh->medge, mesh->edges_num);
1504 if (mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) {
1505 float *creases =
static_cast<float *
>(
1507 for (
const int i : edges.index_range()) {
1508 creases[i] = edges[i].crease_legacy / 255.0f;
1515 if (!mesh->attributes().contains(
"crease_vert")) {
1517 mesh->vert_data, CD_CREASE,
CD_PROP_FLOAT, mesh->verts_num,
"crease_vert");
1519 if (!mesh->attributes().contains(
"crease_edge")) {
1521 mesh->edge_data, CD_CREASE,
CD_PROP_FLOAT, mesh->edges_num,
"crease_edge");
1538 const Span<MEdge> edges(mesh->medge, mesh->edges_num);
1540 if (attributes.contains(
"sharp_edge")) {
1543 if (std::any_of(edges.begin(), edges.end(), [](
const MEdge &edge) {
1544 return edge.flag_legacy & ME_SHARP;
1548 "sharp_edge", AttrDomain::Edge);
1549 threading::parallel_for(edges.index_range(), 4096, [&](
const IndexRange range) {
1550 for (const int i : range) {
1551 sharp_edges.span[i] = edges[i].flag_legacy & ME_SHARP;
1573 if (attributes.contains(
".uv_seam")) {
1576 if (std::any_of(edges.begin(), edges.end(), [](
const MEdge &edge) {
1577 return edge.flag_legacy & ME_SEAM;
1581 ".uv_seam", AttrDomain::Edge);
1582 threading::parallel_for(edges.index_range(), 4096, [&](
const IndexRange range) {
1583 for (const int i : range) {
1584 uv_seams.span[i] = edges[i].flag_legacy & ME_SEAM;
1602 if (!mesh->mvert || attributes.contains(
".hide_vert") || attributes.contains(
".hide_edge") ||
1603 attributes.contains(
".hide_poly"))
1608 if (std::any_of(
verts.begin(),
verts.end(), [](
const MVert &vert) {
1609 return vert.flag_legacy & ME_HIDE;
1613 ".hide_vert", AttrDomain::Point);
1614 threading::parallel_for(
verts.index_range(), 4096, [&](
IndexRange range) {
1615 for (const int i : range) {
1616 hide_vert.span[i] = verts[i].flag_legacy & ME_HIDE;
1623 const Span<MEdge> edges(mesh->medge, mesh->edges_num);
1624 if (std::any_of(edges.begin(), edges.end(), [](
const MEdge &edge) {
1625 return edge.flag_legacy & ME_HIDE;
1629 ".hide_edge", AttrDomain::Edge);
1630 threading::parallel_for(edges.index_range(), 4096, [&](
IndexRange range) {
1631 for (const int i : range) {
1632 hide_edge.span[i] = edges[i].flag_legacy & ME_HIDE;
1642 if (std::any_of(polys.begin(), polys.end(), [](
const MPoly &poly) {
1643 return poly.flag_legacy & ME_HIDE;
1647 ".hide_poly", AttrDomain::Face);
1648 threading::parallel_for(polys.index_range(), 4096, [&](
IndexRange range) {
1649 for (const int i : range) {
1650 hide_poly.span[i] = polys[i].flag_legacy & ME_HIDE;
1668 if (!
CustomData_has_layer(&mesh->face_data, CD_MPOLY) || attributes.contains(
"material_index")) {
1675 polys.
begin(), polys.
end(), [](
const MPoly &poly) { return poly.mat_nr_legacy != 0; }))
1678 "material_index", AttrDomain::Face);
1680 for (const int i : range) {
1681 material_indices.span[i] = polys[i].mat_nr_legacy;
1684 material_indices.
finish();
1709 const int active_name_i = uv_names.
as_span().first_index_try(
1711 const int default_name_i = uv_names.
as_span().first_index_try(
1715 const MLoopUV *mloopuv =
static_cast<const MLoopUV *
>(
1717 const uint32_t needed_boolean_attributes = threading::parallel_reduce(
1722 for (const int i : range) {
1723 init |= mloopuv[i].flag;
1731 bool *vert_selection =
nullptr;
1732 bool *edge_selection =
nullptr;
1733 bool *pin =
nullptr;
1734 if (needed_boolean_attributes & MLOOPUV_VERTSEL) {
1735 vert_selection =
static_cast<bool *
>(
1738 if (needed_boolean_attributes & MLOOPUV_EDGESEL) {
1739 edge_selection =
static_cast<bool *
>(
1742 if (needed_boolean_attributes & MLOOPUV_PINNED) {
1743 pin =
static_cast<bool *
>(
MEM_malloc_arrayN(mesh->corners_num,
sizeof(
bool), __func__));
1747 for (const int i : range) {
1748 coords[i] = mloopuv[i].uv;
1750 if (vert_selection) {
1751 for (
const int i :
range) {
1752 vert_selection[i] = mloopuv[i].flag & MLOOPUV_VERTSEL;
1755 if (edge_selection) {
1756 for (
const int i :
range) {
1757 edge_selection[i] = mloopuv[i].flag & MLOOPUV_EDGESEL;
1761 for (
const int i :
range) {
1762 pin[i] = mloopuv[i].flag & MLOOPUV_PINNED;
1771 uv_names[i] = new_name;
1774 &mesh->corner_data,
CD_PROP_FLOAT2, coords, mesh->corners_num, new_name,
nullptr);
1776 if (vert_selection) {
1785 if (edge_selection) {
1804 if (active_name_i != -1) {
1809 uv_names[active_name_i]));
1811 if (default_name_i != -1) {
1816 uv_names[default_name_i]));
1830 if (!mesh->mvert || attributes.contains(
".select_vert") || attributes.contains(
".select_edge") ||
1831 attributes.contains(
".select_poly"))
1838 verts.begin(),
verts.end(), [](
const MVert &vert) { return vert.flag_legacy & SELECT; }))
1841 ".select_vert", AttrDomain::Point);
1842 threading::parallel_for(
verts.index_range(), 4096, [&](
IndexRange range) {
1843 for (const int i : range) {
1844 select_vert.span[i] = verts[i].flag_legacy & SELECT;
1851 const Span<MEdge> edges(mesh->medge, mesh->edges_num);
1852 if (std::any_of(edges.begin(), edges.end(), [](
const MEdge &edge) {
1853 return edge.flag_legacy & SELECT;
1857 ".select_edge", AttrDomain::Edge);
1858 threading::parallel_for(edges.index_range(), 4096, [&](
IndexRange range) {
1859 for (const int i : range) {
1860 select_edge.span[i] = edges[i].flag_legacy & SELECT;
1870 if (std::any_of(polys.begin(), polys.end(), [](
const MPoly &poly) {
1871 return poly.flag_legacy & ME_FACE_SEL;
1875 ".select_poly", AttrDomain::Face);
1876 threading::parallel_for(polys.index_range(), 4096, [&](
IndexRange range) {
1877 for (const int i : range) {
1878 select_poly.span[i] = polys[i].flag_legacy & ME_FACE_SEL;
1895 const MVert *mvert =
static_cast<const MVert *
>(
1906 threading::parallel_for(
verts.index_range(), 2048, [&](
IndexRange range) {
1907 for (const int i : range) {
1908 positions[i] = verts[i].co_legacy;
1913 mesh->mvert =
nullptr;
1926 const MEdge *medge =
static_cast<const MEdge *
>(
1932 const Span<MEdge> legacy_edges(medge, mesh->edges_num);
1938 for (const int i : range) {
1939 edges[i] = int2(legacy_edges[i].v1, legacy_edges[i].v2);
1944 mesh->medge =
nullptr;
1960 if (!mesh->active_color_attribute) {
1961 for (
const int i :
IndexRange(data.totlayer)) {
1962 if (data.layers[i].flag & CD_FLAG_COLOR_ACTIVE) {
1963 mesh->active_color_attribute =
BLI_strdup(data.layers[i].name);
1969 if (!mesh->active_color_attribute) {
1972 mesh->active_color_attribute =
BLI_strdup(data.layers[i].name);
1975 if (!mesh->active_color_attribute) {
1978 mesh->active_color_attribute =
BLI_strdup(data.layers[i].name);
1983 if (!mesh->default_color_attribute) {
1984 for (
const int i :
IndexRange(data.totlayer)) {
1985 if (data.layers[i].flag & CD_FLAG_COLOR_RENDER) {
1986 mesh->default_color_attribute =
BLI_strdup(data.layers[i].name);
1992 if (!mesh->default_color_attribute) {
1995 mesh->default_color_attribute =
BLI_strdup(data.layers[i].name);
1998 if (!mesh->default_color_attribute) {
2001 mesh->default_color_attribute =
BLI_strdup(data.layers[i].name);
2006 active_from_flags(mesh->vert_data);
2007 active_from_flags(mesh->corner_data);
2008 active_from_indices(mesh->vert_data);
2009 active_from_indices(mesh->corner_data);
2011 default_from_flags(mesh->vert_data);
2012 default_from_flags(mesh->corner_data);
2013 default_from_indices(mesh->vert_data);
2014 default_from_indices(mesh->corner_data);
2042 threading::parallel_for(loops.index_range(), 2048, [&](
IndexRange range) {
2043 for (const int i : range) {
2044 corner_verts[i] = loops[i].v;
2045 corner_edges[i] = loops[i].e;
2061 if (polys[i].loopstart > polys[i + 1].loopstart) {
2071 if (mesh->face_offset_indices) {
2083 offsets[i] = polys[i].loopstart;
2089 array_utils::fill_index_range<int>(orig_indices);
2090 std::stable_sort(orig_indices.
begin(), orig_indices.
end(), [polys](
const int a,
const int b) {
2091 return polys[a].loopstart < polys[b].loopstart;
2100 offsets[i] = offset;
2101 offset += polys[orig_indices[i]].totloop;
2105 for (const int i : range) {
2106 CustomData_copy_data(&old_poly_data, &mesh->face_data, orig_indices[i], i, 1);
2127 &bmain, owner_library,
DATA_(
"Auto Smooth"),
"GeometryNodeTree");
2128 if (!group->geometry_node_asset_traits) {
2129 group->geometry_node_asset_traits = MEM_cnew<GeometryNodeAssetTraits>(__func__);
2133 group->tree_interface.add_socket(
2135 group->tree_interface.add_socket(
2140 angle_data.
min = 0.0f;
2145 group_output->
locx = 480.0f;
2146 group_output->
locy = -100.0f;
2148 group_input_angle->
locx = -420.0f;
2149 group_input_angle->
locy = -300.0f;
2151 if (!
STREQ(socket->identifier,
"Socket_2")) {
2156 group_input_mesh->
locx = -60.0f;
2157 group_input_mesh->
locy = -100.0f;
2159 if (!
STREQ(socket->identifier,
"Socket_1")) {
2163 bNode *shade_smooth_edge =
node_add_node(
nullptr, group,
"GeometryNodeSetShadeSmooth");
2165 shade_smooth_edge->
locx = 120.0f;
2166 shade_smooth_edge->
locy = -100.0f;
2167 bNode *shade_smooth_face =
node_add_node(
nullptr, group,
"GeometryNodeSetShadeSmooth");
2169 shade_smooth_face->
locx = 300.0f;
2170 shade_smooth_face->
locy = -100.0f;
2172 edge_angle->
locx = -420.0f;
2173 edge_angle->
locy = -220.0f;
2175 edge_smooth->
locx = -60.0f;
2176 edge_smooth->
locy = -160.0f;
2178 face_smooth->
locx = -240.0f;
2179 face_smooth->
locy = -340.0f;
2182 boolean_and->
locx = -60.0f;
2183 boolean_and->
locy = -220.0f;
2187 less_than_or_equal->
locx = -240.0f;
2188 less_than_or_equal->
locy = -180.0f;
2248 for (
const bNode *node : nodes) {
2253 result.add_new(socket);
2266 if (nodes.size() != 10) {
2269 if (!group.geometry_node_asset_traits) {
2275 const std::array<StringRef, 10> idnames({
"NodeGroupOutput",
2278 "GeometryNodeSetShadeSmooth",
2279 "GeometryNodeSetShadeSmooth",
2280 "GeometryNodeInputMeshEdgeAngle",
2281 "GeometryNodeInputEdgeSmooth",
2282 "GeometryNodeInputShadeSmooth",
2283 "FunctionNodeBooleanMath",
2284 "FunctionNodeCompare"});
2285 for (
const int i : nodes.index_range()) {
2286 if (nodes[i]->idname != idnames[i]) {
2293 if (
static_cast<bNodeSocket *
>(nodes[4]->inputs.last)
2313 const std::array<int, 9> link_from_socket_indices({16, 15, 3, 36, 19, 5, 18, 11, 22});
2314 const std::array<int, 9> link_to_socket_indices({23, 0, 24, 20, 21, 8, 9, 12, 10});
2318 if (socket_indices.index_of(link->fromsock) != link_from_socket_indices[i]) {
2321 if (socket_indices.index_of(link->tosock) != link_to_socket_indices[i]) {
2337 md->node_group = get_node_group(
object.
id.
lib);
2344 ui_data->soft_min = 0.0f;
2345 ui_data->soft_max =
DEG2RADF(180.0f);
2351 return &md->modifier;
2362 Map<Library *, bNodeTree *> group_by_library;
2363 const auto add_node_group = [&](
Library *owner_library) {
2364 if (
bNodeTree **group = group_by_library.lookup_ptr(owner_library)) {
2370 if (existing_group->id.lib != owner_library) {
2373 if (is_auto_smooth_node_tree(*existing_group)) {
2374 group_by_library.add_new(owner_library, existing_group);
2375 return existing_group;
2378 bNodeTree *new_group = add_auto_smooth_node_tree(bmain, owner_library);
2381 group_by_library.add_new(owner_library, new_group);
2386 if (object->type !=
OB_MESH) {
2389 Mesh *mesh =
static_cast<Mesh *
>(
object->data);
2390 const float angle = mesh->smoothresh_legacy;
2399 if (has_custom_normals) {
2408 has_custom_normals =
true;
2413 has_custom_normals =
true;
2419 ModifierData *new_md = create_auto_smooth_modifier(*
object, add_node_group, angle);
2429 has_custom_normals =
true;
2438 if (has_custom_normals) {
2443 ModifierData *new_md = create_auto_smooth_modifier(*
object, add_node_group, angle);
2458 mesh->flag &= ~ME_AUTOSMOOTH_LEGACY;
2466 bool changed =
false;
2468 if (
StringRef(layer.name) ==
".sculpt_mask") {
2469 layer.type = CD_PAINT_MASK;
2470 layer.name[0] =
'\0';
2480 vert_layers.
begin(),
2487 if (mesh.attributes().contains(
".sculpt_mask")) {
2490 void *data =
nullptr;
2492 for (
const int i :
IndexRange(mesh.vert_data.totlayer)) {
2494 if (layer.type == CD_PAINT_MASK) {
2496 sharing_info = layer.sharing_info;
2497 layer.data =
nullptr;
2498 layer.sharing_info =
nullptr;
2503 if (data !=
nullptr) {
2505 &mesh.vert_data,
CD_PROP_FLOAT, data, mesh.verts_num,
".sculpt_mask", sharing_info);
2507 if (sharing_info !=
nullptr) {
2519 const int nulegacy_faces = mesh->totface_legacy;
2523 &mesh->fdata_legacy,
CD_MFACE, mesh->totface_legacy);
2525 MFace *mf = legacy_faces;
2526 for (
int i = 0; i < nulegacy_faces; i++, mf++) {
2539 const int numEdges = eh.
size();
2556 mesh->edge_data = edgeData;
2557 mesh->edges_num = numEdges;
std::string BKE_attribute_calc_unique_name(const AttributeOwner &owner, const blender::StringRef name)
const char * BKE_uv_map_pin_name_get(const char *uv_map_name, char *buffer)
const char * BKE_uv_map_vert_select_name_get(const char *uv_map_name, char *buffer)
const char * BKE_uv_map_edge_select_name_get(const char *uv_map_name, char *buffer)
CustomData interface, see also DNA_customdata_types.h.
void * CustomData_get_n_for_write(CustomData *data, eCustomDataType type, int index, int n, int totelem)
void * CustomData_get_layer_named_for_write(CustomData *data, eCustomDataType type, blender::StringRef name, int totelem)
int CustomData_get_clone_layer(const CustomData *data, eCustomDataType type)
const void * CustomData_get_layer_n(const CustomData *data, eCustomDataType type, int n)
int CustomData_get_named_layer(const CustomData *data, eCustomDataType type, blender::StringRef name)
bool CustomData_free_layer_named(CustomData *data, blender::StringRef name, const int totelem)
void CustomData_set_layer_render_index(CustomData *data, eCustomDataType type, int n)
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
void CustomData_external_read(CustomData *data, ID *id, eCustomDataMask mask, int totelem)
const void * CustomData_get_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
void * CustomData_add_layer_named(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem, blender::StringRef name)
void CustomData_set_layer_render(CustomData *data, eCustomDataType type, int n)
int CustomData_get_stencil_layer(const CustomData *data, eCustomDataType type)
void CustomData_reset(CustomData *data)
int CustomData_get_named_layer_index(const CustomData *data, eCustomDataType type, blender::StringRef name)
bool CustomData_has_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
const char * CustomData_get_layer_name(const CustomData *data, eCustomDataType type, int n)
bool CustomData_free_layer(CustomData *data, eCustomDataType type, int totelem, int index)
void CustomData_free(CustomData *data, int totelem)
void CustomData_set_layer_clone(CustomData *data, eCustomDataType type, int n)
void CustomData_free_layers(CustomData *data, eCustomDataType type, int totelem)
void CustomData_external_add(CustomData *data, ID *id, eCustomDataType type, int totelem, const char *filepath)
void CustomData_set_layer_active_index(CustomData *data, eCustomDataType type, int n)
const char * CustomData_get_render_layer_name(const CustomData *data, eCustomDataType type)
void CustomData_init_layout_from(const CustomData *source, CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
int CustomData_get_active_layer(const CustomData *data, eCustomDataType type)
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
void CustomData_free_elem(CustomData *data, int index, int count)
const void * CustomData_add_layer_with_data(CustomData *data, eCustomDataType type, void *layer_data, int totelem, const blender::ImplicitSharingInfo *sharing_info)
void CustomData_copy_data(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
int CustomData_get_active_layer_index(const CustomData *data, eCustomDataType type)
const char * CustomData_get_active_layer_name(const CustomData *data, eCustomDataType type)
int CustomData_get_render_layer(const CustomData *data, eCustomDataType type)
const void * CustomData_add_layer_named_with_data(CustomData *data, eCustomDataType type, void *layer_data, int totelem, blender::StringRef name, const blender::ImplicitSharingInfo *sharing_info)
int CustomData_number_of_layers(const CustomData *data, eCustomDataType type)
bool CustomData_external_test(CustomData *data, eCustomDataType type)
int CustomData_get_render_layer_index(const CustomData *data, eCustomDataType type)
void CustomData_set_layer_active(CustomData *data, eCustomDataType type, int n)
void * CustomData_get_layer_n_for_write(CustomData *data, eCustomDataType type, int n, int totelem)
const CustomData_MeshMasks CD_MASK_MESH
void * CustomData_get_for_write(CustomData *data, int index, eCustomDataType type, int totelem)
void CustomData_set_layer_stencil(CustomData *data, eCustomDataType type, int n)
void CustomData_swap_corners(CustomData *data, int index, const int *corner_indices)
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
IDPropertyUIData * IDP_ui_data_ensure(IDProperty *prop)
void BKE_mesh_tessface_clear(Mesh *mesh)
void BKE_mesh_face_offsets_ensure_alloc(Mesh *mesh)
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md)
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
ModifierData * BKE_modifier_new(int type)
int multires_mdisp_corners(const MDisps *s)
void BKE_ntree_update_main_tree(Main *bmain, bNodeTree *ntree, NodeTreeUpdateExtraParams *params)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3])
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void normal_float_to_short_v3(short out[3], const float in[3])
MINLINE void normal_short_to_float_v3(float out[3], const short in[3])
MINLINE void zero_v3(float r[3])
MINLINE float normalize_v3(float n[3])
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
#define BLI_MEMARENA_STD_BUFSIZE
void void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
void BLI_polyfill_calc_arena(const float(*coords)[2], unsigned int coords_num, int coords_sign, unsigned int(*r_tris)[3], struct MemArena *arena)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
#define STRNCPY(dst, src)
#define MAX_CUSTOMDATA_LAYER_NAME
@ MOD_BEVEL_HARDEN_NORMALS
@ eModifierType_NormalEdit
@ eModifierType_WeightedNormal
@ eSubsurfModifierFlag_UseCustomNormals
@ MOD_WEIGHTEDNORMAL_KEEP_SHARP
@ NODE_INTERFACE_SOCKET_OUTPUT
@ NODE_INTERFACE_SOCKET_INPUT
@ GEO_NODE_ASSET_MODIFIER
@ NODE_COMPARE_LESS_EQUAL
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static AttributeOwner from_id(ID *id)
Span< T > as_span() const
IndexRange index_range() const
void remove_user_and_delete_if_last() const
constexpr IndexRange drop_back(int64_t n) const
bool add(const Key &key, const Value &value)
void add(const Key &key, const Value &value)
constexpr T * end() const
constexpr T * begin() const
constexpr void copy_from(Span< T > values) const
constexpr int64_t size() const
constexpr const T * end() const
constexpr IndexRange index_range() const
constexpr const T * begin() const
void reserve(const int64_t n)
void add_new(const Key &key)
Span< Key > as_span() const
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void *(* MEM_mallocN)(size_t len, const char *str)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh)
void BKE_mesh_legacy_edge_crease_to_layers(Mesh *mesh)
void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
void BKE_mesh_legacy_sharp_faces_from_flags(Mesh *mesh)
void BKE_mesh_legacy_convert_edges_to_generic(Mesh *mesh)
void BKE_mesh_legacy_bevel_weight_to_generic(Mesh *mesh)
void BKE_mesh_legacy_face_map_to_generic(Main *bmain)
static void bm_corners_to_loops_ex(ID *id, CustomData *fdata_legacy, const int totface, CustomData *ldata, MFace *mface, int totloop, int findex, int loopstart, int numTex, int numCol)
static void update_active_fdata_layers(Mesh &mesh, CustomData *fdata_legacy, CustomData *ldata)
void BKE_mesh_strip_loose_faces(Mesh *mesh)
void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh)
static void replace_custom_data_layer_with_named(CustomData &custom_data, const eCustomDataType old_type, const eCustomDataType new_type, const int elems_num, const char *new_name)
void BKE_mesh_tessface_calc(Mesh *mesh)
static int mesh_tessface_calc(Mesh &mesh, CustomData *fdata_legacy, CustomData *ldata, CustomData *pdata, float(*positions)[3], int totface, int totloop, int faces_num)
static int vergedgesort(const void *v1, const void *v2)
void BKE_mesh_legacy_convert_loops_to_corners(Mesh *mesh)
static void mesh_ensure_tessellation_customdata(Mesh *mesh)
static void mesh_calc_edges_mdata(const MVert *, const MFace *allface, MLoop *allloop, const MPoly *allpoly, int, int totface, int, int faces_num, MEdge **r_medge, int *r_totedge)
static bool check_matching_legacy_layer_counts(CustomData *fdata_legacy, CustomData *ldata, bool fallback)
#define LAYER_CMP(l_a, t_a, l_b, t_b)
void BKE_mesh_calc_edges_tessface(Mesh *mesh)
static bool poly_loops_orders_match(const Span< MPoly > polys)
#define MESH_MLOOPCOL_FROM_MCOL(_mloopcol, _mcol)
void BKE_mesh_legacy_convert_verts_to_positions(Mesh *mesh)
void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh)
void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
#define MESH_MLOOPCOL_TO_MCOL(_mloopcol, _mcol)
void BKE_mesh_legacy_bevel_weight_to_layers(Mesh *mesh)
void BKE_mesh_legacy_crease_to_generic(Mesh *mesh)
void BKE_mesh_calc_edges_legacy(Mesh *mesh)
static void add_mface_layers(Mesh &mesh, CustomData *fdata_legacy, CustomData *ldata, int total)
void BKE_mesh_legacy_convert_flags_to_selection_layers(Mesh *mesh)
static void CustomData_to_bmeshpoly(CustomData *fdata_legacy, CustomData *ldata, int totloop)
static void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata_legacy, CustomData *corner_data)
void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh)
#define ML_TO_MF(i1, i2, i3)
static void move_face_map_data_to_attributes(Mesh *mesh)
static void mesh_loops_to_tessdata(CustomData *fdata_legacy, CustomData *corner_data, MFace *mface, const int *polyindices, uint(*loopindices)[4], const int num_faces)
int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata_legacy, int mfindex, int nr)
void BKE_mesh_legacy_uv_seam_from_flags(Mesh *mesh)
void BKE_mesh_legacy_convert_mpoly_to_material_indices(Mesh *mesh)
void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh)
static void to_edgesort(EdgeSort *ed, uint v1, uint v2, char is_loose, short is_draw)
void BKE_mesh_tessface_ensure(Mesh *mesh)
void BKE_mesh_legacy_sharp_edges_from_flags(Mesh *mesh)
static void convert_mfaces_to_mpolys(ID *id, CustomData *fdata_legacy, CustomData *ldata, CustomData *pdata, int totedge_i, int totface_i, int totloop_i, int faces_num_i, blender::int2 *edges, MFace *mface, int *r_totloop, int *r_faces_num)
void BKE_mesh_legacy_attribute_flags_to_strings(Mesh *mesh)
void BKE_mesh_do_versions_cd_flag_init(Mesh *mesh)
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_INT, set its name and value.
std::unique_ptr< IDProperty, IDPropertyDeleter > create_group(StringRefNull prop_name, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_GROUP.
static bNodeTree * add_auto_smooth_node_tree(Main &bmain, Library *owner_library)
void mesh_sculpt_mask_to_generic(Mesh &mesh)
bNodeTree * node_tree_add_in_lib(Main *bmain, Library *owner_library, const char *name, const char *idname)
bNodeLink * node_add_link(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
static bool is_auto_smooth_node_tree(const bNodeTree &group)
bNode * node_add_node(const bContext *C, bNodeTree *ntree, const char *idname)
void mesh_sculpt_mask_to_legacy(MutableSpan< CustomDataLayer > vert_layers)
bool node_set_selected(bNode *node, bool select)
static VectorSet< const bNodeSocket * > build_socket_indices(const Span< const bNode * > nodes)
static ModifierData * create_auto_smooth_modifier(Object &object, const FunctionRef< bNodeTree *(Library *owner_library)> get_node_group, const float angle)
bNodeSocket * node_find_socket(bNode *node, eNodeSocketInOut in_out, StringRef identifier)
CustomDataExternal * external
struct bNodeTree * node_group
MutableVArraySpan< T > span
static DynamicLibrary lib