104 lines
4.3 KiB
Diff
104 lines
4.3 KiB
Diff
# UNDF: UNDF-2026-000000603
|
|
# UNDF: (leave blank)
|
|
--- a/src/BulletCollision/CollisionDispatch/btGhostObject.h
|
|
+++ b/src/BulletCollision/CollisionDispatch/btGhostObject.h
|
|
@@ -19,6 +19,7 @@
|
|
#include "btCollisionObject.h"
|
|
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
|
|
#include "LinearMath/btAlignedAllocator.h"
|
|
+#include "LinearMath/btHashMap.h"
|
|
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
|
|
#include "btCollisionWorld.h"
|
|
|
|
@@ -36,6 +37,12 @@ btGhostObject : public btCollisionObject
|
|
protected:
|
|
btAlignedObjectArray<btCollisionObject*> m_overlappingObjects;
|
|
|
|
+ // O(1) membership index: maps btCollisionObject* pointer -> index in m_overlappingObjects.
|
|
+ // Eliminates O(N) findLinearSearch on every broadphase add/remove callback,
|
|
+ // turning the per-tick pair-update loop from O(N²) to O(N). CWE-407.
|
|
+ btHashMap<btHashPtr, int> m_overlappingObjectsIndex;
|
|
+
|
|
public:
|
|
btGhostObject();
|
|
|
|
--- a/src/BulletCollision/CollisionDispatch/btGhostObject.cpp
|
|
+++ b/src/BulletCollision/CollisionDispatch/btGhostObject.cpp
|
|
@@ -32,10 +32,12 @@ void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,
|
|
{
|
|
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
|
|
btAssert(otherObject);
|
|
- ///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
|
|
- int index = m_overlappingObjects.findLinearSearch(otherObject);
|
|
- if (index == m_overlappingObjects.size())
|
|
- {
|
|
- //not found
|
|
+ // O(1) hash lookup replaces O(N) findLinearSearch. CWE-407.
|
|
+ if (m_overlappingObjectsIndex.find(btHashPtr(otherObject)) == NULL)
|
|
+ {
|
|
+ int index = m_overlappingObjects.size();
|
|
m_overlappingObjects.push_back(otherObject);
|
|
+ m_overlappingObjectsIndex.insert(btHashPtr(otherObject), index);
|
|
}
|
|
}
|
|
|
|
@@ -44,11 +46,16 @@ void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProx
|
|
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
|
|
btAssert(otherObject);
|
|
- int index = m_overlappingObjects.findLinearSearch(otherObject);
|
|
- if (index < m_overlappingObjects.size())
|
|
+ int* indexPtr = m_overlappingObjectsIndex.find(btHashPtr(otherObject));
|
|
+ if (indexPtr != NULL)
|
|
{
|
|
- m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
|
|
+ int index = *indexPtr;
|
|
+ int lastIndex = m_overlappingObjects.size() - 1;
|
|
+ if (index != lastIndex)
|
|
+ {
|
|
+ // Swap with last; update the moved element's index entry.
|
|
+ btCollisionObject* movedObject = m_overlappingObjects[lastIndex];
|
|
+ m_overlappingObjects[index] = movedObject;
|
|
+ m_overlappingObjectsIndex.insert(btHashPtr(movedObject), index);
|
|
+ }
|
|
m_overlappingObjects.pop_back();
|
|
+ m_overlappingObjectsIndex.remove(btHashPtr(otherObject));
|
|
}
|
|
}
|
|
|
|
@@ -68,9 +75,12 @@ void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* o
|
|
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
|
|
btAssert(otherObject);
|
|
- int index = m_overlappingObjects.findLinearSearch(otherObject);
|
|
- if (index == m_overlappingObjects.size())
|
|
- {
|
|
+ if (m_overlappingObjectsIndex.find(btHashPtr(otherObject)) == NULL)
|
|
+ {
|
|
+ int index = m_overlappingObjects.size();
|
|
m_overlappingObjects.push_back(otherObject);
|
|
+ m_overlappingObjectsIndex.insert(btHashPtr(otherObject), index);
|
|
m_hashPairCache->addOverlappingPair(actualThisProxy, otherProxy);
|
|
}
|
|
}
|
|
@@ -82,11 +92,19 @@ void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy
|
|
btAssert(actualThisProxy);
|
|
|
|
btAssert(otherObject);
|
|
- int index = m_overlappingObjects.findLinearSearch(otherObject);
|
|
- if (index < m_overlappingObjects.size())
|
|
+ int* indexPtr = m_overlappingObjectsIndex.find(btHashPtr(otherObject));
|
|
+ if (indexPtr != NULL)
|
|
{
|
|
- m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
|
|
+ int index = *indexPtr;
|
|
+ int lastIndex = m_overlappingObjects.size() - 1;
|
|
+ if (index != lastIndex)
|
|
+ {
|
|
+ btCollisionObject* movedObject = m_overlappingObjects[lastIndex];
|
|
+ m_overlappingObjects[index] = movedObject;
|
|
+ m_overlappingObjectsIndex.insert(btHashPtr(movedObject), index);
|
|
+ }
|
|
m_overlappingObjects.pop_back();
|
|
+ m_overlappingObjectsIndex.remove(btHashPtr(otherObject));
|
|
m_hashPairCache->removeOverlappingPair(actualThisProxy, otherProxy, dispatcher);
|
|
}
|
|
}
|