MTV PolygonvsPolygon(Shape* pa, Shape* pb)
	{
		Polygon* a = dynamic_cast<Polygon*>(pa);
		Polygon* b = dynamic_cast<Polygon*>(pb);

		Vec2 smallest;
		float overlap = FLT_MAX;
		for (unsigned i = 0; i < a->getAxesNum(); i++) {
			Vec2 axis = a->getAxes(i);
			Projection p1 = a->project(axis);
			Projection p2 = b->project(axis);
			if (!p1.overlap(p2)) {
				return MTV(false);
			}
			else {
				// get the overlap
				float o = p1.getOverlap(p2);
				o = fabs(o);
				// check for minimum
				if (o < overlap) {
					// then set this one as smallest
					overlap = o;
					smallest = axis;

					Vec2 d;
					d = a->Center() - b->Center();
					if (Dot(d, smallest) < 0)
						smallest.Negate();
				}
			}
		}

		for (unsigned i = 0; i < b->getAxesNum(); i++) {
			Vec2 axis = b->getAxes(i);
			Projection p1 = a->project(axis);
			Projection p2 = b->project(axis);
			if (!p1.overlap(p2)) {
				return MTV(false);
			}
			else {
				// get the overlap
				float o = p1.getOverlap(p2);
				o = fabs(o);
				// check for minimum
				if (o < overlap) {
					// then set this one as smallest
					overlap = o;
					smallest = axis;

					Vec2 d;
					d = a->Center() - b->Center();
					if (Dot(d, smallest) < 0)
						smallest.Negate();
				}
			}
		}

		return MTV(smallest, overlap, true);
	}
	MTV CirclevsPolygon(Shape* pa, Shape* pb)
	{
		Circle* a = dynamic_cast<Circle*>(pa);
		Polygon* b = dynamic_cast<Polygon*>(pb);

		// Transform circle center to Polygon model space
		Vec2 center = a->center;

		// Find edge with minimum penetration
		float separation = -FLT_MAX;
		unsigned faceNormal = 0;
		for (unsigned i = 0; i < b->getVertsNum(); ++i)
		{
			float s = Dot(b->getAxes(i), center - b->vertices[i]);
			if (s > a->radius) {
				return MTV(false);
			}

			if (s > separation) {
				separation = s;
				faceNormal = i;
			}
		}

		// Grab face's vertices
		Vec2 v1 = b->vertices[faceNormal];
		unsigned i2 = faceNormal + 1 < b->getVertsNum() ? faceNormal + 1 : 0;
		Vec2 v2 = b->vertices[i2];

		// Determine which voronoi region of the edge center of circle lies within
		float dot1 = Dot(center - v1, v2 - v1);
		float dot2 = Dot(center - v2, v1 - v2);
		
		if (dot1 <= 0.0f) {
			if (DistSqr(center, v1) > a->radius * a->radius)
				return MTV(false);
		}
		else if (dot2 <= 0.0f) {
			if (DistSqr(center, v2) > a->radius * a->radius)
				return MTV(false);
		}
		else {
			Vec2 n = b->getAxes(faceNormal);
			if (Dot(center - v1, n) > a->radius)
				return MTV(false);
		}

		return MTV(b->getAxes(faceNormal), a->radius - separation, true);
	}
	MTV CirclevsCircle(Shape* pa, Shape* pb)
	{
		Circle* a = dynamic_cast<Circle*>(pa);
		Circle* b = dynamic_cast<Circle*>(pb);

		float r = a->radius + b->radius;
		float p = Magnitude((a->center) - (b->center)) - r;
		if (p < 0) {
			Vec2 normal = a->center - b->center;
			Normalize(normal);
			p = abs(p);
			return MTV(normal,p,true);
		}
		return MTV(false);
	}
Exemple #4
0
#include "Collision.h"
#include "Projection.h"

MTV MTV::NONE = MTV(0,maths::Vector2(0,0));

Collision::~Collision(){
}

float Collision::minValue(float a,float b,float c,float d){
	float min = a;
	min = (b < min ? b : min);
	min = (c < min ? c : min);
	min = (d < min ? d : min);
	return min;
}

float Collision::maxValue(float a,float b,float c,float d){
	float max = a;
	max = (b > max ? b : max);
	max = (c > max ? c : max);
	max = (c > max ? c : max);
	return max;
}


MTV Collision::getCollision(const sf::Sprite& object1,Entity::ENTITY_SHAPE shape1,const sf::Sprite& object2,Entity::ENTITY_SHAPE shape2){
	//Use Separating Axis Theorem to determine whether two objects are overlapping
	//See documentation for full explanation of this algorithm

	//Get the oriented bounding box in world coordinates (includes rotation) of objects
	OBB obb1 = getOBB(object1);