BroadPhase.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Physics/Collision/BroadPhase/BroadPhaseQuery.h>
  5. #include <Physics/Collision/BroadPhase/BroadPhaseLayer.h>
  6. // Shorthand function to ifdef out code if broadphase stats tracking is off
  7. #ifdef JPH_TRACK_BROADPHASE_STATS
  8. #define JPH_IF_TRACK_BROADPHASE_STATS(...) __VA_ARGS__
  9. #else
  10. #define JPH_IF_TRACK_BROADPHASE_STATS(...)
  11. #endif // JPH_TRACK_BROADPHASE_STATS
  12. namespace JPH {
  13. class BodyManager;
  14. struct BodyPair;
  15. using BodyPairCollector = CollisionCollector<BodyPair, CollisionCollectorTraitsCollideShape>;
  16. /// Used to do coarse collision detection operations to quickly prune out bodies that will not collide.
  17. class BroadPhase : public BroadPhaseQuery
  18. {
  19. public:
  20. /// Initialize the broadphase.
  21. /// @param inBodyManager The body manager singleton
  22. /// @param inObjectToBroadPhaseLayer Maps object layer to broadphase layer, @see ObjectToBroadPhaseLayer.
  23. /// Note that the broadphase takes a pointer to the data inside inObjectToBroadPhaseLayer so this object should remain static.
  24. virtual void Init(BodyManager *inBodyManager, const ObjectToBroadPhaseLayer &inObjectToBroadPhaseLayer);
  25. /// Should be called after many objects have been inserted to make the broadphase more efficient, usually done on startup only
  26. virtual void Optimize() { /* Optionally overridden by implementation */ }
  27. /// Must be called just before updating the broadphase when none of the body mutexes are locked
  28. virtual void FrameSync() { /* Optionally overridden by implementation */ }
  29. /// Must be called before UpdatePrepare to prevent modifications from being made to the tree
  30. virtual void LockModifications() { /* Optionally overridden by implementation */ }
  31. /// Context used during broadphase update
  32. struct UpdateState { void *mData[4]; };
  33. /// Update the broadphase, needs to be called frequently to update the internal state when bodies have been modified.
  34. /// The UpdatePrepare() function can run in a background thread without influencing the broadphase
  35. virtual UpdateState UpdatePrepare() { return UpdateState(); }
  36. /// Finalizing the update will quickly apply the changes
  37. virtual void UpdateFinalize(UpdateState &inUpdateState) { /* Optionally overridden by implementation */ }
  38. /// Must be called after UpdateFinalize to allow modifications to the broadphase
  39. virtual void UnlockModifications() { /* Optionally overridden by implementation */ }
  40. /// Handle used during adding bodies to the broadphase
  41. using AddState = void *;
  42. /// Prepare adding inNumber bodies at ioBodies to the broadphase, returns a handle that should be used in AddBodiesFinalize/Abort.
  43. /// This can be done on a background thread without influencing the broadphase.
  44. /// ioBodies may be shuffled around by this function and should be kept that way until AddBodiesFinalize/Abort is called.
  45. virtual AddState AddBodiesPrepare(BodyID *ioBodies, int inNumber) { return nullptr; } // By default the broadphase doesn't support this
  46. /// Finalize adding bodies to the broadphase, supply the return value of AddBodiesPrepare in inAddState.
  47. /// Please ensure that the ioBodies array passed to AddBodiesPrepare is unmodified and passed again to this function.
  48. virtual void AddBodiesFinalize(BodyID *ioBodies, int inNumber, AddState inAddState) = 0;
  49. /// Abort adding bodies to the broadphase, supply the return value of AddBodiesPrepare in inAddState.
  50. /// This can be done on a background thread without influencing the broadphase.
  51. /// Please ensure that the ioBodies array passed to AddBodiesPrepare is unmodified and passed again to this function.
  52. virtual void AddBodiesAbort(BodyID *ioBodies, int inNumber, AddState inAddState) { /* By default nothing needs to be done */ }
  53. /// Remove inNumber bodies in ioBodies from the broadphase.
  54. /// ioBodies may be shuffled around by this function.
  55. virtual void RemoveBodies(BodyID *ioBodies, int inNumber) = 0;
  56. /// Call whenever the aabb of a body changes (can change order of ioBodies array)
  57. /// inTakeLock should be false if we're between LockModifications/UnlockModificiations in which case care needs to be taken to not call this between UpdatePrepare/UpdateFinalize
  58. virtual void NotifyBodiesAABBChanged(BodyID *ioBodies, int inNumber, bool inTakeLock = true) = 0;
  59. /// Call whenever the layer (and optionally the aabb as well) of a body changes (can change order of ioBodies array)
  60. virtual void NotifyBodiesLayerChanged(BodyID *ioBodies, int inNumber) = 0;
  61. /// Find all colliding pairs between dynamic bodies
  62. /// Note that this function is very specifically tailored for the PhysicsSystem::Update function, hence it is not part of the BroadPhaseQuery interface.
  63. /// One of the assumptions it can make is that no locking is needed during the query as it will only be called during a very particular part of the update.
  64. /// @param ioActiveBodies is a list of bodies for which we need to find colliding pairs (this function can change the order of the ioActiveBodies array). This can be a subset of the set of active bodies in the system.
  65. /// @param inNumActiveBodies is the size of the ioActiveBodies array.
  66. /// @param inSpeculativeContactDistance Distance at which speculative contact points will be created.
  67. /// @param inObjectVsBroadPhaseLayerFilter is the filter that determines if an object can collide with a broadphase layer.
  68. /// @param inObjectLayerPairFilter is the filter that determines if two objects can collide.
  69. /// @param ioPairCollector receives callbacks for every body pair found.
  70. virtual void FindCollidingPairs(BodyID *ioActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, ObjectVsBroadPhaseLayerFilter inObjectVsBroadPhaseLayerFilter, ObjectLayerPairFilter inObjectLayerPairFilter, BodyPairCollector &ioPairCollector) const = 0;
  71. /// Same as BroadPhaseQuery::CastAABox but can be implemented in a way to take no broad phase locks.
  72. virtual void CastAABoxNoLock(const AABoxCast &inBox, CastShapeBodyCollector &ioCollector, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter) const = 0;
  73. #if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED)
  74. /// Set function that converts a broadphase layer to a human readable string for debugging purposes
  75. virtual void SetBroadPhaseLayerToString(BroadPhaseLayerToString inBroadPhaseLayerToString) { /* Can be implemented by derived classes */ }
  76. #endif // JPH_EXTERNAL_PROFILE || JPH_PROFILE_ENABLED
  77. #ifdef JPH_TRACK_BROADPHASE_STATS
  78. /// Trace the collected broadphase stats in CSV form.
  79. /// This report can be used to judge and tweak the efficiency of the broadphase.
  80. virtual void ReportStats() { /* Can be implemented by derived classes */ }
  81. #endif // JPH_TRACK_BROADPHASE_STATS
  82. protected:
  83. /// Link to the body manager that manages the bodies in this broadphase
  84. BodyManager * mBodyManager = nullptr;
  85. };
  86. } // JPH