Fix: some cases of bone scale were not handled correctly in new FBX importer

- Was not consistently adjusting for bone adjust_post_scale
- Map fbx node "igore parent scale" to Blender bone "inherit scale: none"

Pull Request: https://projects.blender.org/blender/blender/pulls/138204
This commit is contained in:
Aras Pranckevicius
2025-04-30 16:03:00 +02:00
committed by Aras Pranckevicius
parent 8409a5081b
commit 9315af2170
6 changed files with 35 additions and 19 deletions

View File

@@ -289,7 +289,6 @@ void importer_main(Main *bmain, Scene *scene, ViewLayer *view_layer, const FBXIm
* 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;
//@TODO: axes according to import settings
opts.space_conversion = UFBX_SPACE_CONVERSION_ADJUST_TRANSFORMS;
opts.target_axes.right = UFBX_COORDINATE_AXIS_POSITIVE_X;
opts.target_axes.up = UFBX_COORDINATE_AXIS_POSITIVE_Z;

View File

@@ -314,20 +314,8 @@ static void create_transform_curves(const FbxElementMapping &mapping,
ufbx_transform xform = ufbx_evaluate_transform(fbx_anim, fnode, t);
if (is_bone) {
/* For bones that have "ignore parent scale" on them, ufbx helpfully applies global scale to
* the evaluated transform. However we really need to get local transform without global
* scale, so undo that. */
if (fnode->adjust_post_scale != 1.0) {
xform.scale.x /= fnode->adjust_post_scale;
xform.scale.y /= fnode->adjust_post_scale;
xform.scale.z /= fnode->adjust_post_scale;
}
/* Bone transform curves need to be transformed to the bind transform
* in joint-local space. */
ufbx_matrix xform_mtx = ufbx_transform_to_matrix(&xform);
xform_mtx = ufbx_matrix_mul(&bone_xform, &xform_mtx);
xform = ufbx_matrix_to_transform(&xform_mtx);
ufbx_matrix matrix = calc_bone_pose_matrix(xform, *fnode, bone_xform);
xform = ufbx_matrix_to_transform(&matrix);
}
set_curve_sample(curves_pos[0], i, tf, float(xform.translation.x));

View File

@@ -101,6 +101,9 @@ void ArmatureImportContext::create_armature_bones(const ufbx_node *node,
this->mapping.el_to_object.add(&node->element, arm_obj);
bone->flag |= BONE_SELECTED;
bone->parent = parent_bone;
if (node->inherit_mode == UFBX_INHERIT_MODE_IGNORE_PARENT_SCALE) {
bone->inherit_scale_mode = BONE_INHERIT_SCALE_NONE;
}
this->mapping.bone_to_armature.add(node, arm_obj);
@@ -304,11 +307,12 @@ void ArmatureImportContext::find_armatures(const ufbx_node *node)
fbone, world_to_arm, found);
if (found) {
ufbx_matrix bind_local_mtx_inv = ufbx_matrix_invert(&bind_local_mtx);
ufbx_matrix local_mtx = fbone->node_to_parent;
ufbx_transform xform = fbone->local_transform;
if (fbone->node_depth <= 1) {
local_mtx = ufbx_matrix_mul(&world_to_arm, &fbone->node_to_world);
ufbx_matrix matrix = ufbx_matrix_mul(&world_to_arm, &fbone->node_to_world);
xform = ufbx_matrix_to_transform(&matrix);
}
ufbx_matrix pose_mtx = ufbx_matrix_mul(&bind_local_mtx_inv, &local_mtx);
ufbx_matrix pose_mtx = calc_bone_pose_matrix(xform, *fbone, bind_local_mtx_inv);
float pchan_matrix[4][4];
matrix_to_m44(pose_mtx, pchan_matrix);

View File

@@ -59,6 +59,27 @@ void m44_to_matrix(const float src[4][4], ufbx_matrix &dst)
dst.m23 = src[3][2];
}
ufbx_matrix calc_bone_pose_matrix(const ufbx_transform &local_xform,
const ufbx_node &node,
const ufbx_matrix &local_bind_inv_matrix)
{
ufbx_transform xform = local_xform;
/* For bones that have "ignore parent scale" on them, ufbx helpfully applies global scale to
* the evaluated transform. However we really need to get local transform without global
* scale, so undo that. */
if (node.adjust_post_scale != 1.0) {
xform.scale.x /= node.adjust_post_scale;
xform.scale.y /= node.adjust_post_scale;
xform.scale.z /= node.adjust_post_scale;
}
/* Transformed to the bind transform in joint-local space. */
ufbx_matrix matrix = ufbx_transform_to_matrix(&xform);
matrix = ufbx_matrix_mul(&local_bind_inv_matrix, &matrix);
return matrix;
}
void ufbx_matrix_to_obj(const ufbx_matrix &mtx, Object *obj)
{
#ifdef FBX_DEBUG_PRINT

View File

@@ -78,6 +78,10 @@ void node_matrix_to_obj(const ufbx_node *node, Object *obj, const FbxElementMapp
void read_custom_properties(const ufbx_props &props, ID &id, bool enums_as_strings);
void read_custom_properties(const ufbx_props &props, bPoseChannel &pchan, bool enums_as_strings);
ufbx_matrix calc_bone_pose_matrix(const ufbx_transform &local_xform,
const ufbx_node &node,
const ufbx_matrix &local_bind_inv_matrix);
//@TODO remove debug file print once things are working properly
// #define FBX_DEBUG_PRINT