Fix #120590: FBX import gives sharp edges for non-normalized normals

A few files included in reports contained normals that were not normalized.
In order to contain consistent normals around smooth corner fans, sharp
edges are added when neighboring corner normals aren't close enough.
Non-unit-vector normals also triggered this check.

Blender used to do this implicitly when the derived `MeshLoop.normal`
value was set. That API has been changed already, and it's clearer if the
addon provides normalized normals, so this PR adds a normalization
step to the FBX importer.

Pull Request: https://projects.blender.org/blender/blender/pulls/124261
This commit is contained in:
Hans Goudey
2024-07-08 17:09:22 +02:00
committed by Hans Goudey
parent 9d3dc77e05
commit 4e6a962b2b

View File

@@ -1784,6 +1784,11 @@ def blen_read_geom_layer_normal(fbx_obj, mesh, xform=None):
return False
def normalize_vecs(vectors):
norms = np.linalg.norm(vectors, axis=1, keepdims=True)
np.divide(vectors, norms, out=vectors, where=norms != 0)
def blen_read_geom(fbx_tmpl, fbx_obj, settings):
# Vertices are in object space, but we are post-multiplying all transforms with the inverse of the
# global matrix, so we need to apply the global matrix to the vertices to get the correct result.
@@ -1914,6 +1919,10 @@ def blen_read_geom(fbx_tmpl, fbx_obj, settings):
clnors = np.empty(len(mesh.loops) * 3, dtype=bl_nors_dtype)
mesh.attributes["temp_custom_normals"].data.foreach_get("vector", clnors)
clnors = clnors.reshape(len(mesh.loops), 3)
normalize_vecs(clnors)
clnors = clnors.reshape(len(mesh.loops) * 3)
# Iterating clnors into a nested tuple first is faster than passing clnors.reshape(-1, 3) directly into
# normals_split_custom_set. We use clnors.data since it is a memoryview, which is faster to iterate than clnors.
mesh.normals_split_custom_set(tuple(zip(*(iter(clnors.data),) * 3)))