context: 
  /*
  Bullet Continuous Collision Detection and Physics Library
  Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
  
  This software is provided 'as-is', without any express or implied warranty.
  In no event will the authors be held liable for any damages arising from the use of this software.
  Permission is granted to anyone to use this software for any purpose, 
  including commercial applications, and to alter it and redistribute it freely, 
  subject to the following restrictions:
  
  1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.
  */
  
  using System;
  using System.Collections.Generic;
  using Bullet.Collision.BroadPhase;
  using Bullet.Collision.NarrowPhase;
  using Bullet.Types;
  using System.Diagnostics;
  using Bullet.LinearMath;
  
  namespace Bullet.Collision.Dispatch
  {
  
  	///SimulationIslandManager creates and handles simulation islands, using btUnionFind
  	public class btSimulationIslandManager
  	{
  		btUnionFind m_unionFind = new btUnionFind();
  
  		btList<btPersistentManifold> m_islandmanifold = new btList<btPersistentManifold>();
  		btList<btCollisionObject> m_islandBodies = new btList<btCollisionObject>();
  
  		bool m_splitIslands;
  
  		public btUnionFind getUnionFind() { return m_unionFind; }
  
  
  		internal abstract class IslandCallback
  		{
  			internal abstract void processIsland( btCollisionObject[] bodies, int numBodies, btPersistentManifold[] manifolds, int first_manifold, int numManifolds, int islandId );
  		};
  
  
  		public bool getSplitIslands()
  		{
  			return m_splitIslands;
  		}
  		public void setSplitIslands( bool doSplitIslands )
  		{
  			m_splitIslands = doSplitIslands;
  		}
  
  
  		public btSimulationIslandManager()
  		{
  			m_splitIslands = ( true );
  		}
  
  
  		public void initUnionFind( int n )
  		{
  			m_unionFind.reset( n );
  		}
  
  
  		internal void findUnions( btDispatcher dispatcher, btCollisionWorld colWorld )
  		{
  
  			{
  				btOverlappingPairCache pairCachePtr = colWorld.getPairCache();
  				int numOverlappingPairs = pairCachePtr.getNumOverlappingPairs();
  				if( numOverlappingPairs > 0 )
  				{
  					btBroadphasePair[] pairPtr = pairCachePtr.getOverlappingPairArrayPtr();
  
  					for( int i = 0; i < numOverlappingPairs; i++ )
  					{
  						btBroadphasePair collisionPair = pairPtr[i];
  						btCollisionObject colObj0 = (btCollisionObject)collisionPair.m_pProxy0.m_clientObject;
  						btCollisionObject colObj1 = (btCollisionObject)collisionPair.m_pProxy1.m_clientObject;
  
  						if( ( ( colObj0 != null ) && ( ( colObj0 ).mergesSimulationIslands() ) ) &&
  							( ( colObj1 != null ) && ( ( colObj1 ).mergesSimulationIslands() ) ) )
  						{
  							m_unionFind.unite( ( colObj0 ).getIslandTag(),
  								( colObj1 ).getIslandTag() );
  						}
  					}
  				}
  			}
  		}
  
  #if STATIC_SIMULATION_ISLAND_OPTIMIZATION
  public virtual void   btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
  {
  
  	// put the index into m_controllers into m_tag   
  	int index = 0;
  	{
  
  		int i;
  		for (i=0;i<colWorld.getCollisionObjectArray().Count; i++)
  		{
  			btCollisionObject   collisionObject= colWorld.getCollisionObjectArray()[i];
  			//Adding filtering here
  			if (!collisionObject.isStaticOrKinematicObject())
  			{
  				collisionObject.setIslandTag(index++);
  			}
  			collisionObject.setCompanionId(-1);
  			collisionObject.setHitFraction(btScalar.BT_ONE);
  		}
  	}
  	// do the union find
  
  	initUnionFind( index );
  
  	findUnions(dispatcher,colWorld);
  }
  
  public void void   btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
  {
  	// put the islandId ('find' value) into m_tag   
  	{
  		int index = 0;
  		int i;
  		for (i=0;i<colWorld.getCollisionObjectArray().Count;i++)
  		{
  			btCollisionObject collisionObject= colWorld.getCollisionObjectArray()[i];
  			if (!collisionObject.isStaticOrKinematicObject())
  			{
  				collisionObject.setIslandTag( m_unionFind.find(index) );
  				//Set the correct object offset in Collision Object Array
  				m_unionFind.getElement(index).m_sz = i;
  				collisionObject.setCompanionId(-1);
  				index++;
  			} else
  			{
  				collisionObject.setIslandTag(-1);
  				collisionObject.setCompanionId(-2);
  			}
  		}
  	}
  }
  
  
  #else //STATIC_SIMULATION_ISLAND_OPTIMIZATION
  		internal virtual void updateActivationState( btCollisionWorld colWorld, btDispatcher dispatcher )
  		{
  			// put the index into m_controllers into m_tag	
  			int index = 0;
  			{
  				int i;
  				for( i = 0; i < colWorld.getCollisionObjectArray().Count; i++ )
  				{
  					btCollisionObject collisionObject = colWorld.getCollisionObjectArray()[i];
  					if( !collisionObject.isStaticOrKinematicObject() )
  					{
  						collisionObject.setIslandTag( index++ );
  					}
  					collisionObject.setCompanionBody( null );
  					collisionObject.setHitFraction( btScalar.BT_ONE );
  				}
  				initUnionFind( index );
  			}
  			// do the union find
  
  			findUnions( dispatcher, colWorld );
  		}
  
  		public virtual void storeIslandActivationState( btCollisionWorld colWorld )
  		{
  			// put the islandId ('find' value) into m_tag	
  			{
  				int index = 0;
  				int i;
  				for( i = 0; i < colWorld.getCollisionObjectArray().Count; i++ )
  				{
  					btCollisionObject collisionObject = colWorld.getCollisionObjectArray()[i];
  					if( !collisionObject.isStaticOrKinematicObject() )
  					{
  						collisionObject.setIslandTag( m_unionFind.find( index ) );
  						m_unionFind.setElementSz( index, i );
  						collisionObject.setCompanionBody( null );
  						index++;
  					}
  					else
  					{
  						collisionObject.setIslandTag( -1 );
  						collisionObject.setCompanionBody( null );
  					}
  				}
  			}
  		}
  
  #endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
  
  #if ALLOW_INLINE
  		[MethodImpl( MethodImplOptions.AggressiveInlining )]
  #endif
  		static int getIslandId( btPersistentManifold lhs )
  		{
  			int islandId;
  			btCollisionObject rcolObj0 = lhs.m_body0;
  			btCollisionObject rcolObj1 = lhs.m_body1;
  			islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
  			return islandId;
  
  		}
  
  
  
  		/// function object that routes calls to operator<
  		class btPersistentManifoldSortPredicate : IComparer<btPersistentManifold>
  		{
  			int IComparer<btPersistentManifold>.Compare( btPersistentManifold lhs, btPersistentManifold rhs )
  			{
  				return getIslandId( lhs ) < getIslandId( rhs ) ? -1 :
  
gt: 					getIslandId( lhs ) < getIslandId( rhs ) ? 1 : 0;