// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics) // SPDX-FileCopyrightText: 2021 Jorrit Rouwe // SPDX-License-Identifier: MIT #pragma once #include JPH_NAMESPACE_BEGIN /// ID of a body. This is a way of reasoning about bodies in a multithreaded simulation while avoiding race conditions. class BodyID { public: JPH_OVERRIDE_NEW_DELETE static constexpr uint32 cInvalidBodyID = 0xffffffff; ///< The value for an invalid body ID static constexpr uint32 cBroadPhaseBit = 0x00800000; ///< This bit is used by the broadphase static constexpr uint32 cMaxBodyIndex = 0x7fffff; ///< Maximum value for body index (also the maximum amount of bodies supported - 1) static constexpr uint8 cMaxSequenceNumber = 0xff; ///< Maximum value for the sequence number /// Construct invalid body ID BodyID() : mID(cInvalidBodyID) { } /// Construct from index and sequence number combined in a single uint32 (use with care!) explicit BodyID(uint32 inID) : mID(inID) { JPH_ASSERT((inID & cBroadPhaseBit) == 0 || inID == cInvalidBodyID); // Check bit used by broadphase } /// Construct from index and sequence number explicit BodyID(uint32 inID, uint8 inSequenceNumber) : mID((uint32(inSequenceNumber) << 24) | inID) { JPH_ASSERT(inID < cMaxBodyIndex); // Should not use bit pattern for invalid ID and should not use the broadphase bit } /// Get index in body array inline uint32 GetIndex() const { return mID & cMaxBodyIndex; } /// Get sequence number of body. /// The sequence number can be used to check if a body ID with the same body index has been reused by another body. /// It is mainly used in multi threaded situations where a body is removed and its body index is immediately reused by a body created from another thread. /// Functions querying the broadphase can (after acquiring a body lock) detect that the body has been removed (we assume that this won't happen more than 128 times in a row). inline uint8 GetSequenceNumber() const { return uint8(mID >> 24); } /// Returns the index and sequence number combined in an uint32 inline uint32 GetIndexAndSequenceNumber() const { return mID; } /// Check if the ID is valid inline bool IsInvalid() const { return mID == cInvalidBodyID; } /// Equals check inline bool operator == (const BodyID &inRHS) const { return mID == inRHS.mID; } /// Not equals check inline bool operator != (const BodyID &inRHS) const { return mID != inRHS.mID; } /// Smaller than operator, can be used for sorting bodies inline bool operator < (const BodyID &inRHS) const { return mID < inRHS.mID; } /// Greater than operator, can be used for sorting bodies inline bool operator > (const BodyID &inRHS) const { return mID > inRHS.mID; } private: uint32 mID; }; JPH_NAMESPACE_END // Create a std::hash/JPH::Hash for BodyID JPH_MAKE_HASHABLE(JPH::BodyID, t.GetIndexAndSequenceNumber())