82 lines
2.8 KiB
Diff
82 lines
2.8 KiB
Diff
# UNDF: UNDF-2026-000000015
|
|
--- a/src/broad_phase.h
|
|
+++ b/src/broad_phase.h
|
|
@@ -30,8 +30,9 @@ typedef struct b2BroadPhase
|
|
// The move set and array are used to track shapes that have moved significantly
|
|
// and need a pair query for new contacts. The array has a deterministic order.
|
|
- // todo perhaps just a move set?
|
|
- // todo implement a 32bit hash set for faster lookup
|
|
- // todo moveSet can grow quite large on the first time step and remain large
|
|
b2HashSet moveSet;
|
|
b2IntArray moveArray;
|
|
+ // Maps proxyKey+1 → index into moveArray for O(1) removal.
|
|
+ // Updated on every push and on every RemoveSwap (displaced element index fix-up).
|
|
+ b2HashTable moveIndex; // key: proxyKey+1, value: array index (stored in value field)
|
|
|
|
--- a/src/broad_phase.c
|
|
+++ b/src/broad_phase.c
|
|
@@ -35,6 +35,7 @@ void b2CreateBroadPhase( b2BroadPhase* bp )
|
|
bp->moveSet = b2CreateSet( 16 );
|
|
bp->moveArray = b2IntArray_Create( 16 );
|
|
+ bp->moveIndex = b2CreateTable( 16 );
|
|
|
|
bp->pairSet = b2CreateSet( 16 );
|
|
}
|
|
@@ -55,6 +56,7 @@ void b2DestroyBroadPhase( b2BroadPhase* bp )
|
|
b2DestroySet( &bp->moveSet );
|
|
b2IntArray_Destroy( &bp->moveArray );
|
|
+ b2DestroyTable( &bp->moveIndex );
|
|
|
|
b2DestroySet( &bp->pairSet );
|
|
|
|
@@ -63,25 +64,29 @@ void b2DestroyBroadPhase( b2BroadPhase* bp )
|
|
// in b2BufferMove — add both to moveSet (O(1)) and moveArray, recording the
|
|
// new array index into moveIndex (O(1)).
|
|
static inline void b2BufferMove( b2BroadPhase* bp, int queryProxy )
|
|
{
|
|
// Adding 1 because 0 is the sentinel
|
|
bool alreadyAdded = b2AddKey( &bp->moveSet, queryProxy + 1 );
|
|
if ( alreadyAdded == false )
|
|
{
|
|
+ int idx = bp->moveArray.count;
|
|
b2IntArray_Push( &bp->moveArray, queryProxy );
|
|
+ b2TableSet( &bp->moveIndex, (uint32_t)( queryProxy + 1 ), (uint32_t)idx );
|
|
}
|
|
}
|
|
|
|
static inline void b2UnBufferMove( b2BroadPhase* bp, int proxyKey )
|
|
{
|
|
bool found = b2RemoveKey( &bp->moveSet, proxyKey + 1 );
|
|
|
|
if ( found )
|
|
{
|
|
- // Purge from move buffer. Linear search.
|
|
- // todo if I can iterate the move set then I don't need the moveArray
|
|
- int count = bp->moveArray.count;
|
|
- for ( int i = 0; i < count; ++i )
|
|
- {
|
|
- if ( bp->moveArray.data[i] == proxyKey )
|
|
- {
|
|
- b2IntArray_RemoveSwap( &bp->moveArray, i );
|
|
- break;
|
|
- }
|
|
- }
|
|
+ // O(1) index lookup, then RemoveSwap with displaced-element fix-up.
|
|
+ uint32_t idx = b2TableGet( &bp->moveIndex, (uint32_t)( proxyKey + 1 ) );
|
|
+ b2TableRemove( &bp->moveIndex, (uint32_t)( proxyKey + 1 ) );
|
|
+ int last = bp->moveArray.count - 1;
|
|
+ if ( (int)idx != last )
|
|
+ {
|
|
+ // RemoveSwap moves the last element to position idx.
|
|
+ int displaced = bp->moveArray.data[last];
|
|
+ bp->moveArray.data[idx] = displaced;
|
|
+ bp->moveArray.count = last;
|
|
+ // Update the displaced element's index in the map.
|
|
+ b2TableSet( &bp->moveIndex, (uint32_t)( displaced + 1 ), idx );
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ bp->moveArray.count = last;
|
|
+ }
|
|
}
|
|
}
|