11#define DNA_DEPRECATED_ALLOW
84 if (x1->
v1 > x2->
v1) {
87 if (x1->
v1 < x2->
v1) {
90 if (x1->
v2 > x2->
v2) {
93 if (x1->
v2 < x2->
v2) {
103 const MFace *allface,
105 const MPoly *allpoly,
118 uint totedge_final = 0;
123 for (a = totface, mface = allface; a > 0; a--, mface++) {
127 else if (mface->
v3) {
143 for (a = totface, mface = allface; a > 0; a--, mface++) {
150 else if (mface->
v3) {
159 for (a = totedge, ed = edsort; a > 1; a--, ed++) {
161 if (ed->
v1 != (ed + 1)->v1 || ed->
v2 != (ed + 1)->v2) {
169 for (a = totedge, edge = edges, ed = edsort; a > 1; a--, ed++) {
171 if (ed->
v1 != (ed + 1)->v1 || ed->
v2 != (ed + 1)->v2) {
177 if (ed->
v1 + 1 != ed->
v2) {
178 std::swap(edge->v1, edge->v2);
184 (ed + 1)->is_draw |= ed->
is_draw;
195 hash.reserve(totedge_final);
196 for (edge_index = 0, edge = edges; edge_index < totedge_final; edge_index++, edge++) {
197 hash.add({edge->v1, edge->v2}, edge_index);
201 for (a = 0; a < faces_num; a++, mpoly++) {
203 int i = mpoly->totloop;
205 ml_next = allloop + mpoly->loopstart;
206 ml = &ml_next[
i - 1];
209 ml->e =
hash.lookup({ml->v, ml_next->v});
217 *r_totedge = totedge_final;
232 static_cast<MLoop *
>(
249 &mesh->
edge_data, CD_MEDGE, edges, totedge,
nullptr);
252 mesh->tag_topology_changed();
261 MFace *mfaces = mesh->mface;
266 memcpy(&mfaces[
b], f,
sizeof(mfaces[
b]));
298 for (
const MVert &vert :
verts) {
299 if (vert.bweight_legacy != 0) {
300 mesh->cd_flag |= ME_CDFLAG_VERT_BWEIGHT;
305 for (
const MEdge &edge : edges) {
306 if (edge.bweight_legacy != 0) {
307 mesh->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT;
308 if (mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) {
312 if (edge.crease_legacy != 0) {
313 mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE;
314 if (mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
327#define MESH_MLOOPCOL_FROM_MCOL(_mloopcol, _mcol) \
329 MLoopCol *mloopcol__tmp = _mloopcol; \
330 const MCol *mcol__tmp = _mcol; \
331 mloopcol__tmp->r = mcol__tmp->b; \
332 mloopcol__tmp->g = mcol__tmp->g; \
333 mloopcol__tmp->b = mcol__tmp->r; \
334 mloopcol__tmp->a = mcol__tmp->a; \
349 MFace *mf = mface + findex;
351 for (
int i = 0;
i < numTex;
i++) {
370 for (
int i = 0;
i < numCol;
i++) {
374 fdata_legacy,
CD_MCOL, findex,
i, totface);
393 const int max = mf->
v4 ? 4 : 3;
395 for (
int i = 0;
i <
max;
i++, loop_normals++, tessloop_normals++) {
403 fdata_legacy, findex,
CD_MDISPS, totface);
405 int tot = mf->
v4 ? 4 : 3;
423 const int side = int(
sqrtf(
float(fd->
totdisp / corners)));
424 const int side_sq = side * side;
426 for (
int i = 0;
i < tot;
i++, disps += side_sq, ld++) {
436 memcpy(ld->
disps, disps,
size_t(side_sq) *
sizeof(
float[3]));
439 memset(ld->
disps, 0,
size_t(side_sq) *
sizeof(
float[3]));
485 int i, j, totloop, faces_num, *polyindex;
491 faces_num = totface_i;
493 int *material_indices =
static_cast<int *
>(
495 if (material_indices ==
nullptr) {
499 bool *sharp_faces =
static_cast<bool *
>(
502 sharp_faces =
static_cast<bool *
>(
511 for (
i = 0;
i < totface_i;
i++, mf++) {
512 totloop += mf->
v4 ? 4 : 3;
529 for (
i = 0;
i < totedge_i;
i++) {
539 for (
i = 0;
i < totface_i;
i++, mf++, poly++) {
542 poly->totloop = mf->
v4 ? 4 : 3;
544 material_indices[
i] = mf->
mat_nr;
545 sharp_faces[
i] = (mf->
flag & ME_SMOOTH) == 0;
550 ml->e = eh.lookup({mf->v1, mf->v2}); \
569 id, fdata_legacy, totface_i, ldata, mface, totloop,
i, poly->loopstart, numTex, numCol);
580 *r_faces_num = faces_num;
581 *r_totloop = totloop;
638 int a_num = 0, b_num = 0;
639# define LAYER_CMP(l_a, t_a, l_b, t_b) \
640 ((a_num += CustomData_number_of_layers(l_a, t_a)) == \
641 (b_num += CustomData_number_of_layers(l_b, t_b)))
660 return a_num ?
true : fallback;
707 if (tottex_tessface != tottex_original || totcol_tessface != totcol_original) {
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: "
743 mesh->edges_for_write().data(),
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],
862 for (
i = 0;
i < numUV;
i++) {
868 for (findex = 0, pidx = polyindices, lidx = loopindices; findex < num_faces;
869 pidx++, lidx++, findex++, texface++)
871 for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
877 for (
i = 0;
i < numCol;
i++) {
879 fdata_legacy,
CD_MCOL,
i, num_faces);
883 for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, mcol++) {
884 for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
895 for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, of++) {
896 for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
908 for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, face_normals++) {
909 for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
919 if ((mface->
v3 || nr == 4) && mface->
v3 == mface->
v4) {
923 if ((mface->
v2 || mface->
v4) && mface->
v2 == mface->
v3) {
924 mface->
v3 = mface->
v4;
928 if (mface->
v1 == mface->
v2) {
929 mface->
v2 = mface->
v3;
930 mface->
v3 = mface->
v4;
940 mface->
v1 == mface->
v2 || mface->
v2 == mface->
v3 || mface->
v3 == mface->
v1)
948 mface->
v1 == mface->
v2 || mface->
v2 == mface->
v3 || mface->
v3 == mface->
v4 ||
949 mface->
v4 == mface->
v1 ||
951 mface->
v1 == mface->
v3 || mface->
v2 == mface->
v4)
959 if (mface->
v3 == 0) {
960 static int corner_indices[4] = {1, 2, 0, 3};
962 std::swap(mface->
v1, mface->
v2);
963 std::swap(mface->
v2, mface->
v3);
971 if (mface->
v3 == 0 || mface->
v4 == 0) {
972 static int corner_indices[4] = {2, 3, 0, 1};
974 std::swap(mface->
v1, mface->
v3);
975 std::swap(mface->
v2, mface->
v4);
990 float (*positions)[3],
995#define USE_TESSFACE_SPEEDUP
996#define USE_TESSFACE_QUADS
999#define TESSFACE_IS_QUAD 1
1005 int *mface_to_poly_map;
1007 int poly_index, mface_index;
1011 const Span<int> corner_verts = mesh.corner_verts();
1012 const int *material_indices =
static_cast<const int *
>(
1014 const bool *sharp_faces =
static_cast<const bool *
>(
1025 for (poly_index = 0; poly_index < faces_num; poly_index++) {
1028 uint l1, l2, l3, l4;
1030 if (mp_totloop < 3) {
1034#ifdef USE_TESSFACE_SPEEDUP
1036# define ML_TO_MF(i1, i2, i3) \
1037 mface_to_poly_map[mface_index] = poly_index; \
1038 mf = &mface[mface_index]; \
1039 lidx = lindices[mface_index]; \
1041 l1 = mp_loopstart + i1; \
1042 l2 = mp_loopstart + i2; \
1043 l3 = mp_loopstart + i3; \
1044 mf->v1 = corner_verts[l1]; \
1045 mf->v2 = corner_verts[l2]; \
1046 mf->v3 = corner_verts[l3]; \
1052 mf->mat_nr = material_indices ? material_indices[poly_index] : 0; \
1053 mf->flag = (sharp_faces && sharp_faces[poly_index]) ? 0 : ME_SMOOTH; \
1058# define ML_TO_MF_QUAD() \
1059 mface_to_poly_map[mface_index] = poly_index; \
1060 mf = &mface[mface_index]; \
1061 lidx = lindices[mface_index]; \
1063 l1 = mp_loopstart + 0; \
1064 l2 = mp_loopstart + 1; \
1065 l3 = mp_loopstart + 2; \
1066 l4 = mp_loopstart + 3; \
1067 mf->v1 = corner_verts[l1]; \
1068 mf->v2 = corner_verts[l2]; \
1069 mf->v3 = corner_verts[l3]; \
1070 mf->v4 = corner_verts[l4]; \
1075 mf->mat_nr = material_indices ? material_indices[poly_index] : 0; \
1076 mf->flag = (sharp_faces && sharp_faces[poly_index]) ? 0 : ME_SMOOTH; \
1077 mf->edcode = TESSFACE_IS_QUAD; \
1080 else if (mp_totloop == 3) {
1084 else if (mp_totloop == 4) {
1085# ifdef USE_TESSFACE_QUADS
1097 const float *co_curr, *co_prev;
1101 float axis_mat[3][3];
1102 float (*projverts)[2];
1105 const uint totfilltri = mp_totloop - 2;
1117 co_prev = positions[corner_verts[mp_loopstart + mp_totloop - 1]];
1118 for (j = 0; j < mp_totloop; j++) {
1119 const int vert = corner_verts[mp_loopstart + j];
1120 co_curr = positions[vert];
1131 for (j = 0; j < mp_totloop; j++) {
1132 const int vert = corner_verts[mp_loopstart + j];
1133 mul_v2_m3v3(projverts[j], axis_mat, positions[vert]);
1139 for (j = 0; j < totfilltri; j++) {
1140 uint *tri = tris[j];
1141 lidx = lindices[mface_index];
1143 mface_to_poly_map[mface_index] = poly_index;
1144 mf = &mface[mface_index];
1147 l1 = mp_loopstart + tri[0];
1148 l2 = mp_loopstart + tri[1];
1149 l3 = mp_loopstart + tri[2];
1151 mf->
v1 = corner_verts[l1];
1152 mf->
v2 = corner_verts[l2];
1153 mf->
v3 = corner_verts[l3];
1161 mf->
mat_nr = material_indices ? material_indices[poly_index] : 0;
1177 totface = mface_index;
1182 if (
LIKELY(corner_tris_num != totface)) {
1184 mface_to_poly_map = (
int *)
MEM_reallocN(mface_to_poly_map,
1185 sizeof(*mface_to_poly_map) *
size_t(totface));
1208#ifdef USE_TESSFACE_QUADS
1210 for (mface_index = 0; mface_index < totface; mface_index++, mf++) {
1222#undef USE_TESSFACE_SPEEDUP
1223#undef USE_TESSFACE_QUADS
1236 reinterpret_cast<float (*)[3]
>(mesh->vert_positions_for_write().data()),
1268 if (std::any_of(polys.
begin(), polys.
end(), [](
const MPoly &poly) {
1269 return !(poly.flag_legacy & ME_SMOOTH);
1275 for (const int i : range) {
1276 sharp_faces.span[i] = !(polys[i].flag_legacy & ME_SMOOTH);
1279 sharp_faces.finish();
1282 attributes.remove(
"sharp_face");
1295 if (
mesh->attributes().contains(
".sculpt_face_set")) {
1298 void *faceset_data =
nullptr;
1302 if (layer.
type == CD_SCULPT_FACE_SETS) {
1303 faceset_data = layer.
data;
1305 layer.
data =
nullptr;
1311 if (faceset_data !=
nullptr) {
1317 faceset_sharing_info);
1319 if (faceset_sharing_info !=
nullptr) {
1333 if (
mesh->attributes().contains(
"face_maps")) {
1336 int *
data =
nullptr;
1340 if (layer.
type == CD_FACEMAP) {
1341 data =
static_cast<int *
>(layer.
data);
1343 layer.
data =
nullptr;
1355 if (sharing_info !=
nullptr) {
1361 if (
data[
i] == -1) {
1369 for (
const auto item : groups.
items()) {
1373 attribute.
span.fill_indices(item.value.as_span(),
true);
1392 mesh->attributes_for_write().rename(
".temp_face_map_" + std::to_string(
i), face_map->name);
1409 if (
mesh->cd_flag & ME_CDFLAG_VERT_BWEIGHT) {
1410 float *weights =
static_cast<float *
>(
1412 for (
const int i :
verts.index_range()) {
1413 weights[
i] =
verts[
i].bweight_legacy / 255.0f;
1420 if (
mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
1421 float *weights =
static_cast<float *
>(
1424 weights[
i] = edges[
i].bweight_legacy / 255.0f;
1433 const int elems_num,
1434 const char *new_name)
1437 void *
data =
nullptr;
1441 if (layer.
type == old_type) {
1444 layer.
data =
nullptr;
1450 if (
data !=
nullptr) {
1452 &custom_data, new_type,
data, elems_num, new_name, sharing_info);
1454 if (sharing_info !=
nullptr) {
1461 if (!
mesh->attributes().contains(
"bevel_weight_vert")) {
1465 if (!
mesh->attributes().contains(
"bevel_weight_edge")) {
1487 if (
mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) {
1488 float *creases =
static_cast<float *
>(
1491 creases[
i] = edges[
i].crease_legacy / 255.0f;
1498 if (!
mesh->attributes().contains(
"crease_vert")) {
1502 if (!
mesh->attributes().contains(
"crease_edge")) {
1523 if (attributes.
contains(
"sharp_edge")) {
1526 if (std::any_of(edges.
begin(), edges.
end(), [](
const MEdge &edge) {
1527 return edge.flag_legacy & ME_SHARP;
1533 for (const int i : range) {
1534 sharp_edges.span[i] = edges[i].flag_legacy & ME_SHARP;
1537 sharp_edges.finish();
1556 if (attributes.
contains(
".uv_seam")) {
1559 if (std::any_of(edges.
begin(), edges.
end(), [](
const MEdge &edge) {
1560 return edge.flag_legacy & ME_SEAM;
1566 for (const int i : range) {
1567 uv_seams.span[i] = edges[i].flag_legacy & ME_SEAM;
1591 if (std::any_of(
verts.begin(),
verts.end(), [](
const MVert &vert) {
1592 return vert.flag_legacy & ME_HIDE;
1598 for (const int i : range) {
1599 hide_vert.span[i] = verts[i].flag_legacy & ME_HIDE;
1607 if (std::any_of(edges.begin(), edges.end(), [](
const MEdge &edge) {
1608 return edge.flag_legacy & ME_HIDE;
1614 for (const int i : range) {
1615 hide_edge.span[i] = edges[i].flag_legacy & ME_HIDE;
1625 if (std::any_of(polys.begin(), polys.end(), [](
const MPoly &poly) {
1626 return poly.flag_legacy & ME_HIDE;
1632 for (const int i : range) {
1633 hide_poly.span[i] = polys[i].flag_legacy & ME_HIDE;
1658 polys.
begin(), polys.
end(), [](
const MPoly &poly) { return poly.mat_nr_legacy != 0; }))
1663 for (const int i : range) {
1664 material_indices.span[i] = polys[i].mat_nr_legacy;
1667 material_indices.finish();
1692 const int active_name_i = uv_names.
as_span().first_index_try(
1694 const int default_name_i = uv_names.
as_span().first_index_try(
1698 const MLoopUV *mloopuv =
static_cast<const MLoopUV *
>(
1705 for (const int i : range) {
1706 init |= mloopuv[i].flag;
1710 [](
const uint32_t a,
const uint32_t
b) {
return a |
b; });
1713 bool *pin =
nullptr;
1714 if (needed_boolean_attributes & MLOOPUV_PINNED) {
1719 for (const int i : range) {
1720 coords[i] = mloopuv[i].uv;
1723 for (
const int i : range) {
1724 pin[
i] = mloopuv[
i].flag & MLOOPUV_PINNED;
1733 uv_names[
i] = new_name;
1748 if (active_name_i != -1) {
1753 uv_names[active_name_i]));
1755 if (default_name_i != -1) {
1760 uv_names[default_name_i]));
1774 if (!
mesh->mvert || attributes.
contains(
".select_vert") || attributes.
contains(
".select_edge") ||
1775 attributes.
contains(
".select_poly"))
1782 verts.begin(),
verts.end(), [](
const MVert &vert) { return vert.flag_legacy & SELECT; }))
1787 for (const int i : range) {
1788 select_vert.span[i] = verts[i].flag_legacy & SELECT;
1791 select_vert.finish();
1796 if (std::any_of(edges.begin(), edges.end(), [](
const MEdge &edge) {
1797 return edge.flag_legacy & SELECT;
1803 for (const int i : range) {
1804 select_edge.span[i] = edges[i].flag_legacy & SELECT;
1814 if (std::any_of(polys.begin(), polys.end(), [](
const MPoly &poly) {
1815 return poly.flag_legacy & ME_FACE_SEL;
1821 for (const int i : range) {
1822 select_poly.span[i] = polys[i].flag_legacy & ME_FACE_SEL;
1839 const MVert *mvert =
static_cast<const MVert *
>(
1851 for (const int i : range) {
1852 positions[i] = verts[i].co_legacy;
1857 mesh->mvert =
nullptr;
1870 const MEdge *medge =
static_cast<const MEdge *
>(
1882 for (const int i : range) {
1883 edges[i] = int2(legacy_edges[i].v1, legacy_edges[i].v2);
1888 mesh->medge =
nullptr;
1904 if (!
mesh->active_color_attribute) {
1906 if (
data.layers[
i].flag & CD_FLAG_COLOR_ACTIVE) {
1913 if (!
mesh->active_color_attribute) {
1919 if (!
mesh->active_color_attribute) {
1927 if (!
mesh->default_color_attribute) {
1929 if (
data.layers[
i].flag & CD_FLAG_COLOR_RENDER) {
1936 if (!
mesh->default_color_attribute) {
1942 if (!
mesh->default_color_attribute) {
1950 active_from_flags(
mesh->vert_data);
1951 active_from_flags(
mesh->corner_data);
1952 active_from_indices(
mesh->vert_data);
1953 active_from_indices(
mesh->corner_data);
1955 default_from_flags(
mesh->vert_data);
1956 default_from_flags(
mesh->corner_data);
1957 default_from_indices(
mesh->vert_data);
1958 default_from_indices(
mesh->corner_data);
1987 for (const int i : range) {
1988 corner_verts[i] = loops[i].v;
1989 corner_edges[i] = loops[i].e;
2005 if (polys[
i].loopstart > polys[
i + 1].loopstart) {
2015 if (
mesh->face_offset_indices) {
2027 offsets[
i] = polys[
i].loopstart;
2034 std::stable_sort(orig_indices.
begin(), orig_indices.
end(), [polys](
const int a,
const int b) {
2035 return polys[a].loopstart < polys[b].loopstart;
2044 offsets[
i] = offset;
2045 offset += polys[orig_indices[
i]].totloop;
2049 for (const int i : range) {
2050 CustomData_copy_data(&old_poly_data, &mesh->face_data, orig_indices[i], i, 1);
2071 &bmain, owner_library,
DATA_(
"Auto Smooth"),
"GeometryNodeTree");
2084 angle_data.
min = 0.0f;
2089 group_output->
location[0] = 480.0f;
2090 group_output->
location[1] = -100.0f;
2092 group_input_angle->
location[0] = -420.0f;
2093 group_input_angle->
location[1] = -300.0f;
2095 if (!
STREQ(socket->identifier,
"Socket_2")) {
2100 group_input_mesh->
location[0] = -60.0f;
2101 group_input_mesh->
location[1] = -100.0f;
2103 if (!
STREQ(socket->identifier,
"Socket_1")) {
2107 bNode *shade_smooth_edge =
node_add_node(
nullptr, *group,
"GeometryNodeSetShadeSmooth");
2109 shade_smooth_edge->
location[0] = 120.0f;
2110 shade_smooth_edge->
location[1] = -100.0f;
2111 bNode *shade_smooth_face =
node_add_node(
nullptr, *group,
"GeometryNodeSetShadeSmooth");
2113 shade_smooth_face->
location[0] = 300.0f;
2114 shade_smooth_face->
location[1] = -100.0f;
2115 bNode *edge_angle =
node_add_node(
nullptr, *group,
"GeometryNodeInputMeshEdgeAngle");
2120 edge_smooth->
location[1] = -160.0f;
2122 face_smooth->
location[0] = -240.0f;
2123 face_smooth->
location[1] = -340.0f;
2127 boolean_and->
location[1] = -220.0f;
2131 less_than_or_equal->
location[0] = -240.0f;
2132 less_than_or_equal->
location[1] = -180.0f;
2137 *less_than_or_equal,
2147 *less_than_or_equal,
2150 *less_than_or_equal,
2210 if (
nodes.size() != 10) {
2219 const std::array<StringRef, 10> idnames({
"NodeGroupOutput",
2222 "GeometryNodeSetShadeSmooth",
2223 "GeometryNodeSetShadeSmooth",
2224 "GeometryNodeInputMeshEdgeAngle",
2225 "GeometryNodeInputEdgeSmooth",
2226 "GeometryNodeInputShadeSmooth",
2227 "FunctionNodeBooleanMath",
2228 "FunctionNodeCompare"});
2229 for (
const int i :
nodes.index_range()) {
2230 if (
nodes[
i]->idname != idnames[
i]) {
2257 const std::array<int, 9> link_from_socket_indices({16, 15, 3, 36, 19, 5, 18, 11, 22});
2258 const std::array<int, 9> link_to_socket_indices({23, 0, 24, 20, 21, 8, 9, 12, 10});
2262 if (socket_indices.index_of(link->fromsock) != link_from_socket_indices[
i]) {
2265 if (socket_indices.index_of(link->tosock) != link_to_socket_indices[
i]) {
2281 md->node_group = get_node_group(
object.
id.
lib);
2288 ui_data->soft_min = 0.0f;
2289 ui_data->soft_max =
DEG2RADF(180.0f);
2295 return &md->modifier;
2307 const auto add_node_group = [&](
Library *owner_library) {
2314 if (existing_group->id.lib != owner_library) {
2318 group_by_library.
add_new(owner_library, existing_group);
2319 return existing_group;
2325 group_by_library.
add_new(owner_library, new_group);
2334 const float angle =
mesh->smoothresh_legacy;
2345 if (has_custom_normals) {
2354 has_custom_normals =
true;
2359 has_custom_normals =
true;
2375 has_custom_normals =
true;
2384 if (has_custom_normals) {
2412 if (
mesh.attributes().contains(
".sculpt_mask")) {
2415 void *
data =
nullptr;
2419 if (layer.
type == CD_PAINT_MASK) {
2422 layer.
data =
nullptr;
2428 if (
data !=
nullptr) {
2432 if (sharing_info !=
nullptr) {
2440 void *
data =
nullptr;
2444 if (layer.
type == CD_FREESTYLE_EDGE) {
2447 layer.
data =
nullptr;
2453 if (
data !=
nullptr) {
2454 static_assert(
sizeof(FreestyleEdge) ==
sizeof(bool));
2455 static_assert(char(FREESTYLE_EDGE_MARK) == char(
true));
2459 if (sharing_info !=
nullptr) {
2464 void *
data =
nullptr;
2468 if (layer.
type == CD_FREESTYLE_FACE) {
2471 layer.
data =
nullptr;
2477 if (
data !=
nullptr) {
2478 static_assert(
sizeof(FreestyleFace) ==
sizeof(bool));
2479 static_assert(char(FREESTYLE_FACE_MARK) == char(
true));
2483 if (sharing_info !=
nullptr) {
2496 for (
const int i : attr_write_data.
attributes.index_range()) {
2497 const ::Attribute &dna_attr = attr_write_data.
attributes[
i];
2505 if (
STREQ(dna_attr.name,
"freestyle_edge")) {
2506 const auto &array_dna = *
static_cast<const ::
AttributeArray *
>(dna_attr.data);
2507 static_assert(
sizeof(FreestyleEdge) ==
sizeof(bool));
2508 static_assert(char(FREESTYLE_EDGE_MARK) == char(
true));
2510 layer.
type = CD_FREESTYLE_EDGE;
2511 layer.
data = array_dna.data;
2513 edge_layers.
append(layer);
2515 edge_layers.
begin(),
2525 attrs_to_remove[
i] =
true;
2529 if (
STREQ(dna_attr.name,
"freestyle_face")) {
2530 const auto &array_dna = *
static_cast<const ::
AttributeArray *
>(dna_attr.data);
2531 static_assert(
sizeof(FreestyleFace) ==
sizeof(bool));
2532 static_assert(char(FREESTYLE_FACE_MARK) == char(
true));
2534 layer.
type = CD_FREESTYLE_FACE;
2535 layer.
data = array_dna.data;
2537 face_layers.
append(layer);
2539 face_layers.
begin(),
2549 attrs_to_remove[
i] =
true;
2553 attr_write_data.
attributes.remove_if([&](const ::Attribute &attr) {
2554 const int i = &attr - attr_write_data.
attributes.begin();
2555 return attrs_to_remove[
i];
2561 if (
mesh.attributes().contains(
"custom_normal")) {
2564 void *
data =
nullptr;
2568 if (layer.
type == CD_CUSTOMLOOPNORMAL) {
2571 layer.
data =
nullptr;
2577 if (
data !=
nullptr) {
2585 if (sharing_info !=
nullptr) {
2596 const std::string uv_select_vert_name_shared =
".uv_select_vert";
2597 const std::string uv_select_edge_name_shared =
".uv_select_edge";
2598 const std::string uv_select_face_name_shared =
".uv_select_face";
2600 const std::string uv_select_vert_prefix =
".vs.";
2601 const std::string uv_select_edge_prefix =
".es.";
2603 const std::string uv_select_vert_name = uv_select_vert_prefix +
name;
2604 const std::string uv_select_edge_name = uv_select_edge_prefix +
name;
2611 if (uv_select_vert != -1 && uv_select_edge != -1) {
2617 STRNCPY_UTF8(
mesh.corner_data.layers[uv_select_vert].name, uv_select_vert_name_shared.c_str());
2618 STRNCPY_UTF8(
mesh.corner_data.layers[uv_select_edge].name, uv_select_edge_name_shared.c_str());
2625 uv_select_face_name_shared,
2629 if (
mesh.faces_num > 0) {
2632 static_cast<bool *
>(
mesh.corner_data.layers[uv_select_edge].data),
mesh.corners_num);
2634 for (const int face : range) {
2635 uv_select_face[face] = !uv_select_edge_data.slice(faces[face]).contains(false);
2650 if (layer_name.
startswith(uv_select_vert_prefix) ||
2651 layer_name.
startswith(uv_select_edge_prefix))
2657 for (
const StringRef name_to_remove : attributes_to_remove) {
2668 const int nulegacy_faces =
mesh->totface_legacy;
2674 MFace *mf = legacy_faces;
2675 for (
int i = 0;
i < nulegacy_faces;
i++, mf++) {
2688 const int numEdges = eh.
size();
2705 mesh->edge_data = edgeData;
2706 mesh->edges_num = numEdges;
blender::StringRef BKE_uv_map_pin_name_get(blender::StringRef uv_map_name, char *buffer)
std::string BKE_attribute_calc_unique_name(const AttributeOwner &owner, blender::StringRef name)
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)
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)
bool CustomData_free_layer(CustomData *data, eCustomDataType type, int index)
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)
void CustomData_free(CustomData *data)
void CustomData_set_layer_clone(CustomData *data, eCustomDataType type, int n)
void CustomData_free_layers(CustomData *data, eCustomDataType type)
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_free_layer_named(CustomData *data, blender::StringRef name)
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_after_single_tree_change(Main &bmain, bNodeTree &modified_tree, const NodeTreeUpdateExtraParams ¶ms={})
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) 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 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])
#define BLI_MEMARENA_STD_BUFSIZE
MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
void BLI_memarena_free(MemArena *ma) ATTR_NONNULL(1)
void * BLI_memarena_alloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
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_UTF8(dst, src)
#define MAX_CUSTOMDATA_LAYER_NAME
@ MOD_BEVEL_HARDEN_NORMALS
@ eModifierType_NormalEdit
@ eModifierType_WeightedNormal
@ MOD_WEIGHTEDNORMAL_KEEP_SHARP
@ eSubsurfModifierFlag_UseCustomNormals
@ 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.
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Span< T > as_span() const
IndexRange index_range() const
static AttributeOwner from_id(ID *id)
void remove_user_and_delete_if_last() const
const Value * lookup_ptr(const Key &key) const
void add_new(const Key &key, const Value &value)
MapType::ItemIterator items() const
void add(const Key &key, const Value &value)
void remove_user_and_delete_if_last() const
constexpr IndexRange drop_back(int64_t n) const
bool add(const Key &key, const Value &value)
constexpr T * end() const
constexpr T * begin() const
constexpr IndexRange index_range() 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
constexpr bool startswith(StringRef prefix) const
void reserve(const int64_t n)
Span< Key > as_span() const
void append(const T &value)
bool contains(StringRef attribute_id) const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(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 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 convert_mfaces_to_mpolys(ID *id, CustomData *fdata_legacy, CustomData *ldata, CustomData *pdata, int totedge_i, int totface_i, int, int, blender::int2 *edges, MFace *mface, int *r_totloop, int *r_faces_num)
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)
void BKE_mesh_legacy_attribute_flags_to_strings(Mesh *mesh)
void BKE_mesh_do_versions_cd_flag_init(Mesh *mesh)
void fill_index_range(MutableSpan< T > span, const T start=0)
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRef 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(StringRef 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)
void mesh_freestyle_marks_to_generic(Mesh &mesh)
void mesh_freestyle_marks_to_legacy(AttributeStorage::BlendWriteData &attr_write_data, CustomData &edge_data, CustomData &face_data, Vector< CustomDataLayer, 16 > &edge_layers, Vector< CustomDataLayer, 16 > &face_layers)
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
bNode * node_add_node(const bContext *C, bNodeTree &ntree, StringRef idname, std::optional< int > unique_identifier=std::nullopt)
static bool is_auto_smooth_node_tree(const bNodeTree &group)
bool node_set_selected(bNode &node, bool select)
bNodeLink & node_add_link(bNodeTree &ntree, bNode &fromnode, bNodeSocket &fromsock, bNode &tonode, bNodeSocket &tosock)
void mesh_custom_normals_to_generic(Mesh &mesh)
void mesh_uv_select_to_single_attribute(Mesh &mesh)
bNodeTree * node_tree_add_in_lib(Main *bmain, Library *owner_library, StringRefNull name, StringRefNull idname)
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)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
static blender::bke::bNodeSocketTemplate inputs[]
static void init(bNodeTree *, bNode *node)
const ImplicitSharingInfoHandle * sharing_info
CustomDataExternal * external
char * default_color_attribute
char * active_color_attribute
struct bNodeTree * node_group
struct GeometryNodeAssetTraits * geometry_node_asset_traits
bNodeTreeInterface tree_interface
Vector<::Attribute, 16 > & attributes
MutableVArraySpan< T > span
static DynamicLibrary lib