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); }
#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);