IslandBuilder.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. #include <Jolt/Physics/Body/BodyID.h>
  6. #include <Jolt/Core/NonCopyable.h>
  7. #include <Jolt/Core/Atomics.h>
  8. JPH_NAMESPACE_BEGIN
  9. class TempAllocator;
  10. //#define JPH_VALIDATE_ISLAND_BUILDER
  11. /// Keeps track of connected bodies and builds islands for multithreaded velocity/position update
  12. class JPH_EXPORT IslandBuilder : public NonCopyable
  13. {
  14. public:
  15. /// Destructor
  16. ~IslandBuilder();
  17. /// Initialize the island builder with the maximum amount of bodies that could be active
  18. void Init(uint32 inMaxActiveBodies);
  19. /// Prepare for simulation step by allocating space for the contact constraints
  20. void PrepareContactConstraints(uint32 inMaxContactConstraints, TempAllocator *inTempAllocator);
  21. /// Prepare for simulation step by allocating space for the non-contact constraints
  22. void PrepareNonContactConstraints(uint32 inNumConstraints, TempAllocator *inTempAllocator);
  23. /// Link two bodies by their index in the BodyManager::mActiveBodies list to form islands
  24. void LinkBodies(uint32 inFirst, uint32 inSecond);
  25. /// Link a constraint to a body by their index in the BodyManager::mActiveBodies
  26. void LinkConstraint(uint32 inConstraintIndex, uint32 inFirst, uint32 inSecond);
  27. /// Link a contact to a body by their index in the BodyManager::mActiveBodies
  28. void LinkContact(uint32 inContactIndex, uint32 inFirst, uint32 inSecond);
  29. /// Finalize the islands after all bodies have been Link()-ed
  30. void Finalize(const BodyID *inActiveBodies, uint32 inNumActiveBodies, uint32 inNumContacts, TempAllocator *inTempAllocator);
  31. /// Get the amount of islands formed
  32. uint32 GetNumIslands() const { return mNumIslands; }
  33. /// Get iterator for a particular island, return false if there are no constraints
  34. void GetBodiesInIsland(uint32 inIslandIndex, BodyID *&outBodiesBegin, BodyID *&outBodiesEnd) const;
  35. bool GetConstraintsInIsland(uint32 inIslandIndex, uint32 *&outConstraintsBegin, uint32 *&outConstraintsEnd) const;
  36. bool GetContactsInIsland(uint32 inIslandIndex, uint32 *&outContactsBegin, uint32 *&outContactsEnd) const;
  37. /// The number of position iterations for each island
  38. void SetNumPositionSteps(uint32 inIslandIndex, uint inNumPositionSteps) { JPH_ASSERT(inIslandIndex < mNumIslands); JPH_ASSERT(inNumPositionSteps < 256); mNumPositionSteps[inIslandIndex] = uint8(inNumPositionSteps); }
  39. uint GetNumPositionSteps(uint32 inIslandIndex) const { JPH_ASSERT(inIslandIndex < mNumIslands); return mNumPositionSteps[inIslandIndex]; }
  40. #ifdef JPH_TRACK_SIMULATION_STATS
  41. struct IslandStats
  42. {
  43. atomic<uint64> mVelocityConstraintTicks = 0;
  44. atomic<uint64> mPositionConstraintTicks = 0;
  45. atomic<uint64> mUpdateBoundsTicks = 0;
  46. uint8 mNumVelocitySteps = 0;
  47. uint8 mNumPositionSteps = 0; ///< Tracking this a 2nd time since IslandBuilder::mNumPositionSteps is not filled in when there are no constraints or for large islands.
  48. bool mIsLargeIsland = false;
  49. };
  50. /// Tracks simulation stats per island
  51. IslandStats & GetIslandStats(uint32 inIslandIndex) { return mIslandStats[inIslandIndex]; }
  52. #endif
  53. /// After you're done calling the three functions above, call this function to free associated data
  54. void ResetIslands(TempAllocator *inTempAllocator);
  55. private:
  56. /// Returns the index of the lowest body in the group
  57. uint32 GetLowestBodyIndex(uint32 inActiveBodyIndex) const;
  58. #ifdef JPH_VALIDATE_ISLAND_BUILDER
  59. /// Helper function to validate all islands so far generated
  60. void ValidateIslands(uint32 inNumActiveBodies) const;
  61. #endif
  62. // Helper functions to build various islands
  63. void BuildBodyIslands(const BodyID *inActiveBodies, uint32 inNumActiveBodies, TempAllocator *inTempAllocator);
  64. void BuildConstraintIslands(const uint32 *inConstraintToBody, uint32 inNumConstraints, uint32 *&outConstraints, uint32 *&outConstraintsEnd, TempAllocator *inTempAllocator) const;
  65. /// Sorts the islands so that the islands with most constraints go first
  66. void SortIslands(TempAllocator *inTempAllocator);
  67. /// Intermediate data structure that for each body keeps track what the lowest index of the body is that it is connected to
  68. struct BodyLink
  69. {
  70. JPH_OVERRIDE_NEW_DELETE
  71. atomic<uint32> mLinkedTo; ///< An index in mBodyLinks pointing to another body in this island with a lower index than this body
  72. uint32 mIslandIndex; ///< The island index of this body (filled in during Finalize)
  73. };
  74. // Intermediate data
  75. BodyLink * mBodyLinks = nullptr; ///< Maps bodies to the first body in the island
  76. uint32 * mConstraintLinks = nullptr; ///< Maps constraint index to body index (which maps to island index)
  77. uint32 * mContactLinks = nullptr; ///< Maps contact constraint index to body index (which maps to island index)
  78. // Final data
  79. BodyID * mBodyIslands = nullptr; ///< Bodies ordered by island
  80. uint32 * mBodyIslandEnds = nullptr; ///< End index of each body island
  81. uint32 * mConstraintIslands = nullptr; ///< Constraints ordered by island
  82. uint32 * mConstraintIslandEnds = nullptr; ///< End index of each constraint island
  83. uint32 * mContactIslands = nullptr; ///< Contacts ordered by island
  84. uint32 * mContactIslandEnds = nullptr; ///< End index of each contact island
  85. uint32 * mIslandsSorted = nullptr; ///< A list of island indices in order of most constraints first
  86. uint8 * mNumPositionSteps = nullptr; ///< Number of position steps for each island
  87. #ifdef JPH_TRACK_SIMULATION_STATS
  88. IslandStats * mIslandStats = nullptr; ///< Per island statistics
  89. #endif
  90. // Counters
  91. uint32 mMaxActiveBodies; ///< Maximum size of the active bodies list (see BodyManager::mActiveBodies)
  92. uint32 mNumActiveBodies = 0; ///< Number of active bodies passed to
  93. uint32 mNumConstraints = 0; ///< Size of the constraint list (see ConstraintManager::mConstraints)
  94. uint32 mMaxContacts = 0; ///< Maximum amount of contacts supported
  95. uint32 mNumContacts = 0; ///< Size of the contacts list (see ContactConstraintManager::mNumConstraints)
  96. uint32 mNumIslands = 0; ///< Final number of islands
  97. #ifdef JPH_VALIDATE_ISLAND_BUILDER
  98. /// Structure to keep track of all added links to validate that islands were generated correctly
  99. struct LinkValidation
  100. {
  101. uint32 mFirst;
  102. uint32 mSecond;
  103. };
  104. LinkValidation * mLinkValidation = nullptr;
  105. atomic<uint32> mNumLinkValidation;
  106. #endif
  107. };
  108. JPH_NAMESPACE_END