- When sampling animations, the armature is not reset when switching from one action to the next. If an action leaves some channels unkeyed, you'll see a pose from the previous action on those channels. This patch resets the armature between actions.
- The exported bind pose is whatever pose the armature happens to be in at export time, rather than the T-pose specified in edit mode. Animations that only key certain channels often rely on the bind pose being accurate. This patch resets armatures to the bind pose before exporting.
- For single-frame animations (poses), the exporter simplifies all keyframes out of existence, because there is never any change. This patch keeps the first keyframe if it is different from the bind pose.
- The exporter simplifies keyframes on a per-component basis, e.g. X, Y, Z positions are simplified separately. Some pipelines (Assimp for example) can't handle individual components. This patch keys all components together if any one of them is changed.
Details
- Reviewers
Bastien Montagne (mont29) - Maniphest Tasks
- T47397: FBX partial animation fix
Diff Detail
- Repository
- rBA Blender Add-ons
Event Timeline
This change clears users actions after exporting, other minor issues noted below.
| io_scene_fbx/export_fbx_bin.py | ||
|---|---|---|
| 2071 | can just use scene.update() here. | |
| 2084 | This removes ob.animation_data.action = org_act, the action isn't being restored after this patch is applied (meaning users will have their actions cleared after export...). Exporting shouldn't be non-destructive from a user perspective. | |
| io_scene_fbx/fbx_utils.py | ||
| 797 | Checking start frame is zero seems a bit fragile if the intention is to check the first frame. (depends on start_zero argument to fbx_animations_do(...)) Since the first frame may not be zero. could check idx instead? | |
As it is right now it seems like simplify will not drop any curves anymore at all, even those that do not differ from the rest pose and are redundant.
| io_scene_fbx/fbx_utils.py | ||
|---|---|---|
| 797 | Instead of checking for the initial frame at all, the better solution would be to initialize p_key with default_values so that it always compares the first key to the rest pose. Initializing p_key with keys[0], as it is done currently, does absolutely nothing. | |
The original action and armature pose should now be restored after export. Also, the method of detecting the first keyframe should now be more robust. I rebased this diff on the latest version, not sure if that works or if I need to make a new revision.
This patch only changes the behavior on the first frame.
Before, p_key and key would always be identical on the first frame, so it would get simplified away unless there was a different frame later on. If you wanted to have just a single keyframe on a channel, it would always get simplified away.
Now, on the first frame, if the value is the same as the bind pose, it simplifies it away. If it's different, it keys it.
I think the problem here for me is floating point inaccuracy.
This check if val == self.default_values[idx] will fail if the keys are close but not quite the same.
I do not key any scale curves on my bones, but after resampling it will usually come out as something like 0.999994.
This should probably use the same comparison as the other keys including the min_reldiff_fac and min_absdiff_fac.
Bind pose comparison now uses the same epsilon logic as the other keyframes.
I keep rebasing on the latest commit - tell me if I'm doing this wrong. I'm used to GitHub.
@Evan Todd (et1337), rebasing is fine here, noted some minor points but best to get @Bastien Montagne (mont29)'s input here.
Regarding:
The exporter simplifies keyframes on a per-component basis, e.g. X, Y, Z positions are simplified separately. Some pipelines (Assimp for example) can't handle individual components. This patch keys all components together if any one of them is changed.
This seems unnecessary to limit Blender's exports based on limits in assimp. Having separate keyframes per channel isn't an advanced feature.
But would like feedback from other devs too.
| io_scene_fbx/export_fbx_bin.py | ||
|---|---|---|
| 2103 | this can use __slots__, (convention, but also avoids accidents). | |
That's fair, but I'll point out that partial animations are currently broken for *all* content pipelines. It outputs incorrect keyframes where none exist.
Also just to kick in my 2 cents, per-component keyframes don't make much sense from a game dev perspective. The animation systems I've used always deal with complete positions, orientations, and scales. They're keyed separately, but each always has all of its components.