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 # Special case for Blender exported Shape Keys with a Vertex Group assigned. The Vertex Group weights are stored
# in the FullWeights array. # in the FullWeights array.
# XXX - It's possible, though very rare, to get a false positive here and create a Vertex Group when we # 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 # shouldn't. This should only be possible when there are extraneous FullWeights or when there is a single
# and its value is not 100.0. # FullWeight and its value is not 100.0.
is_vertex_weights = len(full_weights) == len(indices) if (
# Skip creating a Vertex Group if all the weights are 100.0 because such a Vertex Group has no effect and this # Blender exported Shape Keys only ever export as 1 Shape per BlendShapeChannel.
# avoids creating a Vertex Group for imported Shapes that only move a single vertex because their singular num_shapes_assigned_to_channel == 1

I'm not very happy about this possible false positive.
It should be noted that most software will truncate the FullWeights array to the same length as the number of Shapes, so the Blender Vertex Group weights will not often be preserved. External software can also read the Vertex Group weights as FullWeights values which can have unintended effects.

A few ideas:

  • Add a new import option that controls whether importing FullWeights as Vertex Group weights is enabled.
    • FullWeights as Vertex Groups is a really niche feature that is only really relevant for importing Blender exported .fbx back into Blender, so adding an importer option sounds like overkill.
  • Only import as Vertex Group weights when the the creator of the .fbx file is Blender.
    • If there is external software that has added support for propagating Blender Vertex Group weights, this could break support
  • Entirely remove support for exporting/importing FullWeights as Vertex Group weights
    • Just because it's a really niche feature doesn't mean nobody has been using it
    • While there's not much code to change, it's probably too big of a change for 4.0 at this point.
I'm not very happy about this possible false positive. It should be noted that most software will truncate the FullWeights array to the same length as the number of Shapes, so the Blender Vertex Group weights will not often be preserved. External software can also read the Vertex Group weights as FullWeights values which can have unintended effects. A few ideas: - Add a new import option that controls whether importing FullWeights as Vertex Group weights is enabled. - FullWeights as Vertex Groups is a really niche feature that is only really relevant for importing Blender exported .fbx back into Blender, so adding an importer option sounds like overkill. - Only import as Vertex Group weights when the the creator of the .fbx file is Blender. - If there is external software that has added support for propagating Blender Vertex Group weights, this could break support - Entirely remove support for exporting/importing FullWeights as Vertex Group weights - Just because it's a really niche feature doesn't mean nobody has been using it - While there's not much code to change, it's probably too big of a change for 4.0 at this point.

I've added an extra check that all the FullWeights are within the [0.0, 100.0] range, which prevents the false positives when importing the .fbx files in #104909

I've added an extra check that all the FullWeights are within the [0.0, 100.0] range, which prevents the false positives when importing the .fbx files in https://projects.blender.org/blender/blender-addons/issues/104909
# FullWeight is expected to always be 100.0. # There should be one vertex weight for each vertex moved by the Shape.
if is_vertex_weights and np.any(full_weights != 100.0): and len(full_weights) == len(indices)
# Not doing the division in-place because it's technically possible for FBX Shape Keys to be used by more # Skip creating a Vertex Group when all the weights are 100.0 because such a Vertex Group has no effect.
# than one mesh, though this shouldn't be the case for Blender exported Shape Keys. # 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 vgweights = full_weights / 100.0
else: else:
vgweights = None 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) assert(len(full_weights) >= num_shapes_assigned_to_channel)
# To add shape keys to the mesh, an Object using the mesh is needed. # To add shape keys to the mesh, an Object using the mesh is needed.