Polygon vs Circle
function b2CollidePolygonAndCircle(manifold, polygonA, xfA, circleB, xfB) {
manifold.pointCount = 0;
// Compute circle position in the frame of the polygon.
let c = b2Mul(xfB, circleB.m_p); //b2Vec2
let cLocal = b2MulT(xfA, c); //b2Vec2
// Find the min separating edge.
let normalIndex = 0;
let separation = Number.NEGATIVE_INFINITY; //-b2_maxFloat;
let radius = polygonA.m_radius + circleB.m_radius;
let vertexCount = polygonA.m_count;
const vertices = polygonA.m_vertices; //b2Vec2*
const normals = polygonA.m_normals; //b2Vec2*
for (let i = 0; i < vertexCount; ++i) {
let s = Vec2.b2Dot(normals[i], Vec2.Subtract(cLocal, vertices[i]));
if (s > radius) {
// Early out.
return;
}
if (s > separation) {
separation = s;
normalIndex = i;
}
}
// Vertices that subtend the incident face.
let vertIndex1 = normalIndex;
let vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;
let v1 = vertices[vertIndex1]; //b2Vec2
let v2 = vertices[vertIndex2]; //b2Vec2
// If the center is inside the polygon ...
if (separation < b2_epsilon) {
manifold.pointCount = 1;
manifold.type = b2Manifold.e_faceA;
manifold.localNormal = normals[normalIndex];
manifold.localPoint = Vec2.Scale(0.5, Vec2.Add(v1, v2));
manifold.points[0].localPoint = circleB.m_p;
manifold.points[0].id.key = 0;
return;
}
// Compute barycentric coordinates
let u1 = Vec2.b2Dot(Vec2.Subtract(cLocal, v1), Vec2.Subtract(v2, v1));
let u2 = Vec2.b2Dot(Vec2.Subtract(cLocal, v2), Vec2.Subtract(v1, v2));
if (u1 <= 0.0) {
if (Vec2.DistanceSquared(cLocal, v1) > radius radius) {
return;
}
manifold.pointCount = 1;
manifold.type = b2Manifold.e_faceA;
manifold.localNormal = Vec2.Subtract(cLocal, v1);
manifold.localNormal.normalize();
manifold.localPoint = v1;
manifold.points[0].localPoint = circleB.m_p;
manifold.points[0].id.key = 0;
}
else if (u2 <= 0.0) {
if (Vec2.DistanceSquared(cLocal, v2) > radius radius) {
return;
}
manifold.pointCount = 1;
manifold.type = b2Manifold.e_faceA;
manifold.localNormal = Vec2.Subtract(cLocal, v2);
manifold.localNormal.normalize();
manifold.localPoint = v2;
manifold.points[0].localPoint = circleB.m_p;
manifold.points[0].id.key = 0;
}
else
{
let faceCenter = Vec2.Scale(0.5, Vec2.Add(v1, v2)); //b2Vec2
let s = Vec2.b2Dot(Vec2.Subtract(cLocal, faceCenter), normals[vertIndex1]);
if (s > radius) {
return;
}
manifold.pointCount = 1;
manifold.type = b2Manifold.e_faceA;
manifold.localNormal = normals[vertIndex1];
manifold.localPoint = faceCenter;
manifold.points[0].localPoint = circleB.m_p;
manifold.points[0].id.key = 0;
}
}
Comments