Contact.hpp
Go to the documentation of this file.
1 /*
2  * Original work Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
3  * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 
22 #ifndef PLAYRHO_DYNAMICS_CONTACTS_CONTACT_HPP
23 #define PLAYRHO_DYNAMICS_CONTACTS_CONTACT_HPP
24 
25 #include <PlayRho/Common/Math.hpp>
30 
31 namespace playrho {
32 
43 inline Real MixFriction(Real friction1, Real friction2)
44 {
45  assert(friction1 >= 0 && friction2 >= 0);
46  return sqrt(friction1 * friction2);
47 }
48 
54 inline Real MixRestitution(Real restitution1, Real restitution2) noexcept
55 {
56  return (restitution1 > restitution2) ? restitution1 : restitution2;
57 }
58 
59 struct ToiConf;
60 class StepConf;
61 
62 namespace d2 {
63 
64 class Body;
65 class Fixture;
66 class ContactListener;
67 
81 class Contact
82 {
83 public:
84 
87 
89  struct UpdateConf
90  {
93  };
94 
96  static UpdateConf GetUpdateConf(const StepConf& conf) noexcept;
97 
113  Contact(Fixture* fA, ChildCounter iA, Fixture* fB, ChildCounter iB);
114 
116  Contact() = delete;
117 
119  Contact(const Contact& copy) = default;
120 
122  const Manifold& GetManifold() const noexcept;
123 
131  bool IsTouching() const noexcept;
132 
137  [[deprecated]] void SetEnabled(bool flag) noexcept;
138 
140  void SetEnabled() noexcept;
141 
143  void UnsetEnabled() noexcept;
144 
146  bool IsEnabled() const noexcept;
147 
149  Fixture* GetFixtureA() const noexcept;
150 
152  ChildCounter GetChildIndexA() const noexcept;
153 
155  Fixture* GetFixtureB() const noexcept;
156 
158  ChildCounter GetChildIndexB() const noexcept;
159 
166  void SetFriction(Real friction) noexcept;
167 
172  Real GetFriction() const noexcept;
173 
178  void SetRestitution(Real restitution) noexcept;
179 
181  Real GetRestitution() const noexcept;
182 
184  void SetTangentSpeed(LinearVelocity speed) noexcept;
185 
187  LinearVelocity GetTangentSpeed() const noexcept;
188 
190  substep_type GetToiCount() const noexcept;
191 
194  bool HasValidToi() const noexcept;
195 
201  Real GetToi() const;
202 
204  void FlagForFiltering() noexcept;
205 
207  bool NeedsFiltering() const noexcept;
208 
210  void FlagForUpdating() noexcept;
211 
213  bool NeedsUpdating() const noexcept;
214 
215 private:
216 
217  friend class ContactAtty;
218 
220  using FlagsType = std::uint8_t;
221 
223  enum: FlagsType
224  {
225  // Used when crawling contact graph when forming islands.
226  e_islandFlag = 0x01,
227 
228  // Set when the shapes are touching.
229  e_touchingFlag = 0x02,
230 
231  // This contact can be disabled (by user)
232  e_enabledFlag = 0x04,
233 
234  // This contact needs filtering because a fixture filter was changed.
235  e_filterFlag = 0x08,
236 
237  // This contact has a valid TOI in m_toi
238  e_toiFlag = 0x10,
239 
240  // This contacts needs its touching state updated.
241  e_dirtyFlag = 0x20
242  };
243 
246  void UnflagForFiltering() noexcept;
247 
249  void UnflagForUpdating() noexcept;
250 
265  void Update(const UpdateConf& conf, ContactListener* listener = nullptr);
266 
273  void SetToi(Real toi) noexcept;
274 
276  void UnsetToi() noexcept;
277 
279  void SetToiCount(substep_type value) noexcept;
280 
286  void SetTouching() noexcept;
287 
289  void UnsetTouching() noexcept;
290 
294  Manifold& GetMutableManifold() noexcept;
295 
297  bool IsIslanded() const noexcept;
298 
300  void SetIslanded() noexcept;
301 
303  void UnsetIslanded() noexcept;
304 
305  // Member variables...
306 
307  Manifold mutable m_manifold;
308 
309  // Need to be able to identify two different fixtures, the child shape per fixture,
310  // and the two different bodies that each fixture is associated with. This could be
311  // done by storing whatever information is needed to lookup this information. For
312  // instance, if the dynamic tree's two leaf nodes for this contact contained this
313  // info then minimally only those two indexes are needed. That may be sub-optimal
314  // however depending the speed of cache and memory access.
315 
316  Fixture* const m_fixtureA;
317  Fixture* const m_fixtureB;
318  ChildCounter const m_indexA;
319  ChildCounter const m_indexB;
320 
321  // initialized on construction (construction-time depedent)
322  Real m_friction;
323  Real m_restitution;
324 
325  LinearVelocity m_tangentSpeed = 0;
326 
330  Real m_toi;
331 
332  substep_type m_toiCount = 0;
333 
334  FlagsType m_flags = e_enabledFlag|e_dirtyFlag;
335 };
336 
340 
341 inline const Manifold& Contact::GetManifold() const noexcept
342 {
343  // XXX: What to do if needs-updating?
344  //assert(!NeedsUpdating());
345  return m_manifold;
346 }
347 
348 inline Manifold& Contact::GetMutableManifold() noexcept
349 {
350  return m_manifold;
351 }
352 
353 inline void Contact::SetEnabled(bool flag) noexcept
354 {
355  if (flag)
356  {
357  SetEnabled();
358  }
359  else
360  {
361  UnsetEnabled();
362  }
363 }
364 
365 inline void Contact::SetEnabled() noexcept
366 {
367  m_flags |= Contact::e_enabledFlag;
368 }
369 
370 inline void Contact::UnsetEnabled() noexcept
371 {
372  m_flags &= ~Contact::e_enabledFlag;
373 }
374 
375 inline bool Contact::IsEnabled() const noexcept
376 {
377  return (m_flags & e_enabledFlag) != 0;
378 }
379 
380 inline bool Contact::IsTouching() const noexcept
381 {
382  // XXX: What to do if needs-updating?
383  // assert(!NeedsUpdating());
384  return (m_flags & e_touchingFlag) != 0;
385 }
386 
387 inline void Contact::SetTouching() noexcept
388 {
389  m_flags |= e_touchingFlag;
390 }
391 
392 inline void Contact::UnsetTouching() noexcept
393 {
394  m_flags &= ~e_touchingFlag;
395 }
396 
397 inline Fixture* Contact::GetFixtureA() const noexcept
398 {
399  return m_fixtureA;
400 }
401 
402 inline Fixture* Contact::GetFixtureB() const noexcept
403 {
404  return m_fixtureB;
405 }
406 
407 inline void Contact::FlagForFiltering() noexcept
408 {
409  m_flags |= e_filterFlag;
410 }
411 
412 inline void Contact::UnflagForFiltering() noexcept
413 {
414  m_flags &= ~Contact::e_filterFlag;
415 }
416 
417 inline bool Contact::NeedsFiltering() const noexcept
418 {
419  return (m_flags & Contact::e_filterFlag) != 0;
420 }
421 
422 inline void Contact::FlagForUpdating() noexcept
423 {
424  m_flags |= e_dirtyFlag;
425 }
426 
427 inline void Contact::UnflagForUpdating() noexcept
428 {
429  m_flags &= ~Contact::e_dirtyFlag;
430 }
431 
432 inline bool Contact::NeedsUpdating() const noexcept
433 {
434  return (m_flags & Contact::e_dirtyFlag) != 0;
435 }
436 
437 inline void Contact::SetFriction(Real friction) noexcept
438 {
439  assert(friction >= 0);
440  m_friction = friction;
441 }
442 
443 inline Real Contact::GetFriction() const noexcept
444 {
445  return m_friction;
446 }
447 
448 inline void Contact::SetRestitution(Real restitution) noexcept
449 {
450  m_restitution = restitution;
451 }
452 
453 inline Real Contact::GetRestitution() const noexcept
454 {
455  return m_restitution;
456 }
457 
458 inline void Contact::SetTangentSpeed(LinearVelocity speed) noexcept
459 {
460  m_tangentSpeed = speed;
461 }
462 
464 {
465  return m_tangentSpeed;
466 }
467 
468 inline bool Contact::HasValidToi() const noexcept
469 {
470  return (m_flags & Contact::e_toiFlag) != 0;
471 }
472 
473 inline Real Contact::GetToi() const
474 {
475  assert(HasValidToi());
476  return m_toi;
477 }
478 
479 inline void Contact::SetToi(Real toi) noexcept
480 {
481  assert(toi >= 0 && toi <= 1);
482  m_toi = toi;
483  m_flags |= Contact::e_toiFlag;
484 }
485 
486 inline void Contact::UnsetToi() noexcept
487 {
488  m_flags &= ~Contact::e_toiFlag;
489 }
490 
491 inline void Contact::SetToiCount(substep_type value) noexcept
492 {
493  m_toiCount = value;
494 }
495 
497 {
498  return m_toiCount;
499 }
500 
501 inline bool Contact::IsIslanded() const noexcept
502 {
503  return (m_flags & e_islandFlag) != 0;
504 }
505 
506 inline void Contact::SetIslanded() noexcept
507 {
508  m_flags |= e_islandFlag;
509 }
510 
511 inline void Contact::UnsetIslanded() noexcept
512 {
513  m_flags &= ~e_islandFlag;
514 }
515 
516 inline ChildCounter Contact::GetChildIndexA() const noexcept
517 {
518  return m_indexA;
519 }
520 
521 inline ChildCounter Contact::GetChildIndexB() const noexcept
522 {
523  return m_indexB;
524 }
525 
526 // Free functions...
527 
530 
533 Body* GetBodyA(const Contact& contact) noexcept;
534 
537 Body* GetBodyB(const Contact& contact) noexcept;
538 
541 inline Fixture* GetFixtureA(const Contact& contact) noexcept
542 {
543  return contact.GetFixtureA();
544 }
545 
548 inline Fixture* GetFixtureB(const Contact& contact) noexcept
549 {
550  return contact.GetFixtureB();
551 }
552 
555 inline ChildCounter GetChildIndexA(const Contact& contact) noexcept
556 {
557  return contact.GetChildIndexA();
558 }
559 
562 inline ChildCounter GetChildIndexB(const Contact& contact) noexcept
563 {
564  return contact.GetChildIndexB();
565 }
566 
569 bool HasSensor(const Contact& contact) noexcept;
570 
573 bool IsImpenetrable(const Contact& contact) noexcept;
574 
577 bool IsActive(const Contact& contact) noexcept;
578 
581 void SetAwake(const Contact& c) noexcept;
582 
585 void ResetFriction(Contact& contact);
586 
589 void ResetRestitution(Contact& contact) noexcept;
590 
593 TOIOutput CalcToi(const Contact& contact, ToiConf conf);
594 
595 } // namespace d2
596 } // namespace playrho
597 
598 #endif // PLAYRHO_DYNAMICS_CONTACTS_CONTACT_HPP