PhysicsUpdateContext.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Jolt/Physics/Body/BodyPair.h>
  5. #include <Jolt/Physics/Collision/ContactListener.h>
  6. #include <Jolt/Physics/Collision/BroadPhase/BroadPhase.h>
  7. #include <Jolt/Core/StaticArray.h>
  8. #include <Jolt/Core/JobSystem.h>
  9. #include <Jolt/Core/STLTempAllocator.h>
  10. JPH_NAMESPACE_BEGIN
  11. class PhysicsSystem;
  12. class IslandBuilder;
  13. class Constraint;
  14. class TempAllocator;
  15. /// Information used during the Update call
  16. class PhysicsUpdateContext : public NonCopyable
  17. {
  18. public:
  19. /// Destructor
  20. explicit PhysicsUpdateContext(TempAllocator &inTempAllocator);
  21. ~PhysicsUpdateContext();
  22. static constexpr int cMaxConcurrency = 32; ///< Maximum supported amount of concurrent jobs
  23. static constexpr int cMaxSubSteps = 4; ///< Maximum supported amount of integration sub steps
  24. using JobHandleArray = StaticArray<JobHandle, cMaxConcurrency>;
  25. struct Step;
  26. /// Structure that contains job handles for each integration sub step
  27. struct SubStep
  28. {
  29. Step * mStep; ///< Step that this substeb belongs to
  30. bool mIsFirst; ///< If this is the first substep in the step
  31. bool mIsLast; ///< If this is the last substep in the step
  32. bool mIsFirstOfAll; ///< If this is the first substep of the first step
  33. bool mIsLastOfAll; ///< If this is the last substep in the last step
  34. atomic<uint32> mSolveVelocityConstraintsNextIsland { 0 }; ///< Next island that needs to be processed for the solve velocity constraints step (doesn't need own cache line since position jobs don't run at same time)
  35. atomic<uint32> mSolvePositionConstraintsNextIsland { 0 }; ///< Next island that needs to be processed for the solve position constraints step (doesn't need own cache line since velocity jobs don't run at same time)
  36. /// Contains the information needed to cast a body through the scene to do continuous collision detection
  37. struct CCDBody
  38. {
  39. CCDBody(BodyID inBodyID1, Vec3Arg inDeltaPosition, float inLinearCastThresholdSq, float inMaxPenetration) : mDeltaPosition(inDeltaPosition), mBodyID1(inBodyID1), mLinearCastThresholdSq(inLinearCastThresholdSq), mMaxPenetration(inMaxPenetration) { }
  40. Vec3 mDeltaPosition; ///< Desired rotation step
  41. Vec3 mContactNormal; ///< World space normal of closest hit (only valid if mFractionPlusSlop < 1)
  42. Vec3 mContactPointOn2; ///< World space contact point on body 2 of closest hit (only valid if mFractionPlusSlop < 1)
  43. BodyID mBodyID1; ///< Body 1 (the body that is performing collision detection)
  44. BodyID mBodyID2; ///< Body 2 (the body of the closest hit, only valid if mFractionPlusSlop < 1)
  45. float mFraction = 1.0f; ///< Fraction at which the hit occurred
  46. float mFractionPlusSlop = 1.0f; ///< Fraction at which the hit occurred + extra delta to allow body to penetrate by mMaxPenetration
  47. float mLinearCastThresholdSq; ///< Maximum allowed squared movement before doing a linear cast (determined by inner radius of shape)
  48. float mMaxPenetration; ///< Maximum allowed penetration (determined by inner radius of shape)
  49. ContactSettings mContactSettings; ///< The contact settings for this contact
  50. };
  51. atomic<uint32> mIntegrateVelocityReadIdx { 0 }; ///< Next active body index to take when integrating velocities
  52. CCDBody * mCCDBodies = nullptr; ///< List of bodies that need to do continuous collision detection
  53. uint32 mCCDBodiesCapacity = 0; ///< Capacity of the mCCDBodies list
  54. atomic<uint32> mNumCCDBodies = 0; ///< Number of CCD bodies in mCCDBodies
  55. atomic<uint32> mNextCCDBody { 0 }; ///< Next unprocessed body index in mCCDBodies
  56. int * mActiveBodyToCCDBody = nullptr; ///< A mapping between an index in BodyManager::mActiveBodies and the index in mCCDBodies
  57. uint32 mNumActiveBodyToCCDBody = 0; ///< Number of indices in mActiveBodyToCCDBody
  58. JobHandleArray mSolveVelocityConstraints; ///< Solve the constraints in the velocity domain
  59. JobHandle mPreIntegrateVelocity; ///< Setup integration of all body positions
  60. JobHandleArray mIntegrateVelocity; ///< Integrate all body positions
  61. JobHandle mPostIntegrateVelocity; ///< Finalize integration of all body positions
  62. JobHandle mResolveCCDContacts; ///< Updates the positions and velocities for all bodies that need continuous collision detection
  63. JobHandleArray mSolvePositionConstraints; ///< Solve all constraints in the position domain
  64. JobHandle mStartNextSubStep; ///< Trampoline job that either kicks the next sub step or the next step
  65. };
  66. using SubSteps = StaticArray<SubStep, cMaxSubSteps>;
  67. struct BodyPairQueue
  68. {
  69. atomic<uint32> mWriteIdx { 0 }; ///< Next index to write in mBodyPair array (need to add thread index * mMaxBodyPairsPerQueue and modulo mMaxBodyPairsPerQueue)
  70. uint8 mPadding1[JPH_CACHE_LINE_SIZE - sizeof(atomic<uint32>)];///< Moved to own cache line to avoid conflicts with consumer jobs
  71. atomic<uint32> mReadIdx { 0 }; ///< Next index to read in mBodyPair array (need to add thread index * mMaxBodyPairsPerQueue and modulo mMaxBodyPairsPerQueue)
  72. uint8 mPadding2[JPH_CACHE_LINE_SIZE - sizeof(atomic<uint32>)];///< Moved to own cache line to avoid conflicts with producer/consumer jobs
  73. };
  74. using BodyPairQueues = StaticArray<BodyPairQueue, cMaxConcurrency>;
  75. using JobMask = uint32; ///< A mask that has as many bits as we can have concurrent jobs
  76. static_assert(sizeof(JobMask) * 8 >= cMaxConcurrency);
  77. /// Structure that contains data needed for each collision step.
  78. struct Step
  79. {
  80. Step() = default;
  81. Step(const Step &) { JPH_ASSERT(false); } // vector needs a copy constructor, but we're never going to call it
  82. PhysicsUpdateContext *mContext; ///< The physics update context
  83. BroadPhase::UpdateState mBroadPhaseUpdateState; ///< Handle returned by Broadphase::UpdatePrepare
  84. uint32 mNumActiveBodiesAtStepStart; ///< Number of bodies that were active at the start of the physics update step. Only these bodies will receive gravity (they are the first N in the active body list).
  85. atomic<uint32> mConstraintReadIdx { 0 }; ///< Next constraint for determine active constraints
  86. uint8 mPadding1[JPH_CACHE_LINE_SIZE - sizeof(atomic<uint32>)];///< Padding to avoid sharing cache line with the next atomic
  87. atomic<uint32> mNumActiveConstraints { 0 }; ///< Number of constraints in the mActiveConstraints array
  88. uint8 mPadding2[JPH_CACHE_LINE_SIZE - sizeof(atomic<uint32>)];///< Padding to avoid sharing cache line with the next atomic
  89. atomic<uint32> mStepListenerReadIdx { 0 }; ///< Next step listener to call
  90. uint8 mPadding3[JPH_CACHE_LINE_SIZE - sizeof(atomic<uint32>)];///< Padding to avoid sharing cache line with the next atomic
  91. atomic<uint32> mApplyGravityReadIdx { 0 }; ///< Next body to apply gravity to
  92. uint8 mPadding4[JPH_CACHE_LINE_SIZE - sizeof(atomic<uint32>)];///< Padding to avoid sharing cache line with the next atomic
  93. atomic<uint32> mActiveBodyReadIdx { 0 }; ///< Index of fist active body that has not yet been processed by the broadphase
  94. uint8 mPadding5[JPH_CACHE_LINE_SIZE - sizeof(atomic<uint32>)];///< Padding to avoid sharing cache line with the next atomic
  95. BodyPairQueues mBodyPairQueues; ///< Queues in which to put body pairs that need to be tested by the narrowphase
  96. uint32 mMaxBodyPairsPerQueue; ///< Amount of body pairs that we can queue per queue
  97. atomic<JobMask> mActiveFindCollisionJobs; ///< A bitmask that indicates which jobs are still active
  98. atomic<uint> mNumBodyPairs { 0 }; ///< The number of body pairs found in this step (used to size the contact cache in the next step)
  99. atomic<uint> mNumManifolds { 0 }; ///< The number of manifolds found in this step (used to size the contact cache in the next step)
  100. // Jobs in order of execution (some run in parallel)
  101. JobHandle mBroadPhasePrepare; ///< Prepares the new tree in the background
  102. JobHandleArray mStepListeners; ///< Listeners to notify of the beginning of a physics step
  103. JobHandleArray mDetermineActiveConstraints; ///< Determine which constraints will be active during this step
  104. JobHandleArray mApplyGravity; ///< Update velocities of bodies with gravity
  105. JobHandleArray mFindCollisions; ///< Find all collisions between active bodies an the world
  106. JobHandle mUpdateBroadphaseFinalize; ///< Swap the newly built tree with the current tree
  107. JobHandle mSetupVelocityConstraints; ///< Calculate properties for all constraints in the constraint manager
  108. JobHandle mBuildIslandsFromConstraints; ///< Go over all constraints and assign the bodies they're attached to to an island
  109. JobHandle mFinalizeIslands; ///< Finalize calculation simulation islands
  110. JobHandle mBodySetIslandIndex; ///< Set the current island index on each body (not used by the simulation, only for drawing purposes)
  111. SubSteps mSubSteps; ///< Integration sub steps
  112. JobHandle mContactRemovedCallbacks; ///< Calls the contact removed callbacks
  113. JobHandle mStartNextStep; ///< Job that kicks the next step (empty for the last step)
  114. };
  115. using Steps = std::vector<Step, STLTempAllocator<Step>>;
  116. /// Maximum amount of concurrent jobs on this machine
  117. int GetMaxConcurrency() const { const int max_concurrency = PhysicsUpdateContext::cMaxConcurrency; return min(max_concurrency, mJobSystem->GetMaxConcurrency()); } ///< Need to put max concurrency in temp var as min requires a reference
  118. PhysicsSystem * mPhysicsSystem; ///< The physics system we belong to
  119. TempAllocator * mTempAllocator; ///< Temporary allocator used during the update
  120. JobSystem * mJobSystem; ///< Job system that processes jobs
  121. JobSystem::Barrier * mBarrier; ///< Barrier used to wait for all physics jobs to complete
  122. float mStepDeltaTime; ///< Delta time for a simulation step (collision step)
  123. float mSubStepDeltaTime; ///< Delta time for a simulation sub step (integration step)
  124. float mWarmStartImpulseRatio; ///< Ratio of this step delta time vs last step
  125. Constraint ** mActiveConstraints = nullptr; ///< Constraints that were active at the start of the physics update step (activating bodies can activate constraints and we need a consistent snapshot). Only these constraints will be resolved.
  126. BodyPair * mBodyPairs = nullptr; ///< A list of body pairs found by the broadphase
  127. IslandBuilder * mIslandBuilder; ///< Keeps track of connected bodies and builds islands for multithreaded velocity/position update
  128. Steps mSteps;
  129. };
  130. JPH_NAMESPACE_END