From 61b22d27c8b9b64f04a7dd585eac11134184a235 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 23 Jun 2021 13:48:33 +1000 Subject: Fix T89249: incorrect mesh validate error with zeroed vertex normals It's not an error for centered vertices to have a zero normal. --- source/blender/blenkernel/intern/mesh_validate.c | 29 ++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 3570b1dd933..df84cf6607f 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -217,6 +217,16 @@ static int search_polyloop_cmp(const void *v1, const void *v2) * Validate the mesh, \a do_fixes requires \a mesh to be non-null. * * \return false if no changes needed to be made. + * + * Vertex Normals + * ============== + * + * While zeroed normals are checked, these checks aren't comprehensive. + * Technically, to detect errors here a normal recalculation and comparison is necessary. + * However this function is mainly to prevent severe errors in geometry + * (invalid data that will crash Blender, or cause some features to behave incorrectly), + * not to detect subtle differences in the resulting normals which could be caused + * by importers that load normals (for example). */ /* NOLINTNEXTLINE: readability-function-size */ bool BKE_mesh_validate_arrays(Mesh *mesh, @@ -328,10 +338,21 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, } if (fix_normal) { - PRINT_ERR("\tVertex %u: has zero normal, assuming Z-up normal", i); - if (do_fixes) { - mv->no[2] = SHRT_MAX; - fix_flag.verts = true; + /* If the vertex normal accumulates to zero or isn't part of a face, the location is used. + * When the location is also zero, a zero normal warning should not be raised. + * since this is the expected behavior of normal calculation. + * + * This avoids false positives but isn't foolproof as it's possible the vertex + * is part of a polygon that has a normal which this vertex should be using, + * although it's also possible degenerate/opposite faces accumulate to a zero vector. + * To detect this a full normal recalculation would be needed, which is out of scope + * for a basic validity check (see "Vertex Normal" in the doc-string). */ + if (!is_zero_v3(mv->co)) { + PRINT_ERR("\tVertex %u: has zero normal, assuming Z-up normal", i); + if (do_fixes) { + mv->no[2] = SHRT_MAX; + fix_flag.verts = true; + } } } } -- cgit v1.2.3