Skip to content

Commit 8ee46f9

Browse files
committed
Fix for b2PolygonShape::ComputeDistance
This makes the distance correctly calculated when it comes to corners.
1 parent 7f20402 commit 8ee46f9

File tree

1 file changed

+21
-26
lines changed

1 file changed

+21
-26
lines changed

liquidfun/Box2D/Box2D/Collision/Shapes/b2PolygonShape.cpp

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -262,43 +262,38 @@ void b2PolygonShape::ComputeDistance(const b2Transform& xf, const b2Vec2& p, flo
262262
B2_NOT_USED(childIndex);
263263

264264
b2Vec2 pLocal = b2MulT(xf.q, p - xf.p);
265-
float32 maxDistance = -FLT_MAX;
266-
b2Vec2 normalForMaxDistance = pLocal;
267265

266+
// If the nearest point is a corner, then the dot products of the normals on each of its edges will be positive.
267+
int32 prevI = m_count - 1;
268268
for (int32 i = 0; i < m_count; ++i)
269269
{
270-
float32 dot = b2Dot(m_normals[i], pLocal - m_vertices[i]);
271-
if (dot > maxDistance)
270+
const b2Vec2& beforeNorm = m_normals[prevI]; // The normal of point i and the point i-1
271+
const b2Vec2& afterNorm = m_normals[i]; // The normal of point i and the point i+1
272+
b2Vec2 dist = pLocal - m_vertices[i];
273+
if (b2Dot(dist, beforeNorm) > 0.0f && b2Dot(dist, afterNorm) > 0.0f)
272274
{
273-
maxDistance = dot;
274-
normalForMaxDistance = m_normals[i];
275+
*distance = dist.Length();
276+
*normal = b2Mul(xf.q, dist);
277+
if (*distance > 0.0f)
278+
*normal /= *distance;
279+
return;
275280
}
281+
prevI = i;
276282
}
277283

278-
if (maxDistance > 0)
284+
float32 maxDistance = -FLT_MAX;
285+
b2Vec2 normalForMaxDistance = pLocal;
286+
for (int32 i = 0; i < m_count; ++i)
279287
{
280-
b2Vec2 minDistance = normalForMaxDistance;
281-
float32 minDistance2 = maxDistance * maxDistance;
282-
for (int32 i = 0; i < m_count; ++i)
288+
float32 dot = b2Dot(m_normals[i], pLocal - m_vertices[i]);
289+
if (dot > maxDistance)
283290
{
284-
b2Vec2 distance = pLocal - m_vertices[i];
285-
float32 distance2 = distance.LengthSquared();
286-
if (minDistance2 > distance2)
287-
{
288-
minDistance = distance;
289-
minDistance2 = distance2;
290-
}
291+
maxDistance = dot;
292+
normalForMaxDistance = m_normals[i];
291293
}
292-
293-
*distance = b2Sqrt(minDistance2);
294-
*normal = b2Mul(xf.q, minDistance);
295-
normal->Normalize();
296-
}
297-
else
298-
{
299-
*distance = maxDistance;
300-
*normal = b2Mul(xf.q, normalForMaxDistance);
301294
}
295+
*distance = maxDistance;
296+
*normal = b2Mul(xf.q, normalForMaxDistance);
302297
}
303298

304299
bool b2PolygonShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input,

0 commit comments

Comments
 (0)