FBX IO: Fix error importing BlendShapeChannels with extraneous FullWeights #104956

Merged
Thomas Barlow merged 6 commits from Mysteryem/blender-addons:fbx_fix_extra_fullweights_error into main 2023-11-05 10:16:56 +01:00
Showing only changes of commit 1ea4d1f110 - Show all commits

View File

@ -1962,19 +1962,28 @@ def blen_read_shapes(fbx_tmpl, fbx_data, objects, me, scene):
# Special case for Blender exported Shape Keys with a Vertex Group assigned. The Vertex Group weights are stored
# in the FullWeights array.
# XXX - It's possible, though very rare, to get a false positive here and create a Vertex Group when we
# shouldn't. This should only happen if there are extraneous FullWeights or there is a single FullWeight
# and its value is not 100.0.
is_vertex_weights = len(full_weights) == len(indices)
# Skip creating a Vertex Group if all the weights are 100.0 because such a Vertex Group has no effect and this
# avoids creating a Vertex Group for imported Shapes that only move a single vertex because their singular
# FullWeight is expected to always be 100.0.
if is_vertex_weights and np.any(full_weights != 100.0):
# Not doing the division in-place because it's technically possible for FBX Shape Keys to be used by more
# than one mesh, though this shouldn't be the case for Blender exported Shape Keys.
# shouldn't. This should only be possible when there are extraneous FullWeights or when there is a single
# FullWeight and its value is not 100.0.
if (
# Blender exported Shape Keys only ever export as 1 Shape per BlendShapeChannel.
num_shapes_assigned_to_channel == 1
# There should be one vertex weight for each vertex moved by the Shape.
and len(full_weights) == len(indices)
# Skip creating a Vertex Group when all the weights are 100.0 because such a Vertex Group has no effect.
# This also avoids creating a Vertex Group for imported Shapes that only move a single vertex because
# their BlendShapeChannel's singular FullWeight is expected to always be 100.0.
and not np.all(full_weights == 100.0)
# Blender vertex weights are always within the [0.0, 1.0] range (scaled to [0.0, 100.0] when saving to
# FBX). This can eliminate imported BlendShapeChannels from Unreal that have extraneous FullWeights
# because the extraneous values are usually negative.
and np.all((full_weights >= 0.0) & (full_weights <= 100.0))
):
# Not doing the division in-place because it's technically possible for FBX BlendShapeChannels to be used by
# more than one FBX BlendShape, though this shouldn't be the case for Blender exported Shape Keys.
vgweights = full_weights / 100.0
else:
vgweights = None
# There must be a FullWeight for each Shape. Any excess is ignored.
# There must be a FullWeight for each Shape. Any extra FullWeights are ignored.
assert(len(full_weights) >= num_shapes_assigned_to_channel)
# To add shape keys to the mesh, an Object using the mesh is needed.