public void Swap(int[] bodies, int islandCount) { //Pick a body. Find all bodies of its type. //Put them all in the same spot, starting at the body with the lowest index. if (bodyIndex >= bodies.Length) { bodyIndex = 0; } var bodyType = bodies[bodyIndex]; int lowestIndex = -1; QuickList <int, Array <int> > .Create(pool, 128, out var islandBodyIndices); for (int i = bodies.Length - 1; i >= 0; --i) { if (bodies[i] == bodyType) { lowestIndex = i; islandBodyIndices.Add(i, pool); } } var baseIndex = Math.Min(bodies.Length - islandBodyIndices.Count, lowestIndex); Array.Sort(islandBodyIndices.Span.Memory, 0, islandBodyIndices.Count); for (int i = 0; i < islandBodyIndices.Count; ++i) { IslandCacheConvergence.Swap(ref bodies[baseIndex + i], ref bodies[islandBodyIndices[i]]); } bodyIndex += islandBodyIndices.Count; islandBodyIndices.Dispose(pool); }
public void Swap(int[] bodies, int islandCount) { //Pick a body. Does it have any connections that are currently positioned to the right? //This will pointlessly shuffle all island neighbors to the right. //The goal here is just super simplicity. //(This is roughly equivalent to checking a body's connections, seeing if any are to the right, and if they are, pulling them to be a neighbor. //This is NOT a globally stable heuristic- even after it 'converges' it will continually reshuffle the elements within islands. //If you had full island information, you could grab only one and stick it onto the end of the currently gathered island set....) var nextIndex = (swapIndex + 1) % bodies.Length; for (int i = (nextIndex + 1) % bodies.Length; i < bodies.Length; ++i) { if (bodies[i] == bodies[swapIndex]) { IslandCacheConvergence.Swap(ref bodies[i], ref bodies[nextIndex]); //Just do one. break; } } swapIndex = nextIndex; }