Advertisement
Guest User

Untitled

a guest
Jan 23rd, 2018
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.94 KB | None | 0 0
  1. bool PhysicsSystem::CircleToPolygon(Collider2D* a_pColliderA, Collider2D* a_pColliderB, Collision2D& a_collision) const
  2. {
  3.     CircleCollider2D* col1 = static_cast<CircleCollider2D*>(a_pColliderA);
  4.     PolygonCollider2D* col2 = static_cast<PolygonCollider2D*>(a_pColliderB);
  5.  
  6.     col2->UpdateCorners();
  7.     col2->UpdateNormals();
  8.  
  9.     std::vector<igad::Vector2>& polyNormals = col2->GetNormals();
  10.     std::vector<igad::Vector2>& polyVertices = col2->GetCorners();
  11.     const igad::Vector2 circleCenter = col1->GetPosition();
  12.  
  13.     //Get minimum penetration using SAT
  14.     float overlap = -FLT_MAX;
  15.     int normalIndex = 0;
  16.     for (int i = 0; i < polyNormals.size(); ++i)
  17.     {
  18.         float projection = polyNormals[i].Dot(circleCenter - polyVertices[i]);
  19.        
  20.         if (projection > col1->GetRadius())
  21.             return false;
  22.  
  23.         if (projection > overlap)
  24.         {
  25.             overlap = projection;
  26.             normalIndex = i;
  27.         }
  28.     }
  29.  
  30.     //Poly face vertices
  31.     igad::Vector2 v1 = polyVertices[normalIndex];
  32.     igad::Vector2 v2 = polyVertices[(normalIndex + 1) % polyVertices.size()];
  33.  
  34.     //Check to see if circle center is within the poly's body
  35.     if (overlap < EPSILON)
  36.     {
  37.         a_collision.v2Normal = polyNormals[normalIndex];
  38.         a_collision.fOverlap = col1->GetRadius();
  39.         a_collision.contactPoints.push_back(std::pair<igad::Vector2, float>(a_collision.fOverlap * -a_collision.v2Normal + circleCenter, a_collision.fOverlap));
  40.         return true;
  41.     }
  42.  
  43.     //Determine which voronoi region is the closest to the center of the circle
  44.     const float dot1 = (circleCenter - v1).Dot(v2 - v1);
  45.     const float dot2 = (circleCenter - v2).Dot(v1 - v2);
  46.     a_collision.fOverlap = col1->GetRadius() - overlap;
  47.  
  48.     //Outside v1 but close to it
  49.     if (dot1 <= 0.0f)
  50.     {
  51.         if ((circleCenter - v1).SquaredMagnitude() > col1->GetRadius() * col1->GetRadius())
  52.             return false;
  53.  
  54.         a_collision.v2Normal = (circleCenter - v1).Normalized();
  55.         igad::Vector2 contactPoint = -a_collision.v2Normal * col1->GetRadius() + col1->GetPosition();
  56.         float penetration = (contactPoint - v1).Magnitude();
  57.         a_collision.contactPoints.push_back(std::pair<igad::Vector2, float>(contactPoint, penetration));
  58.     }
  59.     //Outside v2 but close to it
  60.     else if (dot2 <= 0.0f)
  61.     {
  62.         if ((circleCenter - v2).SquaredMagnitude() > col1->GetRadius() * col1->GetRadius())
  63.             return false;
  64.  
  65.         a_collision.v2Normal = (circleCenter - v2).Normalized();
  66.         igad::Vector2 contactPoint = -a_collision.v2Normal * col1->GetRadius() + col1->GetPosition();
  67.         float penetration = (contactPoint - v2).Magnitude();
  68.         a_collision.contactPoints.push_back(std::pair<igad::Vector2, float>(contactPoint, penetration));
  69.     }
  70.     //Inside a region so we just take the normal of the face
  71.     else
  72.     {
  73.         igad::Vector2 normal = polyNormals[normalIndex];
  74.         if (normal.Dot(circleCenter - v1) > col1->GetRadius())
  75.             return false;
  76.  
  77.         a_collision.v2Normal = normal;
  78.         a_collision.contactPoints.push_back(std::pair<igad::Vector2, float>(col1->GetRadius() * -a_collision.v2Normal + circleCenter, a_collision.fOverlap));
  79.     }
  80.     return true;
  81. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement