Speed up FBX export of vertex cos with numpy
commit6054d1bef845c5f8498b48fb7baaefa6798fb4fb
authorThomas Barlow <github@mysterymayhem.co.uk>
Fri, 27 Jan 2023 01:32:56 +0000 (27 01:32 +0000)
committerGitea <gitea@fake.local>
Tue, 28 Feb 2023 17:05:02 +0000 (28 18:05 +0100)
tree280e2209c8116d523a067c27db149f84d928f7e4
parent994c4d9175b07f86b82a3223b916c3872572b05b
Speed up FBX export of vertex cos with numpy

Use buffer matching the single precision float type of the vertex cos data in foreach_get to avoid having to iterate and cast every element in the C foreach_getset function when single precision float is not 64 bits (it's usually 32 bits). Numpy does the casting to the 64 bit fbx type much faster with .astype when needed.

Replace use of vcos_transformed_gen mesh transform helper with numpy version.

~35 (1538 vertices) to 55 (best) (24578 vertices) to 20 (6M to 25M vertices) times faster when geom_mat_co is None
~21 (1538 vertices) to 50 (best) (24578 vertices) to 23 (6M to 25M vertices) times faster when geom_mat_co is set

Relative to the original implementation, the numpy implementation seems to perform increasingly faster the more vertices there are until about 25k vertices and then starts getting slower at a decreasing rate, to the point that there is pretty much no change in the relative speedup between 6M and 25M vertices.

This patch slightly changes the exported cos when geom_mat_co is set by skipping a cast from double to single precision before casting as float64 (usually double precision):
The original code would multiply mathutils.Matrix (single precision) and mathutils.Vector (single precision) together, which casts the Matrix elements to double precision, performs the multiplication, and then casts the result back to single precision. These single precision multiplied vectors would then be cast to float64 to be exported.
The new code performs the same cast of the matrix to double precision, but skips the step of casting back to single precision, instead casting directly to float64.
Even if the new code were to cast back to single precision float and then to float64 like the original code, there does tend to be a small difference in the result, presumably due to precision error.

Pull Request #104448
io_scene_fbx/export_fbx_bin.py