From eb96ef2dff899425a2d8324303dc6a39d23da61b Mon Sep 17 00:00:00 2001 From: Aras Pranckevicius Date: Mon, 1 Sep 2025 19:39:54 +0200 Subject: [PATCH] Fix #145116: new FBX importer does not handle geometry transform + instancing properly When instanced meshes were using FBX geometric transforms, the code was not telling ufbx to create proper adjustment helper nodes due to UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY_NO_FALLBACK flag. That flag was put in earlier, before import of armatures was solidified, turns out using the proper flag (UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY) is not a problem anymore. Pull Request: https://projects.blender.org/blender/blender/pulls/145527 --- source/blender/io/fbx/importer/fbx_import.cc | 6 +---- .../io/fbx/importer/fbx_import_armature.cc | 10 ++++++- .../io/fbx/importer/fbx_import_mesh.cc | 10 ++++++- ...x_max_geometry_transform_instances_77b.txt | 26 +++++++++++++++---- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/source/blender/io/fbx/importer/fbx_import.cc b/source/blender/io/fbx/importer/fbx_import.cc index a909506014a..2132b51572f 100644 --- a/source/blender/io/fbx/importer/fbx_import.cc +++ b/source/blender/io/fbx/importer/fbx_import.cc @@ -347,11 +347,7 @@ void importer_main(Main *bmain, Scene *scene, ViewLayer *view_layer, const FBXIm opts.clean_skin_weights = true; opts.use_blender_pbr_material = true; - /* Do geometry modifications for "geometric transforms" cases; when it cannot do that - * (e.g. instancing etc.), do not insert helper nodes to account for that. Helper nodes currently - * cause armatures/skins to not import correctly, when inserted in the middle of bone chain. */ - opts.geometry_transform_handling = UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY_NO_FALLBACK; - + opts.geometry_transform_handling = UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY; opts.pivot_handling = UFBX_PIVOT_HANDLING_ADJUST_TO_ROTATION_PIVOT; opts.space_conversion = UFBX_SPACE_CONVERSION_ADJUST_TRANSFORMS; diff --git a/source/blender/io/fbx/importer/fbx_import_armature.cc b/source/blender/io/fbx/importer/fbx_import_armature.cc index 2146aabbd29..2171efde812 100644 --- a/source/blender/io/fbx/importer/fbx_import_armature.cc +++ b/source/blender/io/fbx/importer/fbx_import_armature.cc @@ -109,7 +109,15 @@ void ArmatureImportContext::create_armature_bones(const ufbx_node *node, bArmature *arm = static_cast(arm_obj->data); /* Create an EditBone. */ - EditBone *bone = ED_armature_ebone_add(arm, get_fbx_name(node->name, "Bone")); + std::string name; + if (node->is_geometry_transform_helper) { + /* Name geometry transform adjustment helpers with parent name and _GeomAdjust suffix. */ + name = get_fbx_name(node->parent->name, "Bone") + std::string("_GeomAdjust"); + } + else { + name = get_fbx_name(node->name, "Bone"); + } + EditBone *bone = ED_armature_ebone_add(arm, name.c_str()); this->mapping.node_to_name.add(node, bone->name); this->mapping.node_is_blender_bone.add(node); this->mapping.bone_to_armature.add(node, arm_obj); diff --git a/source/blender/io/fbx/importer/fbx_import_mesh.cc b/source/blender/io/fbx/importer/fbx_import_mesh.cc index d978001bf3a..47689a1463f 100644 --- a/source/blender/io/fbx/importer/fbx_import_mesh.cc +++ b/source/blender/io/fbx/importer/fbx_import_mesh.cc @@ -524,7 +524,15 @@ void import_meshes(Main &bmain, /* Create objects that use this mesh. */ for (const ufbx_node *node : fmesh->instances) { - Object *obj = BKE_object_add_only_object(&bmain, OB_MESH, get_fbx_name(node->name)); + std::string name; + if (node->is_geometry_transform_helper) { + /* Name geometry transform adjustment helpers with parent name and _GeomAdjust suffix. */ + name = get_fbx_name(node->parent->name) + std::string("_GeomAdjust"); + } + else { + name = get_fbx_name(node->name); + } + Object *obj = BKE_object_add_only_object(&bmain, OB_MESH, name.c_str()); obj->data = mesh_main; if (!node->visible) { obj->visibility_flag |= OB_HIDE_VIEWPORT; diff --git a/tests/files/io_tests/fbx/reference/ufbx_max_geometry_transform_instances_77b.txt b/tests/files/io_tests/fbx/reference/ufbx_max_geometry_transform_instances_77b.txt index e4d7eeca7e0..2e55f34af9d 100644 --- a/tests/files/io_tests/fbx/reference/ufbx_max_geometry_transform_instances_77b.txt +++ b/tests/files/io_tests/fbx/reference/ufbx_max_geometry_transform_instances_77b.txt @@ -29,25 +29,41 @@ - (1.000, 1.000) - (0.000, 1.000) -==== Objects: 4 -- Obj 'Box001' MESH data:'Mesh' +==== Objects: 8 +- Obj 'Box001' EMPTY - pos 0.000, 0.000, 0.254 - rot 0.000, 0.000, 0.000 (XYZ) - scl 0.025, 0.025, 0.025 - props: int:MaxHandle=1 -- Obj 'Box002' MESH data:'Mesh' par:'Box001' +- Obj 'Box001_GeomAdjust' MESH data:'Mesh' par:'Box001' + - pos 40.000, 0.000, -10.000 + - rot 0.000, 0.000, 0.000 (XYZ) + - scl 1.000, 1.000, 1.000 +- Obj 'Box002' EMPTY par:'Box001' - pos 0.000, 0.000, 10.000 - rot 0.000, 0.000, 0.524 (XYZ) - scl 1.000, 1.000, 1.000 - props: int:MaxHandle=5 -- Obj 'Box003' MESH data:'Mesh' par:'Box002' +- Obj 'Box002_GeomAdjust' MESH data:'Mesh' par:'Box002' + - pos 20.000, 34.641, -20.000 + - rot 0.000, 0.000, -0.524 (XYZ) + - scl 1.000, 1.000, 1.500 +- Obj 'Box003' EMPTY par:'Box002' - pos 0.000, 0.000, 20.000 - rot 0.000, 0.000, 0.524 (XYZ) - scl 1.000, 1.000, 1.000 - props: int:MaxHandle=6 -- Obj 'Box004' MESH data:'Mesh' par:'Box003' +- Obj 'Box003_GeomAdjust' MESH data:'Mesh' par:'Box003' + - pos -20.000, 34.641, -40.000 + - rot 0.000, 0.000, -1.047 (XYZ) + - scl 1.000, 1.000, 2.000 +- Obj 'Box004' EMPTY par:'Box003' - pos 0.000, 0.000, 10.000 - rot 0.000, 0.000, 0.524 (XYZ) - scl 1.000, 1.000, 1.000 - props: int:MaxHandle=7 +- Obj 'Box004_GeomAdjust' MESH data:'Mesh' par:'Box004' + - pos -40.000, 0.000, -50.000 + - rot 0.000, 0.000, 0.000 (XYZ) + - scl 1.000, 1.000, 2.500