Skip to content

Commit 58e0568

Browse files
committed
Merge pull request #110507 from jrouwe/issue_110479
Fix bug in ManifoldBetweenTwoFaces
2 parents a298979 + 1daf989 commit 58e0568

File tree

1 file changed

+43
-20
lines changed

1 file changed

+43
-20
lines changed

thirdparty/jolt_physics/Jolt/Physics/Collision/ManifoldBetweenTwoFaces.cpp

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -156,37 +156,60 @@ void ManifoldBetweenTwoFaces(Vec3Arg inContactPoint1, Vec3Arg inContactPoint2, V
156156
// Remember size before adding new points, to check at the end if we added some
157157
ContactPoints::size_type old_size = outContactPoints1.size();
158158

159-
// Check if both shapes have polygon faces
160-
if (inShape1Face.size() >= 2 // The dynamic shape needs to have at least 2 points or else there can never be more than 1 contact point
161-
&& inShape2Face.size() >= 3) // The dynamic/static shape needs to have at least 3 points (in the case that it has 2 points only if the edges match exactly you can have 2 contact points, but this situation is unstable anyhow)
159+
// Both faces need to have at least 2 points or else there can never be more than 1 contact point
160+
// At least one face needs to have at least 3 points (in the case that it has 2 points only if the edges match exactly you can have 2 contact points, but this situation is unstable anyhow)
161+
if (min(inShape1Face.size(), inShape2Face.size()) >= 2
162+
&& max(inShape1Face.size(), inShape2Face.size()) >= 3)
162163
{
163-
// Clip the polygon of face 2 against that of 1
164-
ConvexShape::SupportingFace clipped_face;
165-
if (inShape1Face.size() >= 3)
166-
ClipPolyVsPoly(inShape2Face, inShape1Face, inPenetrationAxis, clipped_face);
167-
else if (inShape1Face.size() == 2)
168-
ClipPolyVsEdge(inShape2Face, inShape1Face[0], inShape1Face[1], inPenetrationAxis, clipped_face);
164+
// Swap the shapes if the 2nd face doesn't have enough vertices
165+
const ConvexShape::SupportingFace *shape1_face, *shape2_face;
166+
ContactPoints *contact_points1, *contact_points2;
167+
Vec3 penetration_axis;
168+
if (inShape2Face.size() >= 3)
169+
{
170+
shape1_face = &inShape1Face;
171+
shape2_face = &inShape2Face;
172+
contact_points1 = &outContactPoints1;
173+
contact_points2 = &outContactPoints2;
174+
penetration_axis = inPenetrationAxis;
175+
}
176+
else
177+
{
178+
shape1_face = &inShape2Face;
179+
shape2_face = &inShape1Face;
180+
contact_points1 = &outContactPoints2;
181+
contact_points2 = &outContactPoints1;
182+
penetration_axis = -inPenetrationAxis;
183+
}
184+
185+
// Determine plane origin and first edge direction
186+
Vec3 plane_origin = shape1_face->at(0);
187+
Vec3 first_edge = shape1_face->at(1) - plane_origin;
169188

170-
// Determine plane origin and normal for shape 1
171-
Vec3 plane_origin = inShape1Face[0];
172189
Vec3 plane_normal;
173-
Vec3 first_edge = inShape1Face[1] - plane_origin;
174-
if (inShape1Face.size() >= 3)
190+
ConvexShape::SupportingFace clipped_face;
191+
if (shape1_face->size() >= 3)
175192
{
193+
// Clip the polygon of face 2 against that of 1
194+
ClipPolyVsPoly(*shape2_face, *shape1_face, penetration_axis, clipped_face);
195+
176196
// Three vertices, can just calculate the normal
177-
plane_normal = first_edge.Cross(inShape1Face[2] - plane_origin);
197+
plane_normal = first_edge.Cross(shape1_face->at(2) - plane_origin);
178198
}
179199
else
180200
{
201+
// Clip the polygon of face 2 against edge of 1
202+
ClipPolyVsEdge(*shape2_face, shape1_face->at(0), shape1_face->at(1), penetration_axis, clipped_face);
203+
181204
// Two vertices, first find a perpendicular to the edge and penetration axis and then use the perpendicular together with the edge to form a normal
182-
plane_normal = first_edge.Cross(inPenetrationAxis).Cross(first_edge);
205+
plane_normal = first_edge.Cross(penetration_axis).Cross(first_edge);
183206
}
184207

185208
// If penetration axis and plane normal are perpendicular, fall back to the contact points
186-
float penetration_axis_dot_plane_normal = inPenetrationAxis.Dot(plane_normal);
209+
float penetration_axis_dot_plane_normal = penetration_axis.Dot(plane_normal);
187210
if (penetration_axis_dot_plane_normal != 0.0f)
188211
{
189-
float penetration_axis_len = inPenetrationAxis.Length();
212+
float penetration_axis_len = penetration_axis.Length();
190213

191214
for (Vec3 p2 : clipped_face)
192215
{
@@ -200,9 +223,9 @@ void ManifoldBetweenTwoFaces(Vec3Arg inContactPoint1, Vec3Arg inContactPoint2, V
200223
// If the point is less than inMaxContactDistance in front of the plane of face 2, add it as a contact point
201224
if (distance * penetration_axis_len < inMaxContactDistance)
202225
{
203-
Vec3 p1 = p2 - distance * inPenetrationAxis;
204-
outContactPoints1.push_back(p1);
205-
outContactPoints2.push_back(p2);
226+
Vec3 p1 = p2 - distance * penetration_axis;
227+
contact_points1->push_back(p1);
228+
contact_points2->push_back(p2);
206229
}
207230
}
208231
}

0 commit comments

Comments
 (0)