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) {
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;
193 hash.reserve(totedge_final);
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 *
>(
247 &mesh->
edge_data, CD_MEDGE, edges, totedge,
nullptr);
250 mesh->tag_topology_changed();
259 MFace *mfaces = mesh->mface;
264 memcpy(&mfaces[
b], f,
sizeof(mfaces[
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++) {
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);
402 const float(*disps)[3] = fd->
disps;
403 int tot = mf->
v4 ? 4 : 3;
421 const int side = int(
sqrtf(
float(fd->
totdisp / corners)));
422 const int side_sq = side * side;
424 for (
int i = 0;
i < tot;
i++, disps += side_sq, ld++) {
434 memcpy(ld->
disps, disps,
size_t(side_sq) *
sizeof(
float[3]));
437 memset(ld->
disps, 0,
size_t(side_sq) *
sizeof(
float[3]));
483 int i, j, totloop, faces_num, *polyindex;
489 faces_num = totface_i;
491 int *material_indices =
static_cast<int *
>(
493 if (material_indices ==
nullptr) {
497 bool *sharp_faces =
static_cast<bool *
>(
500 sharp_faces =
static_cast<bool *
>(
509 for (
i = 0;
i < totface_i;
i++, mf++) {
510 totloop += mf->
v4 ? 4 : 3;
527 for (
i = 0;
i < totedge_i;
i++) {
537 for (
i = 0;
i < totface_i;
i++, mf++, poly++) {
540 poly->totloop = mf->
v4 ? 4 : 3;
542 material_indices[
i] = mf->
mat_nr;
543 sharp_faces[
i] = (mf->
flag & ME_SMOOTH) == 0;
548 ml->e = eh.lookup({mf->v1, mf->v2}); \
567 id, fdata_legacy, totface_i, ldata, mface, totloop,
i, poly->loopstart, numTex, numCol);
578 *r_faces_num = faces_num;
579 *r_totloop = totloop;
636 int a_num = 0, b_num = 0;
637# define LAYER_CMP(l_a, t_a, l_b, t_b) \
638 ((a_num += CustomData_number_of_layers(l_a, t_a)) == \
639 (b_num += CustomData_number_of_layers(l_b, t_b)))
661 return a_num ?
true : fallback;
712 if (tottex_tessface != tottex_original || totcol_tessface != totcol_original) {
724 "%s: warning! Tessellation uvs or vcol data got out of sync, "
725 "had to reset!\n CD_MTFACE: %d != CD_PROP_FLOAT2: %d || CD_MCOL: %d != "
726 "CD_PROP_BYTE_COLOR: "
748 mesh->edges_for_write().data(),
808 mesh->edges_for_write().data(),
828#define MESH_MLOOPCOL_TO_MCOL(_mloopcol, _mcol) \
830 const MLoopCol *mloopcol__tmp = _mloopcol; \
831 MCol *mcol__tmp = _mcol; \
832 mcol__tmp->b = mloopcol__tmp->r; \
833 mcol__tmp->g = mloopcol__tmp->g; \
834 mcol__tmp->r = mloopcol__tmp->b; \
835 mcol__tmp->a = mloopcol__tmp->a; \
851 const int *polyindices,
852 uint (*loopindices)[4],
868 for (
i = 0;
i < numUV;
i++) {
874 for (findex = 0, pidx = polyindices, lidx = loopindices; findex < num_faces;
875 pidx++, lidx++, findex++, texface++)
877 for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
883 for (
i = 0;
i < numCol;
i++) {
885 fdata_legacy,
CD_MCOL,
i, num_faces);
889 for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, mcol++) {
890 for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
901 for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, of++) {
902 for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
914 for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, face_normals++) {
915 for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
921 if (hasLoopTangent) {
926 for (findex = 0, pidx = polyindices, lidx = loopindices; findex < num_faces;
927 pidx++, lidx++, findex++)
929 int nverts = (mface ? mface[findex].
v4 : (*lidx)[3]) ? 4 : 3;
930 for (j = nverts; j--;) {
931 copy_v4_v4(ftangents[findex * 4 + j], ltangents[(*lidx)[j]]);
940 if ((mface->
v3 || nr == 4) && mface->
v3 == mface->
v4) {
944 if ((mface->
v2 || mface->
v4) && mface->
v2 == mface->
v3) {
945 mface->
v3 = mface->
v4;
949 if (mface->
v1 == mface->
v2) {
950 mface->
v2 = mface->
v3;
951 mface->
v3 = mface->
v4;
961 mface->
v1 == mface->
v2 || mface->
v2 == mface->
v3 || mface->
v3 == mface->
v1)
969 mface->
v1 == mface->
v2 || mface->
v2 == mface->
v3 || mface->
v3 == mface->
v4 ||
970 mface->
v4 == mface->
v1 ||
972 mface->
v1 == mface->
v3 || mface->
v2 == mface->
v4)
980 if (mface->
v3 == 0) {
981 static int corner_indices[4] = {1, 2, 0, 3};
983 std::swap(mface->
v1, mface->
v2);
984 std::swap(mface->
v2, mface->
v3);
992 if (mface->
v3 == 0 || mface->
v4 == 0) {
993 static int corner_indices[4] = {2, 3, 0, 1};
995 std::swap(mface->
v1, mface->
v3);
996 std::swap(mface->
v2, mface->
v4);
1011 float (*positions)[3],
1016#define USE_TESSFACE_SPEEDUP
1017#define USE_TESSFACE_QUADS
1020#define TESSFACE_IS_QUAD 1
1026 int *mface_to_poly_map;
1028 int poly_index, mface_index;
1032 const Span<int> corner_verts = mesh.corner_verts();
1033 const int *material_indices =
static_cast<const int *
>(
1035 const bool *sharp_faces =
static_cast<const bool *
>(
1046 for (poly_index = 0; poly_index < faces_num; poly_index++) {
1049 uint l1, l2, l3, l4;
1051 if (mp_totloop < 3) {
1055#ifdef USE_TESSFACE_SPEEDUP
1057# define ML_TO_MF(i1, i2, i3) \
1058 mface_to_poly_map[mface_index] = poly_index; \
1059 mf = &mface[mface_index]; \
1060 lidx = lindices[mface_index]; \
1062 l1 = mp_loopstart + i1; \
1063 l2 = mp_loopstart + i2; \
1064 l3 = mp_loopstart + i3; \
1065 mf->v1 = corner_verts[l1]; \
1066 mf->v2 = corner_verts[l2]; \
1067 mf->v3 = corner_verts[l3]; \
1073 mf->mat_nr = material_indices ? material_indices[poly_index] : 0; \
1074 mf->flag = (sharp_faces && sharp_faces[poly_index]) ? 0 : ME_SMOOTH; \
1079# define ML_TO_MF_QUAD() \
1080 mface_to_poly_map[mface_index] = poly_index; \
1081 mf = &mface[mface_index]; \
1082 lidx = lindices[mface_index]; \
1084 l1 = mp_loopstart + 0; \
1085 l2 = mp_loopstart + 1; \
1086 l3 = mp_loopstart + 2; \
1087 l4 = mp_loopstart + 3; \
1088 mf->v1 = corner_verts[l1]; \
1089 mf->v2 = corner_verts[l2]; \
1090 mf->v3 = corner_verts[l3]; \
1091 mf->v4 = corner_verts[l4]; \
1096 mf->mat_nr = material_indices ? material_indices[poly_index] : 0; \
1097 mf->flag = (sharp_faces && sharp_faces[poly_index]) ? 0 : ME_SMOOTH; \
1098 mf->edcode = TESSFACE_IS_QUAD; \
1101 else if (mp_totloop == 3) {
1105 else if (mp_totloop == 4) {
1106# ifdef USE_TESSFACE_QUADS
1118 const float *co_curr, *co_prev;
1122 float axis_mat[3][3];
1123 float(*projverts)[2];
1126 const uint totfilltri = mp_totloop - 2;
1133 projverts = (float(*)[2])
BLI_memarena_alloc(arena,
sizeof(*projverts) *
size_t(mp_totloop));
1138 co_prev = positions[corner_verts[mp_loopstart + mp_totloop - 1]];
1139 for (j = 0; j < mp_totloop; j++) {
1140 const int vert = corner_verts[mp_loopstart + j];
1141 co_curr = positions[vert];
1152 for (j = 0; j < mp_totloop; j++) {
1153 const int vert = corner_verts[mp_loopstart + j];
1154 mul_v2_m3v3(projverts[j], axis_mat, positions[vert]);
1160 for (j = 0; j < totfilltri; j++) {
1161 uint *tri = tris[j];
1162 lidx = lindices[mface_index];
1164 mface_to_poly_map[mface_index] = poly_index;
1165 mf = &mface[mface_index];
1168 l1 = mp_loopstart + tri[0];
1169 l2 = mp_loopstart + tri[1];
1170 l3 = mp_loopstart + tri[2];
1172 mf->
v1 = corner_verts[l1];
1173 mf->
v2 = corner_verts[l2];
1174 mf->
v3 = corner_verts[l3];
1182 mf->
mat_nr = material_indices ? material_indices[poly_index] : 0;
1198 totface = mface_index;
1203 if (
LIKELY(corner_tris_num != totface)) {
1205 mface_to_poly_map = (
int *)
MEM_reallocN(mface_to_poly_map,
1206 sizeof(*mface_to_poly_map) *
size_t(totface));
1229#ifdef USE_TESSFACE_QUADS
1231 for (mface_index = 0; mface_index < totface; mface_index++, mf++) {
1243#undef USE_TESSFACE_SPEEDUP
1244#undef USE_TESSFACE_QUADS
1257 reinterpret_cast<float(*)[3]
>(mesh->vert_positions_for_write().data()),
1289 if (std::any_of(polys.
begin(), polys.
end(), [](
const MPoly &poly) {
1290 return !(poly.flag_legacy & ME_SMOOTH);
1296 for (const int i : range) {
1297 sharp_faces.span[i] = !(polys[i].flag_legacy & ME_SMOOTH);
1300 sharp_faces.finish();
1303 attributes.remove(
"sharp_face");
1316 if (
mesh->attributes().contains(
".sculpt_face_set")) {
1319 void *faceset_data =
nullptr;
1323 if (layer.
type == CD_SCULPT_FACE_SETS) {
1324 faceset_data = layer.
data;
1326 layer.
data =
nullptr;
1332 if (faceset_data !=
nullptr) {
1338 faceset_sharing_info);
1340 if (faceset_sharing_info !=
nullptr) {
1354 if (
mesh->attributes().contains(
"face_maps")) {
1357 int *
data =
nullptr;
1361 if (layer.
type == CD_FACEMAP) {
1362 data =
static_cast<int *
>(layer.
data);
1364 layer.
data =
nullptr;
1376 if (sharing_info !=
nullptr) {
1382 if (
data[
i] == -1) {
1390 for (
const auto item : groups.
items()) {
1394 attribute.
span.fill_indices(item.value.as_span(),
true);
1413 mesh->attributes_for_write().rename(
".temp_face_map_" + std::to_string(
i), face_map->name);
1430 if (
mesh->cd_flag & ME_CDFLAG_VERT_BWEIGHT) {
1431 float *weights =
static_cast<float *
>(
1433 for (
const int i :
verts.index_range()) {
1434 weights[
i] =
verts[
i].bweight_legacy / 255.0f;
1441 if (
mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
1442 float *weights =
static_cast<float *
>(
1445 weights[
i] = edges[
i].bweight_legacy / 255.0f;
1454 const int elems_num,
1455 const char *new_name)
1458 void *
data =
nullptr;
1462 if (layer.
type == old_type) {
1465 layer.
data =
nullptr;
1471 if (
data !=
nullptr) {
1473 &custom_data, new_type,
data, elems_num, new_name, sharing_info);
1475 if (sharing_info !=
nullptr) {
1482 if (!
mesh->attributes().contains(
"bevel_weight_vert")) {
1486 if (!
mesh->attributes().contains(
"bevel_weight_edge")) {
1508 if (
mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) {
1509 float *creases =
static_cast<float *
>(
1512 creases[
i] = edges[
i].crease_legacy / 255.0f;
1519 if (!
mesh->attributes().contains(
"crease_vert")) {
1523 if (!
mesh->attributes().contains(
"crease_edge")) {
1544 if (attributes.
contains(
"sharp_edge")) {
1547 if (std::any_of(edges.
begin(), edges.
end(), [](
const MEdge &edge) {
1548 return edge.flag_legacy & ME_SHARP;
1554 for (const int i : range) {
1555 sharp_edges.span[i] = edges[i].flag_legacy & ME_SHARP;
1558 sharp_edges.finish();
1577 if (attributes.
contains(
".uv_seam")) {
1580 if (std::any_of(edges.
begin(), edges.
end(), [](
const MEdge &edge) {
1581 return edge.flag_legacy & ME_SEAM;
1587 for (const int i : range) {
1588 uv_seams.span[i] = edges[i].flag_legacy & ME_SEAM;
1612 if (std::any_of(
verts.begin(),
verts.end(), [](
const MVert &vert) {
1613 return vert.flag_legacy & ME_HIDE;
1619 for (const int i : range) {
1620 hide_vert.span[i] = verts[i].flag_legacy & ME_HIDE;
1628 if (std::any_of(edges.begin(), edges.end(), [](
const MEdge &edge) {
1629 return edge.flag_legacy & ME_HIDE;
1635 for (const int i : range) {
1636 hide_edge.span[i] = edges[i].flag_legacy & ME_HIDE;
1646 if (std::any_of(polys.begin(), polys.end(), [](
const MPoly &poly) {
1647 return poly.flag_legacy & ME_HIDE;
1653 for (const int i : range) {
1654 hide_poly.span[i] = polys[i].flag_legacy & ME_HIDE;
1679 polys.
begin(), polys.
end(), [](
const MPoly &poly) { return poly.mat_nr_legacy != 0; }))
1684 for (const int i : range) {
1685 material_indices.span[i] = polys[i].mat_nr_legacy;
1688 material_indices.finish();
1713 const int active_name_i = uv_names.
as_span().first_index_try(
1715 const int default_name_i = uv_names.
as_span().first_index_try(
1719 const MLoopUV *mloopuv =
static_cast<const MLoopUV *
>(
1726 for (const int i : range) {
1727 init |= mloopuv[i].flag;
1731 [](
const uint32_t a,
const uint32_t
b) {
return a |
b; });
1734 bool *vert_selection =
nullptr;
1735 bool *edge_selection =
nullptr;
1736 bool *pin =
nullptr;
1737 if (needed_boolean_attributes & MLOOPUV_VERTSEL) {
1740 if (needed_boolean_attributes & MLOOPUV_EDGESEL) {
1743 if (needed_boolean_attributes & MLOOPUV_PINNED) {
1748 for (const int i : range) {
1749 coords[i] = mloopuv[i].uv;
1751 if (vert_selection) {
1752 for (
const int i : range) {
1753 vert_selection[
i] = mloopuv[
i].flag & MLOOPUV_VERTSEL;
1756 if (edge_selection) {
1757 for (
const int i : range) {
1758 edge_selection[
i] = mloopuv[
i].flag & MLOOPUV_EDGESEL;
1762 for (
const int i : range) {
1763 pin[
i] = mloopuv[
i].flag & MLOOPUV_PINNED;
1772 uv_names[
i] = new_name;
1777 if (vert_selection) {
1785 if (edge_selection) {
1803 if (active_name_i != -1) {
1808 uv_names[active_name_i]));
1810 if (default_name_i != -1) {
1815 uv_names[default_name_i]));
1829 if (!
mesh->mvert || attributes.
contains(
".select_vert") || attributes.
contains(
".select_edge") ||
1830 attributes.
contains(
".select_poly"))
1837 verts.begin(),
verts.end(), [](
const MVert &vert) { return vert.flag_legacy & SELECT; }))
1842 for (const int i : range) {
1843 select_vert.span[i] = verts[i].flag_legacy & SELECT;
1846 select_vert.finish();
1851 if (std::any_of(edges.begin(), edges.end(), [](
const MEdge &edge) {
1852 return edge.flag_legacy & SELECT;
1858 for (const int i : range) {
1859 select_edge.span[i] = edges[i].flag_legacy & SELECT;
1869 if (std::any_of(polys.begin(), polys.end(), [](
const MPoly &poly) {
1870 return poly.flag_legacy & ME_FACE_SEL;
1876 for (const int i : range) {
1877 select_poly.span[i] = polys[i].flag_legacy & ME_FACE_SEL;
1894 const MVert *mvert =
static_cast<const MVert *
>(
1906 for (const int i : range) {
1907 positions[i] = verts[i].co_legacy;
1912 mesh->mvert =
nullptr;
1925 const MEdge *medge =
static_cast<const MEdge *
>(
1937 for (const int i : range) {
1938 edges[i] = int2(legacy_edges[i].v1, legacy_edges[i].v2);
1943 mesh->medge =
nullptr;
1959 if (!
mesh->active_color_attribute) {
1961 if (
data.layers[
i].flag & CD_FLAG_COLOR_ACTIVE) {
1968 if (!
mesh->active_color_attribute) {
1974 if (!
mesh->active_color_attribute) {
1982 if (!
mesh->default_color_attribute) {
1984 if (
data.layers[
i].flag & CD_FLAG_COLOR_RENDER) {
1991 if (!
mesh->default_color_attribute) {
1997 if (!
mesh->default_color_attribute) {
2005 active_from_flags(
mesh->vert_data);
2006 active_from_flags(
mesh->corner_data);
2007 active_from_indices(
mesh->vert_data);
2008 active_from_indices(
mesh->corner_data);
2010 default_from_flags(
mesh->vert_data);
2011 default_from_flags(
mesh->corner_data);
2012 default_from_indices(
mesh->vert_data);
2013 default_from_indices(
mesh->corner_data);
2042 for (const int i : range) {
2043 corner_verts[i] = loops[i].v;
2044 corner_edges[i] = loops[i].e;
2060 if (polys[
i].loopstart > polys[
i + 1].loopstart) {
2070 if (
mesh->face_offset_indices) {
2082 offsets[
i] = polys[
i].loopstart;
2089 std::stable_sort(orig_indices.
begin(), orig_indices.
end(), [polys](
const int a,
const int b) {
2090 return polys[a].loopstart < polys[b].loopstart;
2099 offsets[
i] = offset;
2100 offset += polys[orig_indices[
i]].totloop;
2104 for (const int i : range) {
2105 CustomData_copy_data(&old_poly_data, &mesh->face_data, orig_indices[i], i, 1);
2126 &bmain, owner_library,
DATA_(
"Auto Smooth"),
"GeometryNodeTree");
2139 angle_data.
min = 0.0f;
2144 group_output->
location[0] = 480.0f;
2145 group_output->
location[1] = -100.0f;
2147 group_input_angle->
location[0] = -420.0f;
2148 group_input_angle->
location[1] = -300.0f;
2150 if (!
STREQ(socket->identifier,
"Socket_2")) {
2155 group_input_mesh->
location[0] = -60.0f;
2156 group_input_mesh->
location[1] = -100.0f;
2158 if (!
STREQ(socket->identifier,
"Socket_1")) {
2162 bNode *shade_smooth_edge =
node_add_node(
nullptr, *group,
"GeometryNodeSetShadeSmooth");
2164 shade_smooth_edge->
location[0] = 120.0f;
2165 shade_smooth_edge->
location[1] = -100.0f;
2166 bNode *shade_smooth_face =
node_add_node(
nullptr, *group,
"GeometryNodeSetShadeSmooth");
2168 shade_smooth_face->
location[0] = 300.0f;
2169 shade_smooth_face->
location[1] = -100.0f;
2170 bNode *edge_angle =
node_add_node(
nullptr, *group,
"GeometryNodeInputMeshEdgeAngle");
2175 edge_smooth->
location[1] = -160.0f;
2177 face_smooth->
location[0] = -240.0f;
2178 face_smooth->
location[1] = -340.0f;
2182 boolean_and->
location[1] = -220.0f;
2186 less_than_or_equal->
location[0] = -240.0f;
2187 less_than_or_equal->
location[1] = -180.0f;
2192 *less_than_or_equal,
2202 *less_than_or_equal,
2205 *less_than_or_equal,
2265 if (
nodes.size() != 10) {
2274 const std::array<StringRef, 10> idnames({
"NodeGroupOutput",
2277 "GeometryNodeSetShadeSmooth",
2278 "GeometryNodeSetShadeSmooth",
2279 "GeometryNodeInputMeshEdgeAngle",
2280 "GeometryNodeInputEdgeSmooth",
2281 "GeometryNodeInputShadeSmooth",
2282 "FunctionNodeBooleanMath",
2283 "FunctionNodeCompare"});
2284 for (
const int i :
nodes.index_range()) {
2285 if (
nodes[
i]->idname != idnames[
i]) {
2312 const std::array<int, 9> link_from_socket_indices({16, 15, 3, 36, 19, 5, 18, 11, 22});
2313 const std::array<int, 9> link_to_socket_indices({23, 0, 24, 20, 21, 8, 9, 12, 10});
2317 if (socket_indices.index_of(link->fromsock) != link_from_socket_indices[
i]) {
2320 if (socket_indices.index_of(link->tosock) != link_to_socket_indices[
i]) {
2336 md->node_group = get_node_group(
object.
id.
lib);
2343 ui_data->soft_min = 0.0f;
2344 ui_data->soft_max =
DEG2RADF(180.0f);
2350 return &md->modifier;
2362 const auto add_node_group = [&](
Library *owner_library) {
2369 if (existing_group->id.lib != owner_library) {
2373 group_by_library.
add_new(owner_library, existing_group);
2374 return existing_group;
2380 group_by_library.
add_new(owner_library, new_group);
2389 const float angle =
mesh->smoothresh_legacy;
2400 if (has_custom_normals) {
2409 has_custom_normals =
true;
2414 has_custom_normals =
true;
2430 has_custom_normals =
true;
2439 if (has_custom_normals) {
2467 bool changed =
false;
2469 if (
StringRef(layer.name) ==
".sculpt_mask") {
2470 layer.type = CD_PAINT_MASK;
2471 layer.name[0] =
'\0';
2481 vert_layers.
begin(),
2488 if (
mesh.attributes().contains(
".sculpt_mask")) {
2491 void *
data =
nullptr;
2495 if (layer.
type == CD_PAINT_MASK) {
2498 layer.
data =
nullptr;
2504 if (
data !=
nullptr) {
2508 if (sharing_info !=
nullptr) {
2515 bool changed =
false;
2518 layer.type = CD_CUSTOMLOOPNORMAL;
2519 layer.name[0] =
'\0';
2529 corner_layers.
begin(),
2530 corner_layers.
end(),
2536 if (
mesh.attributes().contains(
"custom_normal")) {
2539 void *
data =
nullptr;
2543 if (layer.
type == CD_CUSTOMLOOPNORMAL) {
2546 layer.
data =
nullptr;
2552 if (
data !=
nullptr) {
2560 if (sharing_info !=
nullptr) {
2572 const int nulegacy_faces =
mesh->totface_legacy;
2578 MFace *mf = legacy_faces;
2579 for (
int i = 0;
i < nulegacy_faces;
i++, mf++) {
2592 const int numEdges = eh.
size();
2609 mesh->edge_data = edgeData;
2610 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)
blender::StringRef BKE_uv_map_edge_select_name_get(blender::StringRef uv_map_name, char *buffer)
blender::StringRef BKE_uv_map_vert_select_name_get(blender::StringRef 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)
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 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])
#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
char * STRNCPY(char(&dst)[N], const char *src)
@ MOD_WEIGHTEDNORMAL_KEEP_SHARP
@ eModifierType_NormalEdit
@ eModifierType_WeightedNormal
@ eSubsurfModifierFlag_UseCustomNormals
@ MOD_BEVEL_HARDEN_NORMALS
@ 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.
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
void reserve(const int64_t n)
Span< Key > as_span() const
bool contains(StringRef attribute_id) const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
#define MAX_CUSTOMDATA_LAYER_NAME
#define MEM_reallocN(vmemh, len)
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)
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
bNode * node_add_node(const bContext *C, bNodeTree &ntree, StringRef idname)
static bool is_auto_smooth_node_tree(const bNodeTree &group)
void mesh_custom_normals_to_legacy(MutableSpan< CustomDataLayer > corner_layers)
void mesh_sculpt_mask_to_legacy(MutableSpan< CustomDataLayer > vert_layers)
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)
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
MutableVArraySpan< T > span
static DynamicLibrary lib