void PhysicsSystem::CheckCup(const TransformPtr &ball_transform){
	using glm::vec2; 

	float radius = 0.05f;

	BallComponentPtr ball_comp = ball_comp_mapper_(ball_);
	TileComponentPtr curr_tile = tile_comp_mapper_(ball_comp->current_tile);
	VolumePtr cup_vol = volume_mapper_(curr_tile->cup);
	TransformPtr cup_transform = transform_mapper_(curr_tile->cup);

	// create ball projection
	vec3 proj = Project(ball_transform->position(), cup_vol->normal, cup_vol->vertices[0]);

	// project cup vertices to xz plane
	vector<vec2> projected_vertices;
	for (int j = 0, sizej = cup_vol->vertices.size(); j < sizej; ++j) {
		vec3 v = cup_vol->vertices[j];
		vec2 p(v.x, v.z);

		projected_vertices.push_back(p);
	}

	// project ball to xz plane
	vec2 point(proj.x, proj.z);

	// check to see if ball overlaps hole
	bool inter = PointInPolygon(point, projected_vertices);

	// does ball overlap?
	if (inter) {
		float dist_from_cup = glm::length(ball_transform->position() - cup_transform->position());

		//if ball is close enough to go in hole and moving slow enough, ball went in cup (stop ball)
		if(dist_from_cup < MADE_CUP_RADIUS && glm::length(ball_comp->velocity) < MAX_CUP_ENTRY_SPEED ) {
			ball_comp->velocity = vec3();
			ball_comp->acceleration = vec3();
			ball_comp->in_cup = true;
		}
		//if ball is on lip, alter accel to go towards center
		else if(dist_from_cup > MADE_CUP_RADIUS && dist_from_cup < CUP_LIP_RADIUS) {
			ball_comp->acceleration += glm::normalize(cup_transform->position() - ball_transform->position()) * LIP_ACCEL;
		}
		else{}
	}
}
void PhysicsSystem::UpdateCollision(const TransformPtr &ball_transform) {
	BallComponentPtr ball_comp = ball_comp_mapper_(ball_);
	vec3 start = ball_transform->position();
	vec3 end = start + ball_comp->velocity * Time::GetDeltaTime();

	vec3 normal, penetration;

	unordered_map<VolumePtr, EntityPtr>::iterator it;
	for (it = wall_map_.begin(); it != wall_map_.end(); ++it) {
		if (Intersect(start, end, it->first, normal, penetration)) {
			ResolveCollision(ball_transform, normal, penetration);
		}
	}
}
bool PhysicsSystem::UpdateTile(const TransformPtr &ball_transform, const BallComponentPtr &ball_comp, const EntityPtr &tile, const int &depth) {
	using glm::vec2; 

	TileComponentPtr tile_comp = tile_comp_mapper_(tile);
	VolumePtr tile_volume = volume_mapper_(tile);

	if (depth < 0) {
		return false;
	}

	vec3 v;
	vec2 p;
	vector<vec2> projected_vertices;
	for (int j = 0, sizej = tile_volume->vertices.size(); j < sizej; ++j) {
		v = tile_volume->vertices[j];
		p = vec2(v.x, v.z);

		projected_vertices.push_back(p);
	}

	vec2 point(ball_transform->position().x, ball_transform->position().z);

	MeshPtr mesh = mesh_mapper_(tile);
	shared_ptr<BasicMaterial> bm = boost::dynamic_pointer_cast<BasicMaterial>(mesh->material);

	// is ball in this tile?
	if (PointInPolygon(point, projected_vertices)) {
		// color tile yellow
		bm->Ld_ = vec3(1, 1, 0);

		ProjectToSlope(ball_transform, ball_comp, tile);

		// set ball's current tile
		ball_comp->current_tile = tile;

		return true;
	} else {
		bm->Ld_ = vec3(0, 1, 0);

		vector<EntityPtr>::iterator it, ite;

		for (it = tile_comp->neighbors.begin(), ite = tile_comp->neighbors.end(); it != ite; ++it) {
			if (UpdateTile(ball_transform, ball_comp, *it, depth - 1)) {
				return true;
			}
		}

		/*
		// This hack is broken
		ball_comp->velocity = vec3(0);
		ball_comp->acceleration = vec3(0);

		VolumePtr volume = volume_mapper_(ball_comp->current_tile);

		int N = volume->vertices.size();
		vec3 position(0);

		vector<vec3>::iterator jt, jte;
		for (jt = volume->vertices.begin(), jte = volume->vertices.end(); jt != jte; ++jt) {
			position += (*jt);
		}

		position /= N;

		ball_transform->set_position(position);

		ProjectToSlope(ball_transform, ball_comp, ball_comp->current_tile);
		*/

		return false;
	}

	/*
	float radius = 0.05f;

	VolumePtr curr_volume = tile_vols_[0];

	// move ball  up slopes using projections
	vec3 proj = Project(ball_transform->position(), curr_volume->normal, curr_volume->vertices[0]);
	ball_transform->set_position(proj);
	ball_transform->Translate(curr_volume->normal * radius);

	// loop through neighbors
	for (int i = 1, size = tile_vols_.size(); i < size; ++i) {
		VolumePtr neigh = tile_vols_[i];

		// project neighbors vertices to xz plane
		vector<vec2> projected_vertices;
		for (int j = 0, sizej = neigh->vertices.size(); j < sizej; ++j) {
			vec3 v = neigh->vertices[j];
			vec2 p(v.x, v.z);

			projected_vertices.push_back(p);
		}

		// project ball to xz plane
		vec2 point(ball_transform->position().x, ball_transform->position().z);

		// check to see if ball overlaps neighbor
		bool inter = PointInPolygon(point, projected_vertices);

		// does ball overlap?
		if (inter) {
			// set current ball to overlapped neighbor
			MeshPtr mesh = mesh_mapper_(ball_comp->current_tile);
			shared_ptr<BasicMaterial> bm = boost::dynamic_pointer_cast<BasicMaterial>(mesh->material);
			bm->Ld_ = vec3(0, 1, 0);

			//ball_comp->current_tile = curr_tile->neighbors[i - 1];
		
			break;
		}
	}
	*/
}