From 6b5acc2aebff63aad548cd2e9e06e6d25d4c5d82 Mon Sep 17 00:00:00 2001 From: Mikhail Matrosov Date: Sat, 23 Sep 2023 23:06:23 +0300 Subject: [PATCH 1/2] FBX: Fix #104909: AssertionError importing shapekeys --- io_scene_fbx/import_fbx.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/io_scene_fbx/import_fbx.py b/io_scene_fbx/import_fbx.py index 6196e19c8..70343a360 100644 --- a/io_scene_fbx/import_fbx.py +++ b/io_scene_fbx/import_fbx.py @@ -1931,7 +1931,10 @@ def blen_read_shapes(fbx_tmpl, fbx_data, objects, me, scene): # will be clamped, and we'll print a warning message to the console. shape_key_values_in_range = True bc_uuid_to_keyblocks = {} - for bc_uuid, fbx_sdata, fbx_bcdata in fbx_data: + for k, v in fbx_data.items(): + bc_uuid = k[0] + fbx_sdata, fbx_bcdata = v + elem_name_utf8 = elem_name_ensure_class(fbx_sdata, b'Geometry') indices = elem_prop_first(elem_find_first(fbx_sdata, b'Indexes')) dvcos = elem_prop_first(elem_find_first(fbx_sdata, b'Vertices')) @@ -1961,6 +1964,14 @@ def blen_read_shapes(fbx_tmpl, fbx_data, objects, me, scene): if len(vgweights) == 1 and nbr_indices > 1: vgweights = np.full_like(indices, vgweights[0], dtype=vgweights.dtype) + # Special case for trimmed weights with trailing zeroes + if len(vgweights) != nbr_indices: + # Pad with zeros + new_vgweights = np.zeros_like(indices, dtype=vgweights.dtype) + n = min(len(vgweights), nbr_indices) + new_vgweights[:n] = vgweights[:n] + vgweights = new_vgweights + assert(len(vgweights) == nbr_indices == len(dvcos)) # To add shape keys to the mesh, an Object using the mesh is needed. @@ -3506,11 +3517,12 @@ def load(operator, context, filepath="", node = fbx_helper_nodes[o_uuid] if node: objects.append(node) - shapes_list = [] - mesh_to_shapes[bl_mdata] = (objects, shapes_list) + shapes = {} + mesh_to_shapes[bl_mdata] = (objects, shapes) else: - shapes_list = mesh_to_shapes[bl_mdata][1] - shapes_list.append((bc_uuid, fbx_sdata, fbx_bcdata)) + shapes = mesh_to_shapes[bl_mdata][1] + # Dict to avoid duplicates + shapes[(bc_uuid, id(fbx_sdata), id(fbx_bcdata))] = (fbx_sdata, fbx_bcdata) # BlendShape deformers are only here to connect BlendShapeChannels to meshes, nothing else to do. # Iterate through each mesh and create its shape keys -- 2.30.2 From 39b507610de324308a6279eb6decd2a23b0149e8 Mon Sep 17 00:00:00 2001 From: Mikhail Matrosov Date: Sat, 7 Oct 2023 22:45:22 +0300 Subject: [PATCH 2/2] Splitting the PR: only Avoiding AssertionError when FBX has in-between shapes left --- io_scene_fbx/import_fbx.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/io_scene_fbx/import_fbx.py b/io_scene_fbx/import_fbx.py index 70343a360..56810734c 100644 --- a/io_scene_fbx/import_fbx.py +++ b/io_scene_fbx/import_fbx.py @@ -1931,10 +1931,7 @@ def blen_read_shapes(fbx_tmpl, fbx_data, objects, me, scene): # will be clamped, and we'll print a warning message to the console. shape_key_values_in_range = True bc_uuid_to_keyblocks = {} - for k, v in fbx_data.items(): - bc_uuid = k[0] - fbx_sdata, fbx_bcdata = v - + for bc_uuid, fbx_sdata, fbx_bcdata in fbx_data: elem_name_utf8 = elem_name_ensure_class(fbx_sdata, b'Geometry') indices = elem_prop_first(elem_find_first(fbx_sdata, b'Indexes')) dvcos = elem_prop_first(elem_find_first(fbx_sdata, b'Vertices')) @@ -3517,12 +3514,11 @@ def load(operator, context, filepath="", node = fbx_helper_nodes[o_uuid] if node: objects.append(node) - shapes = {} - mesh_to_shapes[bl_mdata] = (objects, shapes) + shapes_list = [] + mesh_to_shapes[bl_mdata] = (objects, shapes_list) else: - shapes = mesh_to_shapes[bl_mdata][1] - # Dict to avoid duplicates - shapes[(bc_uuid, id(fbx_sdata), id(fbx_bcdata))] = (fbx_sdata, fbx_bcdata) + shapes_list = mesh_to_shapes[bl_mdata][1] + shapes_list.append((bc_uuid, fbx_sdata, fbx_bcdata)) # BlendShape deformers are only here to connect BlendShapeChannels to meshes, nothing else to do. # Iterate through each mesh and create its shape keys -- 2.30.2