diff --git a/src/engine/engine_collision_gjk.c b/src/engine/engine_collision_gjk.c
index 42227694..8ad8d782 100644
--- a/src/engine/engine_collision_gjk.c
+++ b/src/engine/engine_collision_gjk.c
@@ -2169,8 +2169,16 @@ static void multicontact(Polytope* pt, Face* face, mjCCDStatus* status,
// face1 is an edge; clip face1 against face2
if (edgecon1) {
- scl3(approx_dir, n2 + 3*j, norm3(dir));
+ scl3(approx_dir, n2 + 3*j, -norm3(dir));
polygonClip(status, face2, nface2, face1, nface1, n2 + 3*j, approx_dir);
+ // x1 and x2 must be flipped as we flipped the faces in polygonClip
+ int nx = status->nx;
+ for (int k = 0; k < nx; k++) {
+ mjtNum tmp[3];
+ copy3(tmp, status->x1 + 3*k);
+ copy3(status->x1 + 3*k, status->x2 + 3*k);
+ copy3(status->x2 + 3*k, tmp);
+ }
return;
}
diff --git a/test/engine/engine_collision_gjk_test.cc b/test/engine/engine_collision_gjk_test.cc
index 21fec2cf..f46d0c0f 100644
--- a/test/engine/engine_collision_gjk_test.cc
+++ b/test/engine/engine_collision_gjk_test.cc
@@ -2028,5 +2028,43 @@ TEST_F(MjGjkTest, CylinderBoxMargin) {
mj_deleteModel(model);
}
+TEST_F(MjGjkTest, BoxEdgeFlipped) {
+ static constexpr char xml[] = R"(
+
+
+
+
+
+ )";
+
+ char error[1024];
+ mjModel* model = LoadModelFromString(xml, error, sizeof(error));
+ ASSERT_THAT(model, NotNull()) << "Failed to load model: " << error;
+
+ mjData* data = mj_makeData(model);
+ mj_forward(model, data);
+
+ int g1 = mj_name2id(model, mjOBJ_GEOM, "geom1");
+ int g2 = mj_name2id(model, mjOBJ_GEOM, "geom2");
+
+ mjCCDStatus status;
+ std::vector dir, pos;
+ mjtNum dist;
+ int ncons = Penetration(status, dist, dir, pos, model, data, g1, g2, 0, 1000);
+
+ EXPECT_EQ(ncons, 2);
+
+ EXPECT_NEAR(status.x1[0], 1.907368, kTolerance);
+ EXPECT_NEAR(status.x1[1], -0.052973, kTolerance);
+ EXPECT_NEAR(status.x1[2], 0.700000, kTolerance);
+ EXPECT_NEAR(status.x2[0], 1.30000, kTolerance);
+ EXPECT_NEAR(status.x2[1], -0.052973, kTolerance);
+ EXPECT_NEAR(status.x2[2], 0.700000, kTolerance);
+
+ mj_deleteData(data);
+ mj_deleteModel(model);
+}
+
} // namespace
} // namespace mujoco