39 auto manifoldConf = Manifold::Conf{};
49 DistanceConf distanceConf;
61 m_fixtureA{fA}, m_fixtureB{fB},
62 m_indexA{iA}, m_indexB{iB},
63 m_friction{
MixFriction(fA->GetFriction(), fB->GetFriction())},
64 m_restitution{
MixRestitution(fA->GetRestitution(), fB->GetRestitution())}
67 assert(fA->GetBody() != fB->GetBody());
70 void Contact::Update(
const UpdateConf& conf, ContactListener* listener)
72 const auto oldManifold = m_manifold;
75 const auto oldTouching = (m_flags & e_touchingFlag) != 0;
76 auto newTouching =
false;
82 const auto shapeA = fixtureA->GetShape();
83 const auto xfA = fixtureA->GetBody()->GetTransformation();
84 const auto shapeB = fixtureB->GetShape();
85 const auto xfB = fixtureB->GetBody()->GetTransformation();
86 const auto childA =
GetChild(shapeA, indexA);
87 const auto childB =
GetChild(shapeB, indexB);
93 #define OVERLAP_TOLERANCE (SquareMeter / Real(20))
95 const auto sensor = fixtureA->IsSensor() || fixtureB->IsSensor();
98 const auto overlapping =
TestOverlap(childA, xfA, childB, xfB, conf.distance);
99 newTouching = (overlapping >= 0_m2);
101 #ifdef OVERLAP_TOLERANCE
104 const auto manifold =
CollideShapes(childA, xfA, childB, xfB, conf.manifold);
105 assert(newTouching == (manifold.GetPointCount() > 0) ||
106 abs(overlapping) < tolerance);
111 m_manifold = Manifold{};
115 auto newManifold =
CollideShapes(childA, xfA, childB, xfB, conf.manifold);
117 const auto old_point_count = oldManifold.GetPointCount();
118 const auto new_point_count = newManifold.GetPointCount();
120 newTouching = new_point_count > 0;
122 #ifdef OVERLAP_TOLERANCE
125 const auto overlapping =
TestOverlap(childA, xfA, childB, xfB, conf.distance);
126 assert(newTouching == (overlapping >= 0_m2) ||
127 abs(overlapping) < tolerance);
133 bool found[2] = {
false, new_point_count < 2};
134 for (
auto i = decltype(new_point_count){0}; i < new_point_count; ++i)
136 const auto new_cf = newManifold.GetContactFeature(i);
137 for (
auto j = decltype(old_point_count){0}; j < old_point_count; ++j)
139 if (new_cf == oldManifold.GetContactFeature(j))
142 newManifold.SetContactImpulses(i, oldManifold.GetContactImpulses(j));
150 for (
auto i = decltype(new_point_count){0}; i < new_point_count; ++i)
154 auto leastSquareDiff = std::numeric_limits<Area>::infinity();
155 const auto newPt = newManifold.GetPoint(i);
156 for (
auto j = decltype(old_point_count){0}; j < old_point_count; ++j)
158 const auto oldPt = oldManifold.GetPoint(j);
160 if (leastSquareDiff > squareDiff)
162 leastSquareDiff = squareDiff;
163 newManifold.SetContactImpulses(i, oldManifold.GetContactImpulses(j));
173 m_manifold = newManifold;
175 #ifdef MAKE_CONTACT_PROCESSING_ORDER_DEPENDENT
176 const auto bodyA = fixtureA->GetBody();
177 const auto bodyB = fixtureB->GetBody();
189 if (newTouching != oldTouching)
199 if (!oldTouching && newTouching)
204 listener->BeginContact(*
this);
207 else if (oldTouching && !newTouching)
212 listener->EndContact(*
this);
216 if (!sensor && newTouching)
220 listener->PreSolve(*
this, oldManifold);
229 return contact.GetFixtureA()->GetBody();
234 return contact.GetFixtureB()->GetBody();
239 return contact.GetFixtureA()->IsSensor() || contact.GetFixtureB()->IsSensor();
244 const auto bA = contact.GetFixtureA()->GetBody();
245 const auto bB = contact.GetFixtureB()->GetBody();
246 return bA->IsImpenetrable() || bB->IsImpenetrable();
251 const auto bA = contact.GetFixtureA()->GetBody();
252 const auto bB = contact.GetFixtureB()->GetBody();
254 assert(!bA->IsAwake() || bA->IsSpeedable());
255 assert(!bB->IsAwake() || bB->IsSpeedable());
257 const auto activeA = bA->IsAwake();
258 const auto activeB = bB->IsAwake();
261 return activeA || activeB;
279 const auto restitutionA = contact.GetFixtureA()->GetRestitution();
280 const auto restitutionB = contact.GetFixtureB()->GetRestitution();
281 contact.SetRestitution(
MixRestitution(restitutionA, restitutionB));
289 const auto bB = fB->GetBody();
301 return GetToiViaSat(proxyA, sweepA, proxyB, sweepB, conf);