void							b3DynamicBvhBroadphase::getBroadphaseAabb(b3Vector3& aabbMin,b3Vector3& aabbMax) const
{

	B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)	bounds;

	if(!m_sets[0].empty())
		if(!m_sets[1].empty())	b3Merge(	m_sets[0].m_root->volume,
			m_sets[1].m_root->volume,bounds);
		else
			bounds=m_sets[0].m_root->volume;
	else if(!m_sets[1].empty())	bounds=m_sets[1].m_root->volume;
	else
		bounds=b3DbvtVolume::FromCR(b3Vector3(0,0,0),0);
	aabbMin=bounds.Mins();
	aabbMax=bounds.Maxs();
}
void b3DynamicBvhBroadphase::setAabbForceUpdate(b3BroadphaseProxy* absproxy,
												const b3Vector3& aabbMin,
												const b3Vector3& aabbMax,
												b3Dispatcher* /*dispatcher*/)
{
	b3DbvtProxy* proxy = (b3DbvtProxy*)absproxy;
	B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
	aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
	bool docollide = false;
	if (proxy->stage == STAGECOUNT)
	{ /* fixed -> dynamic set	*/
		m_sets[1].remove(proxy->leaf);
		proxy->leaf = m_sets[0].insert(aabb, proxy);
		docollide = true;
	}
	else
	{ /* dynamic set				*/
		++m_updates_call;
		/* Teleporting			*/
		m_sets[0].update(proxy->leaf, aabb);
		++m_updates_done;
		docollide = true;
	}
	b3ListRemove(proxy, m_stageRoots[proxy->stage]);
	proxy->m_aabbMin = aabbMin;
	proxy->m_aabbMax = aabbMax;
	proxy->stage = m_stageCurrent;
	b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
	if (docollide)
	{
		m_needcleanup = true;
		if (!m_deferedcollide)
		{
			b3DbvtTreeCollider collider(this);
			m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
			m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
		}
	}
}
void							b3DynamicBvhBroadphase::collide(b3Dispatcher* dispatcher)
{
	/*printf("---------------------------------------------------------\n");
	printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
	printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
	printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
	{
		int i;
		for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
		{
			printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
				getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
		}
		printf("\n");
	}
*/



	b3SPC(m_profiling.m_total);
	/* optimize				*/ 
	m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
	if(m_fixedleft)
	{
		const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
		m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
		m_fixedleft=b3Max<int>(0,m_fixedleft-count);
	}
	/* dynamic -> fixed set	*/ 
	m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
	b3DbvtProxy*	current=m_stageRoots[m_stageCurrent];
	if(current)
	{
		b3DbvtTreeCollider	collider(this);
		do	{
			b3DbvtProxy*	next=current->links[1];
			b3ListRemove(current,m_stageRoots[current->stage]);
			b3ListAppend(current,m_stageRoots[STAGECOUNT]);
#if B3_DBVT_BP_ACCURATESLEEPING
			m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher);
			collider.proxy=current;
			b3DynamicBvh::collideTV(m_sets[0].m_root,current->aabb,collider);
			b3DynamicBvh::collideTV(m_sets[1].m_root,current->aabb,collider);
#endif
			m_sets[0].remove(current->leaf);
			B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)	curAabb=b3DbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax);
			current->leaf	=	m_sets[1].insert(curAabb,current);
			current->stage	=	STAGECOUNT;	
			current			=	next;
		} while(current);
		m_fixedleft=m_sets[1].m_leaves;
		m_needcleanup=true;
	}
	/* collide dynamics		*/ 
	{
		b3DbvtTreeCollider	collider(this);
		if(m_deferedcollide)
		{
			b3SPC(m_profiling.m_fdcollide);
			m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider);
		}
		if(m_deferedcollide)
		{
			b3SPC(m_profiling.m_ddcollide);
			m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider);
		}
	}
	/* clean up				*/ 
	if(m_needcleanup)
	{
		b3SPC(m_profiling.m_cleanup);
		b3BroadphasePairArray&	pairs=m_paircache->getOverlappingPairArray();
		if(pairs.size()>0)
		{

			int			ni=b3Min(pairs.size(),b3Max<int>(m_newpairs,(pairs.size()*m_cupdates)/100));
			for(int i=0;i<ni;++i)
			{
				b3BroadphasePair&	p=pairs[(m_cid+i)%pairs.size()];
				b3DbvtProxy*		pa=&m_proxies[p.x];
				b3DbvtProxy*		pb=&m_proxies[p.y];
				if(!b3Intersect(pa->leaf->volume,pb->leaf->volume))
				{
#if B3_DBVT_BP_SORTPAIRS
					if(pa->m_uniqueId>pb->m_uniqueId) 
						b3Swap(pa,pb);
#endif
					m_paircache->removeOverlappingPair(pa->getUid(),pb->getUid(),dispatcher);
					--ni;--i;
				}
			}
			if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
		}
	}
	++m_pid;
	m_newpairs=1;
	m_needcleanup=false;
	if(m_updates_call>0)
	{ m_updates_ratio=m_updates_done/(b3Scalar)m_updates_call; }
	else
	{ m_updates_ratio=0; }
	m_updates_done/=2;
	m_updates_call/=2;
}
void							b3DynamicBvhBroadphase::setAabb(		b3BroadphaseProxy* absproxy,
														  const b3Vector3& aabbMin,
														  const b3Vector3& aabbMax,
														  b3Dispatcher* /*dispatcher*/)
{
	b3DbvtProxy*						proxy=(b3DbvtProxy*)absproxy;
	B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)	aabb=b3DbvtVolume::FromMM(aabbMin,aabbMax);
#if B3_DBVT_BP_PREVENTFALSEUPDATE
	if(b3NotEqual(aabb,proxy->leaf->volume))
#endif
	{
		bool	docollide=false;
		if(proxy->stage==STAGECOUNT)
		{/* fixed -> dynamic set	*/ 
			m_sets[1].remove(proxy->leaf);
			proxy->leaf=m_sets[0].insert(aabb,proxy);
			docollide=true;
		}
		else
		{/* dynamic set				*/ 
			++m_updates_call;
			if(b3Intersect(proxy->leaf->volume,aabb))
			{/* Moving				*/ 

				const b3Vector3	delta=aabbMin-proxy->m_aabbMin;
				b3Vector3		velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction);
				if(delta[0]<0) velocity[0]=-velocity[0];
				if(delta[1]<0) velocity[1]=-velocity[1];
				if(delta[2]<0) velocity[2]=-velocity[2];
				if	(
#ifdef B3_DBVT_BP_MARGIN				
					m_sets[0].update(proxy->leaf,aabb,velocity,B3_DBVT_BP_MARGIN)
#else
					m_sets[0].update(proxy->leaf,aabb,velocity)
#endif
					)
				{
					++m_updates_done;
					docollide=true;
				}
			}
			else
			{/* Teleporting			*/ 
				m_sets[0].update(proxy->leaf,aabb);
				++m_updates_done;
				docollide=true;
			}	
		}
		b3ListRemove(proxy,m_stageRoots[proxy->stage]);
		proxy->m_aabbMin = aabbMin;
		proxy->m_aabbMax = aabbMax;
		proxy->stage	=	m_stageCurrent;
		b3ListAppend(proxy,m_stageRoots[m_stageCurrent]);
		if(docollide)
		{
			m_needcleanup=true;
			if(!m_deferedcollide)
			{
				b3DbvtTreeCollider	collider(this);
				m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
				m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
			}
		}	
	}
}