godot-0005 (UNDF-2026-000000584): AStar3D/AStar2D/AStarGrid2D::_solve() open_list.find(e) in heap decrease-key branch — O(N) LocalVector scan per node relaxation; fix adds open_index field to Point struct for O(1) lookup. core/math/a_star.cpp:373,878 + a_star_grid_2d.cpp:572. 800x ops reduction. godot-0006 (UNDF-2026-000000585): Skeleton3D::_update_process_order() child_bones.has(i) Vector<int> O(C) scan inside O(B) bone rebuild loop; fix changes child_bones to HashSet<int>. 24x at wide flat rigs. scene/3d/skeleton_3d.cpp:235. godot-0007 (UNDF-2026-000000586): PostImportPluginSkeletonRestFixer bones_to_process.has() + keep_bone_rest.has() — Vector<int> O(B) scan inside O(T) animation track loops; O(T*B) total (188x at T=2000/B=500). Fix: HashSet<int> for both collections. editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp:201,212,681,742. godot-0008 (UNDF-2026-000000587): GLTFDocument::_serialize_nodes/animations() extensions_used.has() — Vector<String> O(E) scan inside per-node and per-animation serialization loops; O((N+A)*E) per export (11x at 3K nodes). Fix: Vector<String> extensions_used -> HashSet<String> in gltf_state.h. modules/gltf/gltf_document.cpp:443,5496. Redot-engine is an identical fork: all four defects confirmed present. 8/8 unit tests PASS (GodotAStarSkeletonTest.java).
38 lines
2.2 KiB
Diff
38 lines
2.2 KiB
Diff
# UNDF: UNDF-2026-000000586
|
|
--- a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp
|
|
+++ b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp
|
|
@@ -162,7 +162,8 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|
// Fix animation by changing node transform.
|
|
- bones_to_process = src_skeleton->get_parentless_bones();
|
|
+ // FIX godot-0007: convert to HashSet<int> for O(1) .has() — was O(B) Vector scan per track
|
|
+ Vector<int> bones_to_process_vec = src_skeleton->get_parentless_bones();
|
|
+ HashSet<int> bones_to_process(bones_to_process_vec.begin(), bones_to_process_vec.end());
|
|
{
|
|
TypedArray<Node> nodes = p_base_scene->find_children("*", "AnimationPlayer");
|
|
while (nodes.size()) {
|
|
@@ -197,7 +197,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|
int bone_idx = src_skeleton->find_bone(bn);
|
|
int key_len = anim->track_get_key_count(i);
|
|
if (anim->track_get_type(i) == Animation::TYPE_POSITION_3D) {
|
|
- if (bones_to_process.has(bone_idx)) {
|
|
+ if (bones_to_process.has(bone_idx)) { // now O(1) via HashSet
|
|
for (int j = 0; j < key_len; j++) {
|
|
--- a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp
|
|
+++ b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp
|
|
@@ -613,7 +613,8 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|
- Vector<int> keep_bone_rest;
|
|
+ // FIX godot-0007: was Vector<int> — .has() O(K) inside O(T) track loop = O(T*K)
|
|
+ HashSet<int> keep_bone_rest;
|
|
if (is_using_modifier || keep_global_rest_leftovers) {
|
|
...
|
|
if (!found_mapped) {
|
|
- keep_bone_rest.push_back(src_idx);
|
|
+ keep_bone_rest.insert(src_idx);
|
|
}
|
|
}
|
|
@@ -678,7 +678,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|
- } else if (keep_global_rest_leftovers && keep_bone_rest.has(src_idx)) {
|
|
+ } else if (keep_global_rest_leftovers && keep_bone_rest.has(src_idx)) { // O(1)
|
|
@@ -739,7 +739,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
|
|
- if (keep_bone_rest.has(bone_idx)) {
|
|
+ if (keep_bone_rest.has(bone_idx)) { // O(1) via HashSet
|