Speed up FBX export of shape keys with numpy #104452
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#104452
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "Mysteryem/blender-addons:fbx_numpy_shape_keys_pr"
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?
Use buffer matching the C type of the "co" property in foreach_get to avoid having to iterate and cast every single element in the C foreach_getset function.
Replace use of vcos_transformed_gen mesh transform helper with numpy version.
Only get cos of shape keys that are needed, since shape keys that are relative to themselves and have no other shape keys are relative to them can be skipped.
~7-12 times faster for shape keys that are entirely equal
~11-25 times faster for shape keys that are entirely different and not similar
~16-28 times faster for shape keys that are almost entirely different but similar
This patch does usually slightly change the exported file because the math for calculating the difference between a shape key and its relative key is done with float64 precision, matching the fbx export type. Beforehand, the difference would be calculated using mathutils.Vector which are single precision float (usually float32).
Because numpy.isclose is not symmetrical, this patch can also rarely result in a difference in which shape key cos are considered similar and are therefore not included in the export.
Consider the relative difference between 0.5 and 1.0:
If 1.0 is considered the reference value there is a 50% difference, but if 0.5 is considered the reference value there is a 100% difference.
math.isclose and fbx_utils.similar_values_iter always picks the value with greater magnitude as the reference value, whereas numpy.isclose picks the second argument as the reference value.
math.isclose(0.5, 1.0, rel_tol=0.5) => True
math.isclose(1.0, 0.5, rel_tol=0.5) => True
numpy.isclose(0.5, 1.0, rtol=0.5) => True
numpy.isclose(1.0, 0.5, rtol=0.5) => False
The relative key of each shape key is used as the reference value for numpy.isclose.
Whether geom_mat_co is set or None didn't make much difference to the total speedup, which is why the timing comparison in the commit message doesn't mention geom_mat_co.
The speedup around shape key weights is very minor. Without the use of accessing the numpy arrays through their underlying memoryview objects, the main loop would be slower since numpy arrays seem to be quite a bit slower to iterate and index one element at a time compared to Python arrays.
It might be possible to speed up the export of shape key weights by figuring out ahead of time all the indices of vertices that are needed for shape key weights so that each vertex is only ever indexed at most once, but this sounded very complicated and I don't think shape key weights typically get used much. I'd rather hope and wait for some way to quickly access vertex group weights, similar to foreach_get/set, to get added to the Python API.
This patch depends on
#104447
I wasn't sure if I should include its commit in this PR, I have included it for now.
386c5f7cac
tofb55abded3
fb55abded3
to0a68da4c8e