diff options
Diffstat (limited to 'source/blender/blenkernel/intern/mesh_validate.cc')
-rw-r--r-- | source/blender/blenkernel/intern/mesh_validate.cc | 188 |
1 files changed, 101 insertions, 87 deletions
diff --git a/source/blender/blenkernel/intern/mesh_validate.cc b/source/blender/blenkernel/intern/mesh_validate.cc index 9b2697ecc84..47de7245ccc 100644 --- a/source/blender/blenkernel/intern/mesh_validate.cc +++ b/source/blender/blenkernel/intern/mesh_validate.cc @@ -24,6 +24,7 @@ #include "BLI_math_vector.h" #include "BLI_utildefines.h" +#include "BKE_attribute.hh" #include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_mesh.h" @@ -32,6 +33,9 @@ #include "MEM_guardedalloc.h" +using blender::MutableSpan; +using blender::Span; + /* loop v/e are unsigned, so using max uint_32 value as invalid marker... */ #define INVALID_LOOP_EDGE_MARKER 4294967295u @@ -238,6 +242,10 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, } \ (void)0 + blender::bke::AttributeWriter<int> material_indices = + mesh->attributes_for_write().lookup_for_write<int>("material_index"); + blender::MutableVArraySpan<int> material_indices_span(material_indices.varray); + MVert *mv = mverts; MEdge *me; MLoop *ml; @@ -559,10 +567,10 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, /* Material index, isolated from other tests here. While large indices are clamped, * negative indices aren't supported by drawing, exporters etc. * To check the indices are in range, use #BKE_mesh_validate_material_indices */ - if (mp->mat_nr < 0) { - PRINT_ERR("\tPoly %u has invalid material (%d)", sp->index, mp->mat_nr); + if (material_indices && material_indices_span[i] < 0) { + PRINT_ERR("\tPoly %u has invalid material (%d)", sp->index, material_indices_span[i]); if (do_fixes) { - mp->mat_nr = 0; + material_indices_span[i] = 0; } } @@ -916,6 +924,9 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, } } + material_indices_span.save(); + material_indices.finish(); + PRINT_MSG("%s: finished\n\n", __func__); *r_changed = (fix_flag.as_flag || free_flag.as_flag || recalc_flag.as_flag); @@ -1001,10 +1012,6 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData_MeshMasks mask = {0}; if (check_meshmask) { mask = CD_MASK_MESH; - /* Normal data isn't in the mask since it is derived data, - * but it is valid and should not be removed. */ - mask.vmask |= CD_MASK_NORMAL; - mask.pmask |= CD_MASK_NORMAL; } is_valid &= mesh_validate_customdata( @@ -1017,7 +1024,6 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, pdata, mask.pmask, totpoly, do_verbose, do_fixes, &is_change_p); const int tot_uvloop = CustomData_number_of_layers(ldata, CD_MLOOPUV); - const int tot_vcolloop = CustomData_number_of_layers(ldata, CD_PROP_BYTE_COLOR); if (tot_uvloop > MAX_MTFACE) { PRINT_ERR( "\tMore UV layers than %d allowed, %d last ones won't be available for render, shaders, " @@ -1025,13 +1031,6 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, MAX_MTFACE, tot_uvloop - MAX_MTFACE); } - if (tot_vcolloop > MAX_MCOL) { - PRINT_ERR( - "\tMore VCol layers than %d allowed, %d last ones won't be available for render, shaders, " - "etc.\n", - MAX_MCOL, - tot_vcolloop - MAX_MCOL); - } /* check indices of clone/stencil */ if (do_fixes && CustomData_get_clone_layer(ldata, CD_MLOOPUV) >= tot_uvloop) { @@ -1068,19 +1067,23 @@ bool BKE_mesh_validate(Mesh *me, const bool do_verbose, const bool cddata_check_ do_verbose, true, &changed); + MutableSpan<MVert> verts = me->verts_for_write(); + MutableSpan<MEdge> edges = me->edges_for_write(); + MutableSpan<MPoly> polys = me->polys_for_write(); + MutableSpan<MLoop> loops = me->loops_for_write(); BKE_mesh_validate_arrays(me, - me->mvert, - me->totvert, - me->medge, - me->totedge, - me->mface, + verts.data(), + verts.size(), + edges.data(), + edges.size(), + (MFace *)CustomData_get_layer(&me->fdata, CD_MFACE), me->totface, - me->mloop, - me->totloop, - me->mpoly, - me->totpoly, - me->dvert, + loops.data(), + loops.size(), + polys.data(), + polys.size(), + me->deform_verts_for_write().data(), do_verbose, true, &changed); @@ -1117,18 +1120,23 @@ bool BKE_mesh_is_valid(Mesh *me) do_fixes, &changed); + MutableSpan<MVert> verts = me->verts_for_write(); + MutableSpan<MEdge> edges = me->edges_for_write(); + MutableSpan<MPoly> polys = me->polys_for_write(); + MutableSpan<MLoop> loops = me->loops_for_write(); + is_valid &= BKE_mesh_validate_arrays(me, - me->mvert, - me->totvert, - me->medge, - me->totedge, - me->mface, + verts.data(), + verts.size(), + edges.data(), + edges.size(), + (MFace *)CustomData_get_layer(&me->fdata, CD_MFACE), me->totface, - me->mloop, - me->totloop, - me->mpoly, - me->totpoly, - me->dvert, + loops.data(), + loops.size(), + polys.data(), + polys.size(), + me->deform_verts_for_write().data(), do_verbose, do_fixes, &changed); @@ -1140,19 +1148,20 @@ bool BKE_mesh_is_valid(Mesh *me) bool BKE_mesh_validate_material_indices(Mesh *me) { - /* Cast to unsigned to catch negative indices too. */ - const uint16_t mat_nr_max = max_ii(0, me->totcol - 1); - MPoly *mp; - const int totpoly = me->totpoly; - int i; + const int mat_nr_max = max_ii(0, me->totcol - 1); bool is_valid = true; - for (mp = me->mpoly, i = 0; i < totpoly; i++, mp++) { - if ((uint16_t)mp->mat_nr > mat_nr_max) { - mp->mat_nr = 0; + blender::bke::AttributeWriter<int> material_indices = + me->attributes_for_write().lookup_for_write<int>("material_index"); + blender::MutableVArraySpan<int> material_indices_span(material_indices.varray); + for (const int i : material_indices_span.index_range()) { + if (material_indices_span[i] < 0 || material_indices_span[i] > mat_nr_max) { + material_indices_span[i] = 0; is_valid = false; } } + material_indices_span.save(); + material_indices.finish(); if (!is_valid) { DEG_id_tag_update(&me->id, ID_RECALC_GEOMETRY_ALL_MODES); @@ -1173,11 +1182,12 @@ void BKE_mesh_strip_loose_faces(Mesh *me) /* NOTE: We need to keep this for edge creation (for now?), and some old `readfile.c` code. */ MFace *f; int a, b; + MFace *mfaces = (MFace *)CustomData_get_layer(&me->fdata, CD_MFACE); - for (a = b = 0, f = me->mface; a < me->totface; a++, f++) { + for (a = b = 0, f = mfaces; a < me->totface; a++, f++) { if (f->v3) { if (a != b) { - memcpy(&me->mface[b], f, sizeof(me->mface[b])); + memcpy(&mfaces[b], f, sizeof(mfaces[b])); CustomData_copy_data(&me->fdata, &me->fdata, a, b, 1); } b++; @@ -1191,13 +1201,16 @@ void BKE_mesh_strip_loose_faces(Mesh *me) void BKE_mesh_strip_loose_polysloops(Mesh *me) { + MutableSpan<MPoly> polys = me->polys_for_write(); + MutableSpan<MLoop> loops = me->loops_for_write(); + MPoly *p; MLoop *l; int a, b; /* New loops idx! */ int *new_idx = (int *)MEM_mallocN(sizeof(int) * me->totloop, __func__); - for (a = b = 0, p = me->mpoly; a < me->totpoly; a++, p++) { + for (a = b = 0, p = polys.data(); a < me->totpoly; a++, p++) { bool invalid = false; int i = p->loopstart; int stop = i + p->totloop; @@ -1206,7 +1219,7 @@ void BKE_mesh_strip_loose_polysloops(Mesh *me) invalid = true; } else { - l = &me->mloop[i]; + l = &loops[i]; i = stop - i; /* If one of the poly's loops is invalid, the whole poly is invalid! */ for (; i--; l++) { @@ -1219,7 +1232,7 @@ void BKE_mesh_strip_loose_polysloops(Mesh *me) if (p->totloop >= 3 && !invalid) { if (a != b) { - memcpy(&me->mpoly[b], p, sizeof(me->mpoly[b])); + memcpy(&polys[b], p, sizeof(polys[b])); CustomData_copy_data(&me->pdata, &me->pdata, a, b, 1); } b++; @@ -1231,10 +1244,10 @@ void BKE_mesh_strip_loose_polysloops(Mesh *me) } /* And now, get rid of invalid loops. */ - for (a = b = 0, l = me->mloop; a < me->totloop; a++, l++) { + for (a = b = 0, l = loops.data(); a < me->totloop; a++, l++) { if (l->e != INVALID_LOOP_EDGE_MARKER) { if (a != b) { - memcpy(&me->mloop[b], l, sizeof(me->mloop[b])); + memcpy(&loops[b], l, sizeof(loops[b])); CustomData_copy_data(&me->ldata, &me->ldata, a, b, 1); } new_idx[a] = b; @@ -1253,8 +1266,8 @@ void BKE_mesh_strip_loose_polysloops(Mesh *me) /* And now, update polys' start loop index. */ /* NOTE: At this point, there should never be any poly using a striped loop! */ - for (a = 0, p = me->mpoly; a < me->totpoly; a++, p++) { - p->loopstart = new_idx[p->loopstart]; + for (const int i : polys.index_range()) { + polys[i].loopstart = new_idx[polys[i].loopstart]; } MEM_freeN(new_idx); @@ -1263,14 +1276,14 @@ void BKE_mesh_strip_loose_polysloops(Mesh *me) void BKE_mesh_strip_loose_edges(Mesh *me) { MEdge *e; - MLoop *l; int a, b; uint *new_idx = (uint *)MEM_mallocN(sizeof(int) * me->totedge, __func__); + MutableSpan<MEdge> edges = me->edges_for_write(); - for (a = b = 0, e = me->medge; a < me->totedge; a++, e++) { + for (a = b = 0, e = edges.data(); a < me->totedge; a++, e++) { if (e->v1 != e->v2) { if (a != b) { - memcpy(&me->medge[b], e, sizeof(me->medge[b])); + memcpy(&edges[b], e, sizeof(edges[b])); CustomData_copy_data(&me->edata, &me->edata, a, b, 1); } new_idx[a] = b; @@ -1288,8 +1301,9 @@ void BKE_mesh_strip_loose_edges(Mesh *me) /* And now, update loops' edge indices. */ /* XXX We hope no loop was pointing to a striped edge! * Else, its e will be set to INVALID_LOOP_EDGE_MARKER :/ */ - for (a = 0, l = me->mloop; a < me->totloop; a++, l++) { - l->e = new_idx[l->e]; + MutableSpan<MLoop> loops = me->loops_for_write(); + for (MLoop &loop : loops) { + loop.e = new_idx[loop.e]; } MEM_freeN(new_idx); @@ -1347,10 +1361,10 @@ static int vergedgesort(const void *v1, const void *v2) /* Create edges based on known verts and faces, * this function is only used when loading very old blend files */ -static void mesh_calc_edges_mdata(MVert *UNUSED(allvert), - MFace *allface, +static void mesh_calc_edges_mdata(const MVert *UNUSED(allvert), + const MFace *allface, MLoop *allloop, - MPoly *allpoly, + const MPoly *allpoly, int UNUSED(totvert), int totface, int UNUSED(totloop), @@ -1359,8 +1373,8 @@ static void mesh_calc_edges_mdata(MVert *UNUSED(allvert), MEdge **r_medge, int *r_totedge) { - MPoly *mpoly; - MFace *mface; + const MPoly *mpoly; + const MFace *mface; MEdge *medge, *med; EdgeHash *hash; struct EdgeSort *edsort, *ed; @@ -1483,28 +1497,29 @@ void BKE_mesh_calc_edges_legacy(Mesh *me, const bool use_old) { MEdge *medge; int totedge = 0; - - mesh_calc_edges_mdata(me->mvert, - me->mface, - me->mloop, - me->mpoly, - me->totvert, + const Span<MVert> verts = me->verts(); + const Span<MPoly> polys = me->polys(); + MutableSpan<MLoop> loops = me->loops_for_write(); + + mesh_calc_edges_mdata(verts.data(), + (MFace *)CustomData_get_layer(&me->fdata, CD_MFACE), + loops.data(), + polys.data(), + verts.size(), me->totface, - me->totloop, - me->totpoly, + loops.size(), + polys.size(), use_old, &medge, &totedge); if (totedge == 0) { /* flag that mesh has edges */ - me->medge = medge; me->totedge = 0; return; } medge = (MEdge *)CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, totedge); - me->medge = medge; me->totedge = totedge; BKE_mesh_strip_loose_faces(me); @@ -1512,18 +1527,18 @@ void BKE_mesh_calc_edges_legacy(Mesh *me, const bool use_old) void BKE_mesh_calc_edges_loose(Mesh *mesh) { - MEdge *med = mesh->medge; - for (int i = 0; i < mesh->totedge; i++, med++) { - med->flag |= ME_LOOSEEDGE; + const Span<MLoop> loops = mesh->loops(); + MutableSpan<MEdge> edges = mesh->edges_for_write(); + + for (const int i : edges.index_range()) { + edges[i].flag |= ME_LOOSEEDGE; } - MLoop *ml = mesh->mloop; - for (int i = 0; i < mesh->totloop; i++, ml++) { - mesh->medge[ml->e].flag &= ~ME_LOOSEEDGE; + for (const int i : loops.index_range()) { + edges[loops[i].e].flag &= ~ME_LOOSEEDGE; } - med = mesh->medge; - for (int i = 0; i < mesh->totedge; i++, med++) { - if (med->flag & ME_LOOSEEDGE) { - med->flag |= ME_EDGEDRAW; + for (const int i : edges.index_range()) { + if (edges[i].flag & ME_LOOSEEDGE) { + edges[i].flag |= ME_EDGEDRAW; } } } @@ -1532,8 +1547,9 @@ void BKE_mesh_calc_edges_tessface(Mesh *mesh) { const int numFaces = mesh->totface; EdgeSet *eh = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(numFaces)); + MFace *mfaces = (MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE); - MFace *mf = mesh->mface; + MFace *mf = mfaces; for (int i = 0; i < numFaces; i++, mf++) { BLI_edgeset_add(eh, mf->v1, mf->v2); BLI_edgeset_add(eh, mf->v2, mf->v3); @@ -1552,8 +1568,8 @@ void BKE_mesh_calc_edges_tessface(Mesh *mesh) /* write new edges into a temporary CustomData */ CustomData edgeData; CustomData_reset(&edgeData); - CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, nullptr, numEdges); - CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, nullptr, numEdges); + CustomData_add_layer(&edgeData, CD_MEDGE, CD_SET_DEFAULT, nullptr, numEdges); + CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_SET_DEFAULT, nullptr, numEdges); MEdge *med = (MEdge *)CustomData_get_layer(&edgeData, CD_MEDGE); int *index = (int *)CustomData_get_layer(&edgeData, CD_ORIGINDEX); @@ -1573,8 +1589,6 @@ void BKE_mesh_calc_edges_tessface(Mesh *mesh) mesh->edata = edgeData; mesh->totedge = numEdges; - mesh->medge = (MEdge *)CustomData_get_layer(&mesh->edata, CD_MEDGE); - BLI_edgeset_free(eh); } |