WIP: FBX IO: Speed up shape key access using pointers #105126
@ -713,6 +713,8 @@ def _fast_mesh_shape_key_co_check():
|
|||||||
# The check has already been run and the result has been stored in _USE_FAST_SHAPE_KEY_CO_FOREACH_GETSET.
|
# The check has already been run and the result has been stored in _USE_FAST_SHAPE_KEY_CO_FOREACH_GETSET.
|
||||||
return _USE_FAST_SHAPE_KEY_CO_FOREACH_GETSET
|
return _USE_FAST_SHAPE_KEY_CO_FOREACH_GETSET
|
||||||
|
|
||||||
|
# Check that accessing a shape key's data through its pointer works, by creating a temporary mesh and adding a shape
|
||||||
|
# key to it.
|
||||||
tmp_mesh = None
|
tmp_mesh = None
|
||||||
tmp_object = None
|
tmp_object = None
|
||||||
try:
|
try:
|
||||||
@ -737,14 +739,15 @@ def _fast_mesh_shape_key_co_check():
|
|||||||
# The check is this function, so explicitly don't do the check.
|
# The check is this function, so explicitly don't do the check.
|
||||||
co_memory_as_array = _shape_key_co_memory_as_ndarray(shape_key, do_check=False)
|
co_memory_as_array = _shape_key_co_memory_as_ndarray(shape_key, do_check=False)
|
||||||
if co_memory_as_array is not None:
|
if co_memory_as_array is not None:
|
||||||
# Immediately make a copy in case the `foreach_get` afterwards can cause the memory to be reallocated.
|
# Immediately make a copy in the unlikely case the `foreach_get` call afterward can cause the memory to be
|
||||||
|
# reallocated.
|
||||||
co_array_from_memory = co_memory_as_array.copy()
|
co_array_from_memory = co_memory_as_array.copy()
|
||||||
del co_memory_as_array
|
del co_memory_as_array
|
||||||
# Check that the array created from the pointer has the exact same contents
|
# Check that the array created from the pointer has the exact same contents
|
||||||
# as using foreach_get.
|
# as using foreach_get.
|
||||||
co_array_check = np.empty(num_co * 3, dtype=co_dtype)
|
co_array_from_foreach_get = np.empty(num_co * 3, dtype=co_dtype)
|
||||||
shape_data.foreach_get("co", co_array_check)
|
shape_data.foreach_get("co", co_array_from_foreach_get)
|
||||||
if np.array_equal(co_array_check, co_array_from_memory, equal_nan=True):
|
if np.array_equal(co_array_from_foreach_get, co_array_from_memory, equal_nan=True):
|
||||||
_USE_FAST_SHAPE_KEY_CO_FOREACH_GETSET = True
|
_USE_FAST_SHAPE_KEY_CO_FOREACH_GETSET = True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -761,6 +764,9 @@ def _fast_mesh_shape_key_co_check():
|
|||||||
|
|
||||||
|
|
||||||
def fast_mesh_shape_key_co_foreach_get(shape_key, seq):
|
def fast_mesh_shape_key_co_foreach_get(shape_key, seq):
|
||||||
|
"""
|
||||||
|
Replacement for ShapeKey.data.foreach_get that accesses the shape key data's memory directly if possible.
|
||||||
|
"""
|
||||||
co_memory_as_array = _shape_key_co_memory_as_ndarray(shape_key)
|
co_memory_as_array = _shape_key_co_memory_as_ndarray(shape_key)
|
||||||
if co_memory_as_array is not None:
|
if co_memory_as_array is not None:
|
||||||
seq[:] = co_memory_as_array
|
seq[:] = co_memory_as_array
|
||||||
@ -770,9 +776,10 @@ def fast_mesh_shape_key_co_foreach_get(shape_key, seq):
|
|||||||
|
|
||||||
def fast_mesh_shape_key_dvcos_foreach_set(new_shape_key, dvcos, indices, mesh_positions_fallback_vector_view):
|
def fast_mesh_shape_key_dvcos_foreach_set(new_shape_key, dvcos, indices, mesh_positions_fallback_vector_view):
|
||||||
"""
|
"""
|
||||||
FBX Shape key data are sparse vectors relative to the mesh, unlike Blender shape keys which are coordinates.
|
Apply sparse FBX shape key vectors to a newly created shape key.
|
||||||
|
|
||||||
The newly created shape keys must have been created with `from_mix=False`, so that they match the mesh positions.
|
The newly created shape key must have been created with `from_mix=False`, so that its coordinates match the mesh
|
||||||
|
positions.
|
||||||
"""
|
"""
|
||||||
co_memory_as_array = _shape_key_co_memory_as_ndarray(new_shape_key)
|
co_memory_as_array = _shape_key_co_memory_as_ndarray(new_shape_key)
|
||||||
if co_memory_as_array is not None:
|
if co_memory_as_array is not None:
|
||||||
@ -782,6 +789,8 @@ def fast_mesh_shape_key_dvcos_foreach_set(new_shape_key, dvcos, indices, mesh_po
|
|||||||
# Memory has been set directly, so call .update().
|
# Memory has been set directly, so call .update().
|
||||||
new_shape_key.data.update()
|
new_shape_key.data.update()
|
||||||
else:
|
else:
|
||||||
|
# As a fallback, copy the mesh positions, apply the sparse vectors to that copy and then set all the shape key
|
||||||
|
# coordinates to the modified copy of the mesh positions.
|
||||||
shape_cos = mesh_positions_fallback_vector_view.copy()
|
shape_cos = mesh_positions_fallback_vector_view.copy()
|
||||||
shape_cos[indices] += dvcos
|
shape_cos[indices] += dvcos
|
||||||
new_shape_key.data.foreach_set("co", shape_cos.ravel())
|
new_shape_key.data.foreach_set("co", shape_cos.ravel())
|
||||||
|
Loading…
Reference in New Issue
Block a user