void
vsCollisionObject::NotifyCollision( vsCollisionObject *other, const vsVector2D &where )
{
	colEvent evt;

	evt.otherObject = other;

	if ( other )
		evt.colFlags = evt.otherObject->m_colFlags;
	else
		evt.colFlags = ColFlag_World;

	evt.collisionPoint = where;

	CollisionCallback(evt);
}
	void World::BroadPhase()
	{
		double InsertStart = 0.0;
		double EraseStart = 0.0;
		double IntersectStart = 0.0;

		InsertArbiterTime = 0;
		EraseArbiterTime = 0;
		IntersectTime = 0;

		int i, j, sz = ( int )bodies.size();

		// O(n^2) broad-phase
		for ( i = 0; i < sz; ++i )
		{
			Body* bi = bodies[i];

			for ( j = i + 1; j < sz; ++j )
			{
				Body* bj = bodies[j];

				if ( bi->invMass == 0.0f && bj->invMass == 0.0f ) { continue; }

				if ( TimingFunction ) { IntersectStart = TimingFunction(); }

				Arbiter newArb( bi, bj );
				ArbiterKey key( bi, bj );

				if ( TimingFunction ) { IntersectStart = TimingFunction() - IntersectStart; IntersectTime += IntersectStart; }

				if ( newArb.numContacts > 0 )
				{
					if ( TimingFunction ) { InsertStart = TimingFunction(); }

					ArbIter iter = arbiters.find( key );

					if ( iter == arbiters.end() )
					{
						arbiters.insert( std::pair<ArbiterKey, Arbiter>( key, newArb ) );

						if ( NewCollisionCallback ) { NewCollisionCallback( CollisionUserData, &newArb ); }
					}
					else
					{
						iter->second.Update( newArb.contacts, newArb.numContacts );

						if ( CollisionCallback ) { CollisionCallback( CollisionUserData, &newArb ); }
					}

					if ( TimingFunction ) { InsertStart = TimingFunction() - InsertStart; InsertArbiterTime += InsertStart; }
				}
				else
				{
					if ( TimingFunction ) { EraseStart = TimingFunction(); }

					if ( arbiters.erase( key ) > 0 )

						// contact ended
						if ( EndCollisionCallback ) { EndCollisionCallback( CollisionUserData, &newArb ); }

					if ( TimingFunction ) { EraseStart = TimingFunction() - EraseStart; EraseArbiterTime += EraseStart; }
				}
			}
		}
	}