Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- bool PhysicsSystem::CircleToPolygon(Collider2D* a_pColliderA, Collider2D* a_pColliderB, Collision2D& a_collision) const
- {
- CircleCollider2D* col1 = static_cast<CircleCollider2D*>(a_pColliderA);
- PolygonCollider2D* col2 = static_cast<PolygonCollider2D*>(a_pColliderB);
- col2->UpdateCorners();
- col2->UpdateNormals();
- std::vector<igad::Vector2>& polyNormals = col2->GetNormals();
- std::vector<igad::Vector2>& polyVertices = col2->GetCorners();
- const igad::Vector2 circleCenter = col1->GetPosition();
- //Get minimum penetration using SAT
- float overlap = -FLT_MAX;
- int normalIndex = 0;
- for (int i = 0; i < polyNormals.size(); ++i)
- {
- float projection = polyNormals[i].Dot(circleCenter - polyVertices[i]);
- if (projection > col1->GetRadius())
- return false;
- if (projection > overlap)
- {
- overlap = projection;
- normalIndex = i;
- }
- }
- //Poly face vertices
- igad::Vector2 v1 = polyVertices[normalIndex];
- igad::Vector2 v2 = polyVertices[(normalIndex + 1) % polyVertices.size()];
- //Check to see if circle center is within the poly's body
- if (overlap < EPSILON)
- {
- a_collision.v2Normal = polyNormals[normalIndex];
- a_collision.fOverlap = col1->GetRadius();
- a_collision.contactPoints.push_back(std::pair<igad::Vector2, float>(a_collision.fOverlap * -a_collision.v2Normal + circleCenter, a_collision.fOverlap));
- return true;
- }
- //Determine which voronoi region is the closest to the center of the circle
- const float dot1 = (circleCenter - v1).Dot(v2 - v1);
- const float dot2 = (circleCenter - v2).Dot(v1 - v2);
- a_collision.fOverlap = col1->GetRadius() - overlap;
- //Outside v1 but close to it
- if (dot1 <= 0.0f)
- {
- if ((circleCenter - v1).SquaredMagnitude() > col1->GetRadius() * col1->GetRadius())
- return false;
- a_collision.v2Normal = (circleCenter - v1).Normalized();
- igad::Vector2 contactPoint = -a_collision.v2Normal * col1->GetRadius() + col1->GetPosition();
- float penetration = (contactPoint - v1).Magnitude();
- a_collision.contactPoints.push_back(std::pair<igad::Vector2, float>(contactPoint, penetration));
- }
- //Outside v2 but close to it
- else if (dot2 <= 0.0f)
- {
- if ((circleCenter - v2).SquaredMagnitude() > col1->GetRadius() * col1->GetRadius())
- return false;
- a_collision.v2Normal = (circleCenter - v2).Normalized();
- igad::Vector2 contactPoint = -a_collision.v2Normal * col1->GetRadius() + col1->GetPosition();
- float penetration = (contactPoint - v2).Magnitude();
- a_collision.contactPoints.push_back(std::pair<igad::Vector2, float>(contactPoint, penetration));
- }
- //Inside a region so we just take the normal of the face
- else
- {
- igad::Vector2 normal = polyNormals[normalIndex];
- if (normal.Dot(circleCenter - v1) > col1->GetRadius())
- return false;
- a_collision.v2Normal = normal;
- a_collision.contactPoints.push_back(std::pair<igad::Vector2, float>(col1->GetRadius() * -a_collision.v2Normal + circleCenter, a_collision.fOverlap));
- }
- return true;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement