Page MenuHome

FBX Import - Armatures are incorrect
Confirmed, NormalPublicKNOWN ISSUE

Description

This has been there for a very long time. Whenever importing FBX with skeleton/armature from other apps, many times It's completely screwed - bones are rotated in wrong directions and rotations are wrong. Looks like coordinate systems are not converted correctly.

In this case - perfectly normal skeleton from Maya (From actual project where it is used in production in Maya, Unity, Motion builder etc).

Blender: All versions
OS: All OS

Event Timeline

Philipp Oeser (lichtwerk) lowered the priority of this task from 90 to Normal.Jan 2 2018, 9:34 PM

While I cant very the file in another program atm (could do tomorrow) I can confirm the output in blender looks unexpected [tried a couple of settings with no luck]
Hate to ask, but @Bastien Montagne (mont29), could you have a look?

can confirm that provided file reads just fine into Maya or Unity

Using Force Connect Children and Automatic Bone Orientation will help. Besides that, yes, upper part of the skeleton is weird, no idea why. Probably some issue in Pose/bind matrices somehow, armature model of FBX is so complicated…

ghoulish (ghoulish) added a comment.EditedJul 23 2019, 2:34 AM

I'm experiencing this issue with the importer (100% of FBX armatures I import fail to import correctly).

After spending a while looking into it, what appears to be happening is the importer is ignoring (or not successfully using) the PreRotation and PostRotation properties from the FBX LimbNodes to give the bones in Blender the rotation they're supposed to have. When the bones are getting created by the importer, the bones are successfully given proper lengths however the bones aren't getting rotated at all so that the bone tails actually wind up where they're supposed to. I'm not 100% sure about this, but from the reading of the python code I've put in I believe somewhere in the following line the rotation information using the PreRotation and PostRotation info is either not being considered or not being correctly applied:

from line 1931 of import_fbx.py
"# And rotate/move it to its final "rest pose".
bone_matrix = parent_matrix @ self.get_bind_matrix().normalized()"

Looks like at least math behind pre-rotation is wrong.
PreRotation should be something like this
parent_matrix @ rotation_matrix @ parent_matrix.inverted()

wait , what? Are you telling me that those f***ing pre transform matrices need to be inter-mingled with parenting??? In other words, we are supposed to 'cancel' the parent transform for those?

So that would give something like (to get final bind matrix) parent_matrix @ pre_matrix @ parent_matrix.inverted() @ bind_matrix @ post_matrix (which should then be normalized and post-multiplied again with parent_matrix)???

I ô so hate FBX transformations model… :(((

Either apply the "pre rotation" first - assuming bone is transform free when we apply, or cancel any transform before, "pre"-rotate and re-apply transform after.

Current code does parent_matrix @ ((pre_matrix @ bind_matrix) @ post_matrix).normalized()… So that should be correct, right (iirc, order matters, but not associativity, in matrix multiplication…)?

As far as i can understand the pre-rotation concept, it is not as the rotation must apply before any other transform (around 0,0,0).

So assuming object is at 0,0,0 before, should more be like this.
parent_matrix @ (post_matrix @ bind_matrix @ pre_matrix).normalized()

If it is not the case (any translation exist) you must cancel translation and re-apply after pre-rotation.

Yes I have the same issue when importing stuff from Unreal Engine to Blender 2.7X and 2.8
Importing FBX from Unreal Engine to Blender results in distorted bones and wrong IK bones locations and orientation even when connecting to children.
I can also confirm that creating an IK in blender and then exporting it to fbx then importing again will show different results than the originals

Richard Antalik (ISS) changed the subtype of this task from "Report" to "Known Issue".Feb 15 2020, 1:06 AM

In case anyone else is stuck by this issue:

I had many FBX files with armatures/animations and many were not rotated correclty when using FBX import. None of the import settings helped, and I tried every combination of bone alignment. The armatures would appear fine in rest pose, but playing animations would distort everything horribly. No amount of manual bone-roll alignment seemed to help.

What did work for me:
Converting the FBX files to glTF, and then importing glTF. The armatures imported correctly and the animations played correctly.

The magic to resolve this issue is either somewhere in the FBX > glTF conversion, or in the glTF importer itself. However, if FBX support is not a priority, maybe a simple hack could be an intermediate conversion during FBX import to glTF, which then proceeds with glTF import.

Anyway, for anyone looking for a manual workaround, here's the github for the converter. You run it via command line but it is very simple to use, and there is good documentation.
FBX to glTF: https://github.com/facebookincubator/FBX2glTF
Documentation: https://developers.facebook.com/docs/sharing/3d-posts/glb-tutorials/#convert-from-fbx

I've investigated and I think I've uncovered the cause of some FBX armature problems as it relates to game engine import/export.

In order to round trip skeletons and animations to game engines, the skeleton bone (joint) rotations need to remain consistent. However the Blender FBX Import automatic bone orientation and force connect children options alter the bone (joint) rotations, effectively altering the skeleton, and so animations built with an imported skeleton no longer match the basis skeleton when pushed back into game engines via Blender FBX Export. (sometimes game engine animation retargetting can fix this, sometimes)

The workaround is to standardize on a Blender compatible +Y bone skeleton.

The fix is for Blender to somehow preserve the original bone orientation through FBX import/export. (more detail below)

Background

I believe (based on what I can find and deduce) a Maya/FBX bone is always displayed connecting two bone joints. In other words, the Maya visual of the bone segment is not dependent on the bone/joint local axis orientation or bone scaling in any way. It's basically just an arrow pointing to a child joint.

Blender always displays bone segments towards the +Y local bone axis.

The pictures below are the default unreal engine mannequin loaded in Maya 2020. I don't see anything in the ASCII FBX file indicating a bone display orientation. In the first image you can see one bone pointing generally towards +x and the other generally towards -x. However, the display bone does not need to point towards any bone axis. In the second picture you can see a bone that doesn't point towards any bone axis at all... The bone is just pointing to the child joint. Joints with no children are shown as a circle with no bone.


Maya also supports adjusting bone axis in "Orient Joint Options" dialog, though I'm not sure what effect this has on the bone.

Maya Joint Orientation in a Minute - YouTube

The Blender FBX import Automatic Bone Orientation and Force Connect Children options sort-of do what Maya does, but the problem is that it throws away the transformation it performs, which effectively creates a new skeleton. Then, when you export an animation based on this skeleton, it does not match the original FBX imported skeleton anymore.

Because each FBX bone can point in a different direction, there is no single uniform swapping of bone orientations on import/export that will ever work for FBX armatures which have different orientations on different bones. For example, the default UE4 skeleton orients left-leg bones towards -X, and right-leg bones towards +X. As a result, using Blender FBX Import "primary bone axis" can fix the left leg OR the right leg, but never both at the same time.

This pic below shows a UE4 mannequin skeleton imported into blender without any bone adjustment. You can see the bone X axis points up on one leg and down on the other. Without any bone correction, the animations work fine in blender and export fine back to UE4, but this rig isn't very convenient to use, as the bones are not oriented in the model.


Ideas about how to fix this problem...

(1) have the FBX importer *save* the correction_matrix that "automatic bone orientation" computes, and save it in custom property per bone. Then. during FBX export of that armature or animations, that matrix would be inverted to correct the bone orientations back to the way they were in the source FBX file. (and it would be convenient to have a small property UI and widget to display the FBX bone local axis, which will not match the Blender bone local axis)

(2) extend Blender's bone display code to have an additional "bone display rotation", which would rotate the visible bone handle without affecting the underlying bone axis. An additional toggle "always orient bone towards child pivot" could orient the bone display towards the child bone, matching Maya's behavior. Leaf bones could be automatically oriented during import, similar to the current "automatic bone orientation"

Pros and Cons:

(1) is likely to be easier to implement and experiment with. It has the drawback that any thing driven off the Blender bone local axis will not match the FBX local axis, but anything like this is unlikely to export into game engines anyway (a primary target of this fbx import/export process).

(2) and/or (3) are probably unnecessary... as the way blender handles bones works just fine


Workaround until then...

Until there is a solution which makes Blender able to preserve FBX bone orientations through import/export in a useful way.. the solution to get import/export interop between Blender and FBX based tools is to standardize on a rig where all bones match the Blender orientation... such as by building a rig in blender and standardizing on that rig. This is the approach the Blender Uefy addon for Unreal Engine takes. Alternatively, one can build a blender-centric +Y bone skeleton for getting animations into Unreal/UE and then retarget them to another skeleton with their animation retargeting tools.