diff options
Diffstat (limited to 'source/blender/blenkernel/intern/mesh_legacy_convert.cc')
-rw-r--r-- | source/blender/blenkernel/intern/mesh_legacy_convert.cc | 306 |
1 files changed, 267 insertions, 39 deletions
diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 479dd6a012a..627c0057a28 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -7,7 +7,7 @@ * Functions to convert mesh data to and from legacy formats like #MFace. */ -// #include <climits> +#define DNA_DEPRECATED_ALLOW #include "MEM_guardedalloc.h" @@ -18,9 +18,12 @@ #include "BLI_math.h" #include "BLI_memarena.h" #include "BLI_polyfill_2d.h" +#include "BLI_task.hh" #include "BLI_utildefines.h" +#include "BKE_attribute.hh" #include "BKE_customdata.h" +#include "BKE_global.h" #include "BKE_mesh.h" #include "BKE_mesh_legacy_convert.h" #include "BKE_multires.h" @@ -135,19 +138,19 @@ static void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *ldata, int to for (int i = 0; i < fdata->totlayer; i++) { if (fdata->layers[i].type == CD_MTFACE) { CustomData_add_layer_named( - ldata, CD_MLOOPUV, CD_CALLOC, nullptr, totloop, fdata->layers[i].name); + ldata, CD_MLOOPUV, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name); } else if (fdata->layers[i].type == CD_MCOL) { CustomData_add_layer_named( - ldata, CD_PROP_BYTE_COLOR, CD_CALLOC, nullptr, totloop, fdata->layers[i].name); + ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name); } else if (fdata->layers[i].type == CD_MDISPS) { CustomData_add_layer_named( - ldata, CD_MDISPS, CD_CALLOC, nullptr, totloop, fdata->layers[i].name); + ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name); } else if (fdata->layers[i].type == CD_TESSLOOPNORMAL) { CustomData_add_layer_named( - ldata, CD_NORMAL, CD_CALLOC, nullptr, totloop, fdata->layers[i].name); + ldata, CD_NORMAL, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name); } } } @@ -163,9 +166,7 @@ static void convert_mfaces_to_mpolys(ID *id, MEdge *medge, MFace *mface, int *r_totloop, - int *r_totpoly, - MLoop **r_mloop, - MPoly **r_mpoly) + int *r_totpoly) { MFace *mf; MLoop *ml, *mloop; @@ -183,8 +184,13 @@ static void convert_mfaces_to_mpolys(ID *id, CustomData_free(pdata, totpoly_i); totpoly = totface_i; - mpoly = (MPoly *)MEM_calloc_arrayN((size_t)totpoly, sizeof(MPoly), "mpoly converted"); - CustomData_add_layer(pdata, CD_MPOLY, CD_ASSIGN, mpoly, totpoly); + mpoly = (MPoly *)CustomData_add_layer(pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, totpoly); + int *material_indices = static_cast<int *>( + CustomData_get_layer_named(pdata, CD_PROP_INT32, "material_index")); + if (material_indices == nullptr) { + material_indices = static_cast<int *>(CustomData_add_layer_named( + pdata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, totpoly, "material_index")); + } numTex = CustomData_number_of_layers(fdata, CD_MTFACE); numCol = CustomData_number_of_layers(fdata, CD_MCOL); @@ -195,9 +201,7 @@ static void convert_mfaces_to_mpolys(ID *id, totloop += mf->v4 ? 4 : 3; } - mloop = (MLoop *)MEM_calloc_arrayN((size_t)totloop, sizeof(MLoop), "mloop converted"); - - CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop); + mloop = (MLoop *)CustomData_add_layer(ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, totloop); CustomData_to_bmeshpoly(fdata, ldata, totloop); @@ -230,7 +234,7 @@ static void convert_mfaces_to_mpolys(ID *id, mp->totloop = mf->v4 ? 4 : 3; - mp->mat_nr = mf->mat_nr; + material_indices[i] = mf->mat_nr; mp->flag = mf->flag; #define ML(v1, v2) \ @@ -269,12 +273,51 @@ static void convert_mfaces_to_mpolys(ID *id, *r_totpoly = totpoly; *r_totloop = totloop; - *r_mpoly = mpoly; - *r_mloop = mloop; #undef ME_FGON } +static void mesh_ensure_tessellation_customdata(Mesh *me) +{ + if (UNLIKELY((me->totface != 0) && (me->totpoly == 0))) { + /* Pass, otherwise this function clears 'mface' before + * versioning 'mface -> mpoly' code kicks in T30583. + * + * Callers could also check but safer to do here - campbell */ + } + else { + const int tottex_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); + const int totcol_original = CustomData_number_of_layers(&me->ldata, CD_PROP_BYTE_COLOR); + + const int tottex_tessface = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + const int totcol_tessface = CustomData_number_of_layers(&me->fdata, CD_MCOL); + + if (tottex_tessface != tottex_original || totcol_tessface != totcol_original) { + BKE_mesh_tessface_clear(me); + + BKE_mesh_add_mface_layers(&me->fdata, &me->ldata, me->totface); + + /* TODO: add some `--debug-mesh` option. */ + if (G.debug & G_DEBUG) { + /* NOTE(campbell): this warning may be un-called for if we are initializing the mesh for + * the first time from #BMesh, rather than giving a warning about this we could be smarter + * and check if there was any data to begin with, for now just print the warning with + * some info to help troubleshoot what's going on. */ + printf( + "%s: warning! Tessellation uvs or vcol data got out of sync, " + "had to reset!\n CD_MTFACE: %d != CD_MLOOPUV: %d || CD_MCOL: %d != " + "CD_PROP_BYTE_COLOR: " + "%d\n", + __func__, + tottex_tessface, + tottex_original, + totcol_tessface, + totcol_original); + } + } + } +} + void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh) { convert_mfaces_to_mpolys(&mesh->id, @@ -285,14 +328,12 @@ void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh) mesh->totface, mesh->totloop, mesh->totpoly, - mesh->medge, - mesh->mface, + mesh->edges_for_write().data(), + (MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE), &mesh->totloop, - &mesh->totpoly, - &mesh->mloop, - &mesh->mpoly); + &mesh->totpoly); - BKE_mesh_update_customdata_pointers(mesh, true); + mesh_ensure_tessellation_customdata(mesh); } /** @@ -344,16 +385,14 @@ void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh) mesh->totface, mesh->totloop, mesh->totpoly, - mesh->medge, - mesh->mface, + mesh->edges_for_write().data(), + (MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE), &mesh->totloop, - &mesh->totpoly, - &mesh->mloop, - &mesh->mpoly); + &mesh->totpoly); CustomData_bmesh_do_versions_update_active_layers(&mesh->fdata, &mesh->ldata); - BKE_mesh_update_customdata_pointers(mesh, true); + mesh_ensure_tessellation_customdata(mesh); } /** \} */ @@ -562,6 +601,8 @@ static int mesh_tessface_calc(CustomData *fdata, mpoly = (const MPoly *)CustomData_get_layer(pdata, CD_MPOLY); mloop = (const MLoop *)CustomData_get_layer(ldata, CD_MLOOP); + const int *material_indices = static_cast<const int *>( + CustomData_get_layer_named(pdata, CD_PROP_INT32, "material_index")); /* Allocate the length of `totfaces`, avoid many small reallocation's, * if all faces are triangles it will be correct, `quads == 2x` allocations. */ @@ -600,7 +641,7 @@ static int mesh_tessface_calc(CustomData *fdata, lidx[1] = l2; \ lidx[2] = l3; \ lidx[3] = 0; \ - mf->mat_nr = mp->mat_nr; \ + mf->mat_nr = material_indices ? material_indices[poly_index] : 0; \ mf->flag = mp->flag; \ mf->edcode = 0; \ (void)0 @@ -623,7 +664,7 @@ static int mesh_tessface_calc(CustomData *fdata, lidx[1] = l2; \ lidx[2] = l3; \ lidx[3] = l4; \ - mf->mat_nr = mp->mat_nr; \ + mf->mat_nr = material_indices ? material_indices[poly_index] : 0; \ mf->flag = mp->flag; \ mf->edcode = TESSFACE_IS_QUAD; \ (void)0 @@ -709,7 +750,7 @@ static int mesh_tessface_calc(CustomData *fdata, lidx[2] = l3; lidx[3] = 0; - mf->mat_nr = mp->mat_nr; + mf->mat_nr = material_indices ? material_indices[poly_index] : 0; mf->flag = mp->flag; mf->edcode = 0; @@ -783,12 +824,12 @@ void BKE_mesh_tessface_calc(Mesh *mesh) mesh->totface = mesh_tessface_calc(&mesh->fdata, &mesh->ldata, &mesh->pdata, - mesh->mvert, + BKE_mesh_verts_for_write(mesh), mesh->totface, mesh->totloop, mesh->totpoly); - BKE_mesh_update_customdata_pointers(mesh, true); + mesh_ensure_tessellation_customdata(mesh); } void BKE_mesh_tessface_ensure(struct Mesh *mesh) @@ -847,26 +888,27 @@ void BKE_mesh_add_mface_layers(CustomData *fdata, CustomData *ldata, int total) for (int i = 0; i < ldata->totlayer; i++) { if (ldata->layers[i].type == CD_MLOOPUV) { CustomData_add_layer_named( - fdata, CD_MTFACE, CD_CALLOC, nullptr, total, ldata->layers[i].name); + fdata, CD_MTFACE, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); } if (ldata->layers[i].type == CD_PROP_BYTE_COLOR) { - CustomData_add_layer_named(fdata, CD_MCOL, CD_CALLOC, nullptr, total, ldata->layers[i].name); + CustomData_add_layer_named( + fdata, CD_MCOL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); } else if (ldata->layers[i].type == CD_PREVIEW_MLOOPCOL) { CustomData_add_layer_named( - fdata, CD_PREVIEW_MCOL, CD_CALLOC, nullptr, total, ldata->layers[i].name); + fdata, CD_PREVIEW_MCOL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); } else if (ldata->layers[i].type == CD_ORIGSPACE_MLOOP) { CustomData_add_layer_named( - fdata, CD_ORIGSPACE, CD_CALLOC, nullptr, total, ldata->layers[i].name); + fdata, CD_ORIGSPACE, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); } else if (ldata->layers[i].type == CD_NORMAL) { CustomData_add_layer_named( - fdata, CD_TESSLOOPNORMAL, CD_CALLOC, nullptr, total, ldata->layers[i].name); + fdata, CD_TESSLOOPNORMAL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); } else if (ldata->layers[i].type == CD_TANGENT) { CustomData_add_layer_named( - fdata, CD_TANGENT, CD_CALLOC, nullptr, total, ldata->layers[i].name); + fdata, CD_TANGENT, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); } } @@ -874,3 +916,189 @@ void BKE_mesh_add_mface_layers(CustomData *fdata, CustomData *ldata, int total) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Bevel Weight Conversion + * \{ */ + +void BKE_mesh_legacy_bevel_weight_from_layers(Mesh *mesh) +{ + using namespace blender; + MutableSpan<MVert> verts = mesh->verts_for_write(); + if (const float *weights = static_cast<const float *>( + CustomData_get_layer(&mesh->vdata, CD_BWEIGHT))) { + mesh->cd_flag |= ME_CDFLAG_VERT_BWEIGHT; + for (const int i : verts.index_range()) { + verts[i].bweight_legacy = std::clamp(weights[i], 0.0f, 1.0f) * 255.0f; + } + } + else { + mesh->cd_flag &= ~ME_CDFLAG_VERT_BWEIGHT; + for (const int i : verts.index_range()) { + verts[i].bweight_legacy = 0; + } + } + MutableSpan<MEdge> edges = mesh->edges_for_write(); + if (const float *weights = static_cast<const float *>( + CustomData_get_layer(&mesh->edata, CD_BWEIGHT))) { + mesh->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; + for (const int i : edges.index_range()) { + edges[i].bweight_legacy = std::clamp(weights[i], 0.0f, 1.0f) * 255.0f; + } + } + else { + mesh->cd_flag &= ~ME_CDFLAG_EDGE_BWEIGHT; + for (const int i : edges.index_range()) { + edges[i].bweight_legacy = 0; + } + } +} + +void BKE_mesh_legacy_bevel_weight_to_layers(Mesh *mesh) +{ + using namespace blender; + const Span<MVert> verts = mesh->verts(); + if (mesh->cd_flag & ME_CDFLAG_VERT_BWEIGHT) { + float *weights = static_cast<float *>( + CustomData_add_layer(&mesh->vdata, CD_BWEIGHT, CD_CONSTRUCT, nullptr, verts.size())); + for (const int i : verts.index_range()) { + weights[i] = verts[i].bweight_legacy / 255.0f; + } + } + + const Span<MEdge> edges = mesh->edges(); + if (mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) { + float *weights = static_cast<float *>( + CustomData_add_layer(&mesh->edata, CD_BWEIGHT, CD_CONSTRUCT, nullptr, edges.size())); + for (const int i : edges.index_range()) { + weights[i] = edges[i].bweight_legacy / 255.0f; + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide Attribute and Legacy Flag Conversion + * \{ */ + +void BKE_mesh_legacy_convert_hide_layers_to_flags(Mesh *mesh) +{ + using namespace blender; + using namespace blender::bke; + const AttributeAccessor attributes = mesh->attributes(); + + MutableSpan<MVert> verts = mesh->verts_for_write(); + const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( + ".hide_vert", ATTR_DOMAIN_POINT, false); + threading::parallel_for(verts.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + SET_FLAG_FROM_TEST(verts[i].flag, hide_vert[i], ME_HIDE); + } + }); + + MutableSpan<MEdge> edges = mesh->edges_for_write(); + const VArray<bool> hide_edge = attributes.lookup_or_default<bool>( + ".hide_edge", ATTR_DOMAIN_EDGE, false); + threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + SET_FLAG_FROM_TEST(edges[i].flag, hide_edge[i], ME_HIDE); + } + }); + + MutableSpan<MPoly> polys = mesh->polys_for_write(); + const VArray<bool> hide_poly = attributes.lookup_or_default<bool>( + ".hide_poly", ATTR_DOMAIN_FACE, false); + threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + SET_FLAG_FROM_TEST(polys[i].flag, hide_poly[i], ME_HIDE); + } + }); +} + +void BKE_mesh_legacy_convert_flags_to_hide_layers(Mesh *mesh) +{ + using namespace blender; + using namespace blender::bke; + MutableAttributeAccessor attributes = mesh->attributes_for_write(); + + const Span<MVert> verts = mesh->verts(); + if (std::any_of( + verts.begin(), verts.end(), [](const MVert &vert) { return vert.flag & ME_HIDE; })) { + SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_only_span<bool>( + ".hide_vert", ATTR_DOMAIN_POINT); + threading::parallel_for(verts.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + hide_vert.span[i] = verts[i].flag & ME_HIDE; + } + }); + hide_vert.finish(); + } + + const Span<MEdge> edges = mesh->edges(); + if (std::any_of( + edges.begin(), edges.end(), [](const MEdge &edge) { return edge.flag & ME_HIDE; })) { + SpanAttributeWriter<bool> hide_edge = attributes.lookup_or_add_for_write_only_span<bool>( + ".hide_edge", ATTR_DOMAIN_EDGE); + threading::parallel_for(edges.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + hide_edge.span[i] = edges[i].flag & ME_HIDE; + } + }); + hide_edge.finish(); + } + + const Span<MPoly> polys = mesh->polys(); + if (std::any_of( + polys.begin(), polys.end(), [](const MPoly &poly) { return poly.flag & ME_HIDE; })) { + SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_only_span<bool>( + ".hide_poly", ATTR_DOMAIN_FACE); + threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + hide_poly.span[i] = polys[i].flag & ME_HIDE; + } + }); + hide_poly.finish(); + } +} + +/** \} */ +/* -------------------------------------------------------------------- */ +/** \name Material Index Conversion + * \{ */ + +void BKE_mesh_legacy_convert_material_indices_to_mpoly(Mesh *mesh) +{ + using namespace blender; + using namespace blender::bke; + const AttributeAccessor attributes = mesh->attributes(); + MutableSpan<MPoly> polys = mesh->polys_for_write(); + const VArray<int> material_indices = attributes.lookup_or_default<int>( + "material_index", ATTR_DOMAIN_FACE, 0); + threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + polys[i].mat_nr_legacy = material_indices[i]; + } + }); +} + +void BKE_mesh_legacy_convert_mpoly_to_material_indices(Mesh *mesh) +{ + using namespace blender; + using namespace blender::bke; + MutableAttributeAccessor attributes = mesh->attributes_for_write(); + const Span<MPoly> polys = mesh->polys(); + if (std::any_of( + polys.begin(), polys.end(), [](const MPoly &poly) { return poly.mat_nr_legacy != 0; })) { + SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_only_span<int>( + "material_index", ATTR_DOMAIN_FACE); + threading::parallel_for(polys.index_range(), 4096, [&](IndexRange range) { + for (const int i : range) { + material_indices.span[i] = polys[i].mat_nr_legacy; + } + }); + material_indices.finish(); + } +} + +/** \} */ |