public virtual void GetAabb(BroadphaseProxy proxy, out IndexedVector3 aabbMin, out IndexedVector3 aabbMax)
        {
            MultiSapProxy multiProxy = (MultiSapProxy)(proxy);

            aabbMin = multiProxy.m_aabbMin;
            aabbMax = multiProxy.m_aabbMax;
        }
        public bool TestAabbOverlap(BroadphaseProxy childProxy0, BroadphaseProxy childProxy1)
        {
            MultiSapProxy multiSapProxy0 = (MultiSapProxy)childProxy0.m_multiSapParentProxy;
            MultiSapProxy multiSapProxy1 = (MultiSapProxy)childProxy1.m_multiSapParentProxy;

            return(AabbUtil2.TestAabbAgainstAabb2(ref multiSapProxy0.m_aabbMin, ref multiSapProxy0.m_aabbMax,
                                                  ref multiSapProxy1.m_aabbMin, ref multiSapProxy1.m_aabbMax));
        }
        public void AddToChildBroadphase(MultiSapProxy parentMultiSapProxy, BroadphaseProxy childProxy, IBroadphaseInterface childBroadphase)
        {
            BridgeProxy bridgeProxyRef = new BridgeProxy();

            bridgeProxyRef.m_childProxy      = childProxy;
            bridgeProxyRef.m_childBroadphase = childBroadphase;
            parentMultiSapProxy.m_bridgeProxies.Add(bridgeProxyRef);
        }
        public virtual BroadphaseProxy CreateProxy(ref IndexedVector3 aabbMin, ref IndexedVector3 aabbMax, BroadphaseNativeTypes shapeType, Object userPtr, CollisionFilterGroups collisionFilterGroup, CollisionFilterGroups collisionFilterMask, IDispatcher dispatcher, Object multiSapProxy)
        {
            //void* ignoreMe -> we could think of recursive multi-sap, if someone is interested

            MultiSapProxy proxy = new MultiSapProxy(ref aabbMin, ref aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask);

            m_multiSapProxies.Add(proxy);

            ///this should deal with inserting/removal into child broadphases
            SetAabb(proxy, ref aabbMin, ref aabbMax, dispatcher);
            return(proxy);
        }
        public virtual void SetAabb(BroadphaseProxy proxy, ref IndexedVector3 aabbMin, ref IndexedVector3 aabbMax, IDispatcher dispatcher)
        {
            MultiSapProxy multiProxy = (MultiSapProxy)proxy;

            multiProxy.m_aabbMin = aabbMin;
            multiProxy.m_aabbMax = aabbMax;

            MyNodeOverlapCallback myNodeCallback = new MyNodeOverlapCallback(this, multiProxy, dispatcher);

            if (m_optimizedAabbTree != null)
            {
                m_optimizedAabbTree.ReportAabbOverlappingNodex(myNodeCallback, ref aabbMin, ref aabbMax);
            }

            for (int i = 0; i < multiProxy.m_bridgeProxies.Count; i++)
            {
                IndexedVector3 worldAabbMin;
                IndexedVector3 worldAabbMax;
                multiProxy.m_bridgeProxies[i].m_childBroadphase.GetBroadphaseAabb(out worldAabbMin, out worldAabbMax);
                bool overlapsBroadphase = AabbUtil2.TestAabbAgainstAabb2(ref worldAabbMin, ref worldAabbMax, ref multiProxy.m_aabbMin, ref multiProxy.m_aabbMax);
                if (!overlapsBroadphase)
                {
                    //remove it now
                    BridgeProxy bridgeProxy = multiProxy.m_bridgeProxies[i];

                    BroadphaseProxy childProxy = bridgeProxy.m_childProxy;
                    bridgeProxy.m_childBroadphase.DestroyProxy(childProxy, dispatcher);

                    multiProxy.m_bridgeProxies.RemoveAtQuick(i);
                }
            }


            /*
             *
             * if (1)
             * {
             *
             *  //find broadphase that contain this multiProxy
             *  int numChildBroadphases = getBroadphaseArray().size();
             *  for (int i=0;i<numChildBroadphases;i++)
             *  {
             *      btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
             *      btVector3 worldAabbMin,worldAabbMax;
             *      childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
             *      bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
             *
             *  //	fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
             *      int containingBroadphaseIndex = -1;
             *
             *      //if already contains this
             *
             *      for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
             *      {
             *          if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
             *          {
             *              containingBroadphaseIndex = i;
             *          }
             *          alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
             *      }
             *
             *      if (overlapsBroadphase)
             *      {
             *          if (containingBroadphaseIndex<0)
             *          {
             *              btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
             *              childProxy->m_multiSapParentProxy = multiProxy;
             *              addToChildBroadphase(multiProxy,childProxy,childBroadphase);
             *          }
             *      } else
             *      {
             *          if (containingBroadphaseIndex>=0)
             *          {
             *              //remove
             *              btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
             *
             *              btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
             *              bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
             *
             *              multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
             *              multiProxy->m_bridgeProxies.pop_back();
             *          }
             *      }
             *  }
             *
             *
             *  ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
             *  ///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
             *  if (0)//!multiProxy->m_bridgeProxies.size())
             *  {
             *      ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
             *      ///this is needed to be able to calculate the aabb overlap
             *      btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
             *      childProxy->m_multiSapParentProxy = multiProxy;
             *      addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
             *  }
             * }
             *
             * if (!multiProxy->m_bridgeProxies.size())
             * {
             *  ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
             *  ///this is needed to be able to calculate the aabb overlap
             *  btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
             *  childProxy->m_multiSapParentProxy = multiProxy;
             *  addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
             * }
             */


            //update
            for (int i = 0; i < multiProxy.m_bridgeProxies.Count; i++)
            {
                BridgeProxy bridgeProxyRef = multiProxy.m_bridgeProxies[i];
                bridgeProxyRef.m_childBroadphase.SetAabb(bridgeProxyRef.m_childProxy, ref aabbMin, ref aabbMax, dispatcher);
            }
        }
 public MyNodeOverlapCallback(MultiSapBroadphase multiSap, MultiSapProxy multiProxy, IDispatcher dispatcher)
 {
     m_multiSap   = multiSap;
     m_multiProxy = multiProxy;
     m_dispatcher = dispatcher;
 }
        ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
        public void CalculateOverlappingPairs(IDispatcher dispatcher)
        {
            if (!m_stopUpdating && GetOverlappingPairCache().HasDeferredRemoval())
            {
                IList <BroadphasePair> overlappingPairArray = GetOverlappingPairCache().GetOverlappingPairArray();


                ((List <BroadphasePair>)overlappingPairArray).Sort();


                m_invalidPair = 0;

                int i;

                BroadphasePair previousPair = new BroadphasePair();
                previousPair.m_pProxy0   = null;
                previousPair.m_pProxy1   = null;
                previousPair.m_algorithm = null;


                for (i = 0; i < overlappingPairArray.Count; i++)
                {
                    BroadphasePair pair = overlappingPairArray[i];

                    MultiSapProxy aProxy0 = pair.m_pProxy0 != null ? (MultiSapProxy)pair.m_pProxy0.m_multiSapParentProxy : null;
                    MultiSapProxy aProxy1 = pair.m_pProxy1 != null ? (MultiSapProxy)pair.m_pProxy1.m_multiSapParentProxy : null;
                    MultiSapProxy bProxy0 = previousPair.m_pProxy0 != null ? (MultiSapProxy)previousPair.m_pProxy0.m_multiSapParentProxy : null;
                    MultiSapProxy bProxy1 = previousPair.m_pProxy1 != null ? (MultiSapProxy)previousPair.m_pProxy1.m_multiSapParentProxy : null;

                    bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);

                    previousPair = pair;

                    bool needsRemoval = false;

                    if (!isDuplicate)
                    {
                        bool hasOverlap = TestAabbOverlap(pair.m_pProxy0, pair.m_pProxy1);

                        if (hasOverlap)
                        {
                            needsRemoval = false;//callback->processOverlap(pair);
                        }
                        else
                        {
                            needsRemoval = true;
                        }
                    }
                    else
                    {
                        //remove duplicate
                        needsRemoval = true;
                        //should have no algorithm
                        Debug.Assert(pair.m_algorithm == null);
                    }

                    if (needsRemoval)
                    {
                        GetOverlappingPairCache().CleanOverlappingPair(pair, dispatcher);

                        //		m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
                        //		m_overlappingPairArray.pop_back();
                        pair.m_pProxy0 = null;
                        pair.m_pProxy1 = null;
                        m_invalidPair++;
                        BulletGlobals.gOverlappingPairs--;
                    }
                }

                ///if you don't like to skip the invalid pairs in the array, execute following code:
                //#define CLEAN_INVALID_PAIRS 1
                //#ifdef CLEAN_INVALID_PAIRS

                //    //perform a sort, to sort 'invalid' pairs to the end
                //    //overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
                //    overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());

                //    overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
                //    m_invalidPair = 0;
                //#endif//CLEAN_INVALID_PAIRS

                //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
            }
        }