36 inline NodeID() =
default;
39 static inline NodeID sInvalid() {
return NodeID(cInvalidNodeIndex); }
41 static inline NodeID sFromNodeIndex(
uint32 inIdx) { NodeID node_id(inIdx | cIsNode);
JPH_ASSERT(node_id.IsNode());
return node_id; }
44 inline bool IsValid()
const {
return mID != cInvalidNodeIndex; }
45 inline bool IsBody()
const {
return (mID & cIsNode) == 0; }
46 inline bool IsNode()
const {
return (mID & cIsNode) != 0; }
50 inline uint32 GetNodeIndex()
const {
JPH_ASSERT(IsNode());
return mID & ~cIsNode; }
54 inline bool operator == (
const NodeID &inRHS)
const {
return mID == inRHS.mID; }
57 friend class AtomicNodeID;
59 inline explicit NodeID(
uint32 inID) : mID(inID) { }
66 static_assert(
sizeof(NodeID) ==
sizeof(
BodyID),
"Body id's should have the same size as NodeIDs");
73 AtomicNodeID() =
default;
74 explicit AtomicNodeID(
const NodeID &inRHS) : mID(inRHS.mID) { }
77 inline void operator = (
const NodeID &inRHS) { mID = inRHS.mID; }
80 inline operator NodeID ()
const {
return NodeID(mID); }
83 inline bool IsValid()
const {
return mID != cInvalidNodeIndex; }
87 inline bool operator == (
const NodeID &inRHS)
const {
return mID == inRHS.mID; }
90 inline bool CompareExchange(NodeID inOld, NodeID inNew) {
return mID.compare_exchange_strong(inOld.mID, inNew.mID); }
101 explicit Node(
bool inIsChanged);
104 void GetNodeBounds(
AABox &outBounds)
const;
107 void GetChildBounds(
int inChildIndex,
AABox &outBounds)
const;
110 void SetChildBounds(
int inChildIndex,
const AABox &inBounds);
113 void InvalidateChildBounds(
int inChildIndex);
116 bool EncapsulateChildBounds(
int inChildIndex,
const AABox &inBounds);
119 atomic<float> mBoundsMinX[4];
120 atomic<float> mBoundsMinY[4];
121 atomic<float> mBoundsMinZ[4];
122 atomic<float> mBoundsMaxX[4];
123 atomic<float> mBoundsMaxY[4];
124 atomic<float> mBoundsMaxZ[4];
127 AtomicNodeID mChildNodeID[4];
131 atomic<uint32> mParentNodeIndex = cInvalidNodeIndex;
135 atomic<uint32> mIsChanged;
142 static constexpr int cStackSize = 128;
144 static_assert(
sizeof(atomic<float>) == 4,
"Assuming that an atomic doesn't add any additional storage");
145 static_assert(
sizeof(atomic<uint32>) == 4,
"Assuming that an atomic doesn't add any additional storage");
146 static_assert(std::is_trivially_destructible<Node>(),
"Assuming that we don't have a destructor");
152 static_assert(Allocator::ObjectStorageSize == 128,
"Node should be 128 bytes");
159 Tracking(
const Tracking &inRHS) : mBroadPhaseLayer(inRHS.mBroadPhaseLayer.load()), mObjectLayer(inRHS.mObjectLayer.load()), mBodyLocation(inRHS.mBodyLocation.load()) { }
162 static const uint32 cInvalidBodyLocation = 0xffffffff;
165 atomic<ObjectLayer> mObjectLayer = cObjectLayerInvalid;
166 atomic<uint32> mBodyLocation { cInvalidBodyLocation };
174#if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED)
176 void SetName(
const char *inName) { mName = inName; }
177 inline const char *
GetName()
const {
return mName; }
181 inline bool HasBodies()
const {
return mNumBodies != 0; }
184 inline bool IsDirty()
const {
return mIsDirty; }
187 inline bool CanBeUpdated()
const {
return mFreeNodeBatch.mNumObjects == 0; }
190 void Init(Allocator &inAllocator);
198 void DiscardOldTree();
201 AABox GetBounds()
const;
211 NodeID mLeafID = NodeID::sInvalid();
254#ifdef JPH_TRACK_BROADPHASE_STATS
256 uint64 GetTicks100Pct()
const;
259 void ReportStats(
uint64 inTicks100Pct)
const;
264 static const uint32 cInvalidNodeIndex = 0xffffffff;
265 static const float cLargeFloat;
266 static const AABox cInvalidBounds;
272 inline NodeID GetNodeID()
const {
return NodeID::sFromNodeIndex(mIndex); }
275 atomic<uint32> mIndex { cInvalidNodeIndex };
279 void GetBodyLocation(
const TrackingVector &inTracking,
BodyID inBodyID,
uint32 &outNodeIdx,
uint32 &outChildIdx)
const;
280 void SetBodyLocation(TrackingVector &ioTracking,
BodyID inBodyID,
uint32 inNodeIdx,
uint32 inChildIdx)
const;
281 static void sInvalidateBodyLocation(TrackingVector &ioTracking,
BodyID inBodyID);
284 JPH_INLINE
const RootNode & GetCurrentRoot()
const {
return mRootNode[mRootNodeIndex]; }
285 JPH_INLINE RootNode & GetCurrentRoot() {
return mRootNode[mRootNodeIndex]; }
288 inline AABox GetNodeOrBodyBounds(
const BodyVector &inBodies, NodeID inNodeID)
const;
291 inline void MarkNodeAndParentsChanged(
uint32 inNodeIndex);
294 inline void WidenAndMarkNodeAndParentsChanged(
uint32 inNodeIndex,
const AABox &inNewBounds);
297 inline uint32 AllocateNode(
bool inIsChanged);
300 inline bool TryInsertLeaf(TrackingVector &ioTracking,
int inNodeIndex, NodeID inLeafID,
const AABox &inLeafBounds,
int inLeafNumBodies);
303 inline bool TryCreateNewRoot(TrackingVector &ioTracking, atomic<uint32> &ioRootNodeIndex, NodeID inLeafID,
const AABox &inLeafBounds,
int inLeafNumBodies);
306 NodeID BuildTree(
const BodyVector &inBodies, TrackingVector &ioTracking, NodeID *ioNodeIDs,
int inNumber,
uint inMaxDepthMarkChanged,
AABox &outBounds);
310 static void sPartition(NodeID *ioNodeIDs,
Vec3 *ioNodeCenters,
int inNumber,
int &outMidPoint);
315 static void sPartition4(NodeID *ioNodeIDs,
Vec3 *ioNodeCenters,
int inBegin,
int inEnd,
int *outSplit);
320 void ValidateTree(
const BodyVector &inBodies,
const TrackingVector &inTracking,
uint32 inNodeIndex,
uint32 inNumExpectedBodies)
const;
323#ifdef JPH_DUMP_BROADPHASE_TREE
325 void DumpTree(
const NodeID &inRoot,
const char *inFileNamePrefix)
const;
329 Allocator * mAllocator =
nullptr;
332 Allocator::Batch mFreeNodeBatch;
341 RootNode mRootNode[2];
342 atomic<uint32> mRootNodeIndex { 0 };
345 atomic<bool> mIsDirty =
false;
347#ifdef JPH_TRACK_BROADPHASE_STATS
349 mutable Mutex mStatsMutex;
355 uint64 mBodiesVisited = 0;
358 uint64 mCollectorTicks = 0;
364 uint64 GetTicks100Pct(
const LayerToStats &inLayer)
const;
367 void ReportStats(
const char *inName,
const LayerToStats &inLayer,
uint64 inTicks100Pct)
const;
369 mutable LayerToStats mCastRayStats;
370 mutable LayerToStats mCollideAABoxStats;
371 mutable LayerToStats mCollideSphereStats;
372 mutable LayerToStats mCollidePointStats;
373 mutable LayerToStats mCollideOrientedBoxStats;
374 mutable LayerToStats mCastAABoxStats;
378 uint GetMaxTreeDepth(
const NodeID &inNodeID)
const;
381 template <
class Visitor>
384#if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED)
386 const char * mName =
"Layer";
ID of a body. This is a way of reasoning about bodies in a multithreaded simulation while avoiding ra...
Definition BodyID.h:13
static constexpr uint32 cBroadPhaseBit
This bit is used by the broadphase.
Definition BodyID.h:18
uint32 GetIndexAndSequenceNumber() const
Returns the index and sequence number combined in an uint32.
Definition BodyID.h:58