From 6315b3d566409c3baaca68f8ad8961699f77fec7 Mon Sep 17 00:00:00 2001 From: Thomas Barlow Date: Fri, 27 Jan 2023 01:32:56 +0000 Subject: [PATCH] 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. --- io_scene_fbx/export_fbx_bin.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/io_scene_fbx/export_fbx_bin.py b/io_scene_fbx/export_fbx_bin.py index f600c7cfd..16188eee7 100644 --- a/io_scene_fbx/export_fbx_bin.py +++ b/io_scene_fbx/export_fbx_bin.py @@ -885,9 +885,11 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes): elem_data_single_int32(geom, b"GeometryVersion", FBX_GEOMETRY_VERSION) # Vertex cos. - t_co = array.array(data_types.ARRAY_FLOAT64, (0.0,)) * len(me.vertices) * 3 + co_bl_dtype = np.single + co_fbx_dtype = np.float64 + t_co = np.empty(len(me.vertices) * 3, dtype=co_bl_dtype) me.vertices.foreach_get("co", t_co) - elem_data_single_float64_array(geom, b"Vertices", chain(*vcos_transformed_gen(t_co, geom_mat_co))) + elem_data_single_float64_array(geom, b"Vertices", vcos_transformed(t_co, geom_mat_co, co_fbx_dtype)) del t_co # Polygon indices. -- 2.30.2