IslandBuilder.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <Physics/Body/BodyID.h>
  5. #include <Core/NonCopyable.h>
  6. #include <atomic>
  7. namespace JPH {
  8. class TempAllocator;
  9. //#define JPH_VALIDATE_ISLAND_BUILDER
  10. /// Keeps track of connected bodies and builds islands for multithreaded velocity/position update
  11. class IslandBuilder : public NonCopyable
  12. {
  13. public:
  14. /// Destructor
  15. ~IslandBuilder();
  16. /// Initialize the island builder with the maximum amount of bodies that could be active
  17. void Init(uint32 inMaxActiveBodies);
  18. /// Prepare for simulation step by allocating space for the contact constraints
  19. void PrepareContactConstraints(uint32 inMaxContactConstraints, TempAllocator *inTempAllocator);
  20. /// Prepare for simulation step by allocating space for the non-contact constraints
  21. void PrepareNonContactConstraints(uint32 inNumConstraints, TempAllocator *inTempAllocator);
  22. /// Link two bodies by their index in the BodyManager::mActiveBodies list to form islands
  23. void LinkBodies(uint32 inFirst, uint32 inSecond);
  24. /// Link a constraint to a body by their index in the BodyManager::mActiveBodies
  25. void LinkConstraint(uint32 inConstraintIndex, uint32 inFirst, uint32 inSecond);
  26. /// Link a contact to a body by their index in the BodyManager::mActiveBodies
  27. void LinkContact(uint32 inContactIndex, uint32 inFirst, uint32 inSecond);
  28. /// Finalize the islands after all bodies have been Link()-ed
  29. void Finalize(const BodyID *inActiveBodies, uint32 inNumActiveBodies, uint32 inNumContacts, TempAllocator *inTempAllocator);
  30. /// Get the amount of islands formed
  31. uint32 GetNumIslands() { return mNumIslands; }
  32. /// Get iterator for a particular island, return false if there are no constraints
  33. void GetBodiesInIsland(uint32 inIslandIndex, BodyID *&outBodiesBegin, BodyID *&outBodiesEnd) const;
  34. bool GetConstraintsInIsland(uint32 inIslandIndex, uint32 *&outConstraintsBegin, uint32 *&outConstraintsEnd) const;
  35. bool GetContactsInIsland(uint32 inIslandIndex, uint32 *&outContactsBegin, uint32 *&outContactsEnd) const;
  36. /// After you're done calling the three functions above, call this function to free associated data
  37. void ResetIslands(TempAllocator *inTempAllocator);
  38. private:
  39. /// Returns the index of the lowest body in the group
  40. uint32 GetLowestBodyIndex(uint32 inActiveBodyIndex) const;
  41. #ifdef JPH_VALIDATE_ISLAND_BUILDER
  42. /// Helper function to validate all islands so far generated
  43. void ValidateIslands(uint32 inNumActiveBodies) const;
  44. #endif
  45. // Helper functions to build various islands
  46. void BuildBodyIslands(const BodyID *inActiveBodies, uint32 inNumActiveBodies, TempAllocator *inTempAllocator);
  47. void BuildConstraintIslands(uint32 *inConstraintToBody, uint32 inNumConstraints, uint32 *&outConstraints, uint32 *&outConstraintsEnd, TempAllocator *inTempAllocator);
  48. /// Sorts the islands so that the islands with most constraints go first
  49. void SortIslands(TempAllocator *inTempAllocator);
  50. /// Intermediate data structure that for each body keeps track what the lowest index of the body is that it is connected to
  51. struct BodyLink
  52. {
  53. atomic<uint32> mLinkedTo; ///< An index in mBodyLinks pointing to another body in this island with a lower index than this body
  54. uint32 mNextLinkOrIslandIndex; ///< If cProcessedLink bit is cleared: Forms a linked list of bodies in the same island, otherwise: points to the island index of this body
  55. };
  56. // Intermediate date
  57. BodyLink * mBodyLinks = nullptr; ///< Maps bodies to the first body in the island
  58. uint32 * mConstraintLinks = nullptr; ///< Maps constraint index to body index (which maps to island index)
  59. uint32 * mContactLinks = nullptr; ///< Maps contact constraint index to body index (which maps to island index)
  60. // Final data
  61. BodyID * mBodyIslands = nullptr; ///< Bodies ordered by island
  62. uint32 * mBodyIslandEnds = nullptr; ///< End index of each body island
  63. uint32 * mConstraintIslands = nullptr; ///< Constraints ordered by island
  64. uint32 * mConstraintIslandEnds = nullptr; ///< End index of each constraint island
  65. uint32 * mContactIslands = nullptr; ///< Contacts ordered by island
  66. uint32 * mContactIslandEnds = nullptr; ///< End index of each contact island
  67. uint32 * mIslandsSorted = nullptr; ///< A list of island indices in order of most constraints first
  68. // Counters
  69. uint32 mMaxActiveBodies; ///< Maximum size of the active bodies list (see BodyManager::mActiveBodies)
  70. uint32 mNumActiveBodies = 0; ///< Number of active bodies passed to
  71. uint32 mNumConstraints = 0; ///< Size of the constraint list (see ConstraintManager::mConstraints)
  72. uint32 mMaxContacts = 0; ///< Maximum amount of contacts supported
  73. uint32 mNumContacts = 0; ///< Size of the contacts list (see ContactConstraintManager::mNumConstraints)
  74. uint32 mNumIslands = 0; ///< Final number of islands
  75. #ifdef JPH_VALIDATE_ISLAND_BUILDER
  76. /// Structure to keep track of all added links to validate that islands were generated correctly
  77. struct LinkValidation
  78. {
  79. uint32 mFirst;
  80. uint32 mSecond;
  81. };
  82. LinkValidation * mLinkValidation = nullptr;
  83. atomic<uint32> mNumLinkValidation;
  84. #endif
  85. };
  86. } // JPH