FBX IO: Speed up animation import using NumPy #104856
No reviewers
Labels
No Label
Interest
Animation & Rigging
Interest
Blender Cloud
Interest
Collada
Interest
Core
Interest
Documentation
Interest
Eevee & Viewport
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
Import and Export
Interest
Modeling
Interest
Modifiers
Interest
Nodes & Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds, Tests & Devices
Interest
Python API
Interest
Rendering & Cycles
Interest
Sculpt, Paint & Texture
Interest
Translations
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Meta
Good First Issue
Meta
Papercut
Module
Add-ons (BF-Blender)
Module
Add-ons (Community)
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender-addons#104856
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "Mysteryem/blender-addons:fbx_import_anim_numpy_p1"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This patch updates much of the animation import code to replace
iteration with NumPy vectorized functions and can result in a
significant speedup for files that are mostly animation.
An FBX file containing an armature with 65 bones and a single animation
with 1523 frames (each one keyframed) animating 47 bones (144 animated
channels in the FBX file) goes from a 1.96s import to a 1.01s import for
me with this patch.
The majority of the remaining animation import time after this patch is
spent converting FBX transformation animations to Blender transformation
animations. Much of this can also be sped up with NumPy, but that will
be submitted separately once it is finished. For this reason, the new
_transformation_curves_gen
function is only intended as an interim tofacilitate this patch until the transformation animation conversion is
also updated to use NumPy.
Changes to the import of valid animations:
Previously, all imported animation curves for a single Action would
interpolate the keyframes of every other animation curve imported for
that action. This is needed for imported Object/PoseBone transformation
animations, but is unnecessary for other imported animations.
This was unlikely to be noticed because it only affected material color
animations and animations that affected both the
lens
andfocus_distance
properties of a camera.Now with this patch, only the transformation animation curves
interpolate the keyframes of every other transform animation curve.
This change is a requirement to be able to support importing other
animation curves in the future, such as those for custom properties.
Changes to the import of questionably valid animations:
FBX's default animation system only uses the first animation curve
assigned to a property's channel, but the specification does allow for
more than one curve per channel.
Previously, Blender would combine these curves together, but in such a
way that each additional imported curve would replace all the values of
prior imported curves at times less than the maximum keyframe time of
the additional imported curve (interpolating values for the keyframes
that don't exist in the additional imported curve).
Now when there are multiple animation curves assigned to a channel, the
additional imported curves only replace values at their keyframe times,
no interpolation for other keyframe times takes place.
Changes to the import of invalid animations:
An animation curve is invalid if its keyframe times are not strictly
increasing. Some imported invalid curves result in extrapolating values.
These extrapolated values are still discarded with this patch, but
previously they would be replaced with a default value. With this patch,
the extrapolated values and their keyframe times are discarded entirely.
Personally, I wouldn't mind skipping additional curves assigned to the same channel since FBX only uses the first curve, but combining them better matches existing Blender FBX IO behaviour.
I just need to double-check the behaviour of importing animations with multiple curves assigned to the same channel because I've only run the relevant code in parts and not with a full .fbx file with this weird setup (and I need to figure out how to create that weird setup).The .fbx file that I profiled to get the timings in the description I cannot redistribute, but it is the
Bellydancing
animation from Mixamo (requires adobe login) at 60 fps, without skin and without any keyframe reduction (all other options set to their defaults). This was the longest animation on the site that I could find.The change to importing valid animation curves that animate both
lens
andfocus_distance
(and material color animations that animate 2 or 3 of the red/green/blue channels):Before:
After:
fbx_animation_tests_nla_disabled_all_actions_disabled.fbx (this contains valid animations of each of the different kinds of currently supported FBX animations, aside from material color animations)
The change to importing invalid animation curves where some of the values would be discarded because they would be extrapolated:
Before (shape keys would default to zero):
After:
ShapeKeyMoveUp_shuffled_all_but_first_and_last.fbx (the times of each keyframe aside from the first and last were shuffled to create this invalid FBX file, the original animation simply activated a shape key from 0-100 linearly over 100 frames)
Nice, the import of multiple curves for the same channel worked/works exactly as I expected.
Note that in Unity, for example, only the curve read first will be used, additional curves are discarded. This matches the FBX SDKs description.
To start with, these are the isolated curves:
Curve 1:
Curve 2:
Old code, Curve 1 read first and then Curve 2
With Curve 2 read second, it replaces every keyframe that was read from Curve 1 because its last keyframe time is greater. The keyframe times from Curve 1 are replaced with interpolated values from Curve 2.
Old code, Curve 2 read first and then Curve 1
With Curve 1 read second, it replaces every keyframe that was read from Curve 2, up until the last keyframe time in Curve 1. The keyframes times from Curve 2 that are replaced are replaced with interpolated values from Curve 1
New code (in this case, the curve read order is irrelevant because they have unique keyframe times)
Because both curves have unique keyframe times, it doesn't matter which order they are read in. The curves get interlaced together.
The intention here is that if there were multiple non-overlapping curves, then they would get combined together in a way that makes sense. The choice of using overlapping curves here is just to better illustrate the behaviour.
In the case of curves that contain the same keyframe times, later curves take precedence and overwrite the existing values at those times.
WIP: FBX IO: Speed up animation import using NumPyto FBX IO: Speed up animation import using NumPyQuite a big patch, so fairly hard to do a detailed review of the whole changes. but from a quick overview it looks fine. Complete and detailed description and comments also help here, thanks!
Feel free to commit the change, also remember in this case to increase the version of the add-on (in its
__init__.py
file), think this is worth a minor version raise! Release notes should also be updated accordingly.@ -551,0 +557,4 @@
}
# Create a setter into transform_data for each values array. e.g. a values array for 'Lcl Scaling' with channel == 2
# would set transform_data.sca[2].
transform_data.scale[2]
I believe?In this case
.sca
is correct, theFBXTransformData
namedtuple uses rather short attribute names.TBH I think it would be best to also discard any additional animation curve here... This should indeed be a separate commit though.