From 1e479b02946f5bc9479b489d2909831c228f4d04 Mon Sep 17 00:00:00 2001 From: detomon Date: Fri, 27 Sep 2024 09:04:57 +0200 Subject: [PATCH] Improve performance of `Skeleton3D::force_update_bone_children_transforms` --- scene/3d/skeleton_3d.cpp | 24 +++++++++--------------- scene/3d/skeleton_3d.h | 1 + 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 0bb6f30c50a..9c034735f95 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -471,6 +471,7 @@ void Skeleton3D::_make_modifiers_dirty() { } void Skeleton3D::_update_bones_nested_set() { + nested_set_offset_to_bone_index.resize(bones.size()); bone_global_pose_dirty.resize(bones.size()); _make_bone_global_poses_dirty(); @@ -490,6 +491,7 @@ int Skeleton3D::_update_bone_nested_set(int p_bone, int p_offset) { span += subspan; } + nested_set_offset_to_bone_index[p_offset] = p_bone; bones.write[p_bone].nested_set_offset = p_offset; bones.write[p_bone].nested_set_span = span; @@ -1056,14 +1058,14 @@ void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) { ERR_FAIL_INDEX(p_bone_idx, bone_size); Bone *bonesptr = bones.ptrw(); - thread_local LocalVector bones_to_process; - bones_to_process.clear(); - bones_to_process.push_back(p_bone_idx); - uint32_t index = 0; - while (index < bones_to_process.size()) { - int current_bone_idx = bones_to_process[index]; + // Loop through nested set. + for (int offset = 0; offset < bone_size; offset++) { + if (!bone_global_pose_dirty[offset]) { + continue; + } + int current_bone_idx = nested_set_offset_to_bone_index[offset]; Bone &b = bonesptr[current_bone_idx]; bool bone_enabled = b.enabled && !show_rest_only; @@ -1110,15 +1112,7 @@ void Skeleton3D::force_update_bone_children_transforms(int p_bone_idx) { } #endif // _DISABLE_DEPRECATED - bone_global_pose_dirty[b.nested_set_offset] = false; - - // Add the bone's children to the list of bones to be processed. - int child_bone_size = b.child_bones.size(); - for (int i = 0; i < child_bone_size; i++) { - bones_to_process.push_back(b.child_bones[i]); - } - - index++; + bone_global_pose_dirty[offset] = false; } } diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index d5d249e4e6f..2e1bd8b8eed 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -186,6 +186,7 @@ private: LocalVector bones_backup; // Global bone pose calculation. + LocalVector nested_set_offset_to_bone_index; // Map from Bone::nested_set_offset to bone index. LocalVector bone_global_pose_dirty; // Indexable with Bone::nested_set_offset. void _update_bones_nested_set(); int _update_bone_nested_set(int p_bone, int p_offset);