ContactListener.h 5.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Physics/Collision/Shape/SubShapeIDPair.h>
  5. #include <Core/StaticArray.h>
  6. namespace JPH {
  7. class Body;
  8. class CollideShapeResult;
  9. /// Array of contact points
  10. using ContactPoints = StaticArray<Vec3, 64>;
  11. /// Manifold class, describes the contact surface between two bodies
  12. class ContactManifold
  13. {
  14. public:
  15. /// Swaps shape 1 and 2
  16. ContactManifold SwapShapes() const { return { -mWorldSpaceNormal, mPenetrationDepth, mSubShapeID2, mSubShapeID1, mWorldSpaceContactPointsOn2, mWorldSpaceContactPointsOn1 }; }
  17. Vec3 mWorldSpaceNormal; ///< Normal for this manifold, direction along which to move body 2 out of collision along the shortest path
  18. float mPenetrationDepth; ///< Penetration depth (move shape 2 by this distance to resolve the collision)
  19. SubShapeID mSubShapeID1; ///< Sub shapes that formed this manifold (note that when multiple manifolds are combined because they're coplanar, we lose some information here because we only keep track of one sub shape pair that we encounter)
  20. SubShapeID mSubShapeID2;
  21. ContactPoints mWorldSpaceContactPointsOn1; ///< Contact points on shape 1 in world space
  22. ContactPoints mWorldSpaceContactPointsOn2; ///< Contact points on shape 2 in world space
  23. };
  24. /// When a contact point is added or persisted, the callback gets a chance to override certain properties of the contact constraint.
  25. /// The values are filled in with their defaults by the system so the callback doesn't need to modify anything, but it can if it wants to.
  26. class ContactSettings
  27. {
  28. public:
  29. float mCombinedFriction; ///< Combined friction for the body pair (usually calculated by sCombineFriction)
  30. float mCombinedRestitution; ///< Combined restitution for the body pair (usually calculated by sCombineRestitution)
  31. };
  32. /// Return value for the OnContactValidate callback. Determines if the contact is being processed or not.
  33. /// Results are ordered so that the strongest accept has the lowest number and the strongest reject the highest number (which allows for easy combining of results)
  34. enum class ValidateResult
  35. {
  36. AcceptAllContactsForThisBodyPair, ///< Accept this and any further contact points for this body pair
  37. AcceptContact, ///< Accept this contact only (and continue calling this callback for every contact manifold for the same body pair)
  38. RejectContact, ///< Reject this contact only (but process any other contact manifolds for the same body pair)
  39. RejectAllContactsForThisBodyPair ///< Rejects this and any further contact points for this body pair
  40. };
  41. /// A listener class that receives collision contact events events.
  42. /// It can be registered with the ContactConstraintManager (or PhysicsSystem).
  43. class ContactListener
  44. {
  45. public:
  46. /// Ensure virtual destructor
  47. virtual ~ContactListener() = default;
  48. /// Called after detecting a collision between a body pair, but before calling OnContactAdded and before adding the contact constraint.
  49. /// If the function returns false, the contact will not be added and any other contacts between this body pair will not be processed.
  50. /// This function will only be called once per PhysicsSystem::Update per body pair and may not be called again the next update
  51. /// if a contact persists and no new contact pairs between sub shapes are found.
  52. /// This is a rather expensive time to reject a contact point since a lot of the collision detection has happened already, make sure you
  53. /// filter out the majority of undesired body pairs through the ObjectLayerPairFilter that is registered on the PhysicsSystem.
  54. /// Note that this callback is called when all bodies are locked, so don't use any locking functions!
  55. /// The order of body 1 and 2 is undefined, but when one of the two bodies is dynamic it will be body 1
  56. virtual ValidateResult OnContactValidate(const Body &inBody1, const Body &inBody2, const CollideShapeResult &inCollisionResult) { return ValidateResult::AcceptAllContactsForThisBodyPair; }
  57. /// Called whenever a new contact point is detected.
  58. /// Note that this callback is called when all bodies are locked, so don't use any locking functions!
  59. /// Body 1 and 2 will be sorted such that body 1 ID < body 2 ID, so body 1 may not be dynamic
  60. virtual void OnContactAdded(const Body &inBody1, const Body &inBody2, const ContactManifold &inManifold, ContactSettings &ioSettings) { }
  61. /// Called whenever a contact is detected that was also detected last update.
  62. /// Note that this callback is called when all bodies are locked, so don't use any locking functions!
  63. /// Body 1 and 2 will be sorted such that body 1 ID < body 2 ID, so body 1 may not be dynamic
  64. virtual void OnContactPersisted(const Body &inBody1, const Body &inBody2, const ContactManifold &inManifold, ContactSettings &ioSettings) { }
  65. /// Called whenever a contact was detected last update but is not detected anymore.
  66. /// Note that this callback is called when all bodies are locked, so don't use any locking functions!
  67. /// Note that we're using BodyID's since the bodies may have been removed at the time of callback.
  68. /// Body 1 and 2 will be sorted such that body 1 ID < body 2 ID, so body 1 may not be dynamic
  69. virtual void OnContactRemoved(const SubShapeIDPair &inSubShapePair) { }
  70. };
  71. } // JPH