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;
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++) {
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;
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++) {
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],
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++) {
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
1253 reinterpret_cast<float(*)[3]
>(mesh->vert_positions_for_write().data()),
1285 if (std::any_of(polys.
begin(), polys.
end(), [](
const MPoly &poly) {
1286 return !(poly.flag_legacy & ME_SMOOTH);
1292 for (const int i : range) {
1293 sharp_faces.span[i] = !(polys[i].flag_legacy & ME_SMOOTH);
1296 sharp_faces.finish();
1299 attributes.remove(
"sharp_face");
1312 if (
mesh->attributes().contains(
".sculpt_face_set")) {
1315 void *faceset_data =
nullptr;
1319 if (layer.
type == CD_SCULPT_FACE_SETS) {
1320 faceset_data = layer.
data;
1322 layer.
data =
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;
1357 if (layer.
type == CD_FACEMAP) {
1358 data =
static_cast<int *
>(layer.
data);
1360 layer.
data =
nullptr;
1372 if (sharing_info !=
nullptr) {
1378 if (
data[i] == -1) {
1386 for (
const auto item : groups.
items()) {
1390 attribute.span.fill_indices(item.value.as_span(),
true);
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;
1437 if (
mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
1438 float *weights =
static_cast<float *
>(
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) {
1461 layer.
data =
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")) {
1482 if (!
mesh->attributes().contains(
"bevel_weight_edge")) {
1504 if (
mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) {
1505 float *creases =
static_cast<float *
>(
1508 creases[i] = edges[i].crease_legacy / 255.0f;
1515 if (!
mesh->attributes().contains(
"crease_vert")) {
1519 if (!
mesh->attributes().contains(
"crease_edge")) {
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;
1550 for (const int i : range) {
1551 sharp_edges.span[i] = edges[i].flag_legacy & ME_SHARP;
1554 sharp_edges.finish();
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;
1583 for (const int i : range) {
1584 uv_seams.span[i] = edges[i].flag_legacy & ME_SEAM;
1608 if (std::any_of(
verts.begin(),
verts.end(), [](
const MVert &vert) {
1609 return vert.flag_legacy & ME_HIDE;
1615 for (const int i : range) {
1616 hide_vert.span[i] = verts[i].flag_legacy & ME_HIDE;
1624 if (std::any_of(edges.begin(), edges.end(), [](
const MEdge &edge) {
1625 return edge.flag_legacy & ME_HIDE;
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;
1649 for (const int i : range) {
1650 hide_poly.span[i] = polys[i].flag_legacy & ME_HIDE;
1675 polys.
begin(), polys.
end(), [](
const MPoly &poly) { return poly.mat_nr_legacy != 0; }))
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 *
>(
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) {
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;
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; }))
1843 for (const int i : range) {
1844 select_vert.span[i] = verts[i].flag_legacy & SELECT;
1847 select_vert.finish();
1852 if (std::any_of(edges.begin(), edges.end(), [](
const MEdge &edge) {
1853 return edge.flag_legacy & SELECT;
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;
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 *
>(
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 *
>(
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) {
1962 if (
data.layers[i].flag & CD_FLAG_COLOR_ACTIVE) {
1969 if (!
mesh->active_color_attribute) {
1975 if (!
mesh->active_color_attribute) {
1983 if (!
mesh->default_color_attribute) {
1985 if (
data.layers[i].flag & CD_FLAG_COLOR_RENDER) {
1992 if (!
mesh->default_color_attribute) {
1998 if (!
mesh->default_color_attribute) {
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);
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;
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");
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;
2266 if (
nodes.size() != 10) {
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]) {
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;
2363 const auto add_node_group = [&](
Library *owner_library) {
2370 if (existing_group->id.lib != owner_library) {
2374 group_by_library.
add_new(owner_library, existing_group);
2375 return existing_group;
2381 group_by_library.
add_new(owner_library, new_group);
2390 const float angle =
mesh->smoothresh_legacy;
2399 if (has_custom_normals) {
2408 has_custom_normals =
true;
2413 has_custom_normals =
true;
2429 has_custom_normals =
true;
2438 if (has_custom_normals) {
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;
2494 if (layer.
type == CD_PAINT_MASK) {
2497 layer.
data =
nullptr;
2503 if (
data !=
nullptr) {
2507 if (sharing_info !=
nullptr) {
2519 const int nulegacy_faces =
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_WEIGHTEDNORMAL_KEEP_SHARP
@ MOD_BEVEL_HARDEN_NORMALS
@ eModifierType_NormalEdit
@ eModifierType_WeightedNormal
@ 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)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Map
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
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(const 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)
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)
void fill_index_range(MutableSpan< T > span, const T start=0)
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)
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
static DynamicLibrary lib