36 inline NodeID() =
default;
39 static inline NodeID sInvalid() {
return NodeID(cInvalidNodeIndex); }
41 static inline NodeID sFromNodeIndex(
uint32 inIdx) {
JPH_ASSERT((inIdx & cIsNode) == 0);
return NodeID(inIdx | cIsNode); }
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");
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);
254#ifdef JPH_TRACK_BROADPHASE_STATS
256 uint64 GetTicks100Pct()
const;
259 void ReportStats(
uint64 inTicks100Pct)
const;
264 static constexpr uint32 cInvalidNodeIndex = 0xffffffff;
265 static const AABox cInvalidBounds;
271 inline NodeID GetNodeID()
const {
return NodeID::sFromNodeIndex(mIndex); }
274 atomic<uint32> mIndex { cInvalidNodeIndex };
278 void GetBodyLocation(
const TrackingVector &inTracking, BodyID inBodyID,
uint32 &outNodeIdx,
uint32 &outChildIdx)
const;
279 void SetBodyLocation(TrackingVector &ioTracking, BodyID inBodyID,
uint32 inNodeIdx,
uint32 inChildIdx)
const;
280 static void sInvalidateBodyLocation(TrackingVector &ioTracking, BodyID inBodyID);
283 JPH_INLINE
const RootNode & GetCurrentRoot()
const {
return mRootNode[mRootNodeIndex]; }
284 JPH_INLINE RootNode & GetCurrentRoot() {
return mRootNode[mRootNodeIndex]; }
287 inline AABox GetNodeOrBodyBounds(
const BodyVector &inBodies, NodeID inNodeID)
const;
290 inline void MarkNodeAndParentsChanged(
uint32 inNodeIndex);
293 inline void WidenAndMarkNodeAndParentsChanged(
uint32 inNodeIndex,
const AABox &inNewBounds);
296 inline uint32 AllocateNode(
bool inIsChanged);
299 inline bool TryInsertLeaf(TrackingVector &ioTracking,
int inNodeIndex, NodeID inLeafID,
const AABox &inLeafBounds,
int inLeafNumBodies);
302 inline bool TryCreateNewRoot(TrackingVector &ioTracking, atomic<uint32> &ioRootNodeIndex, NodeID inLeafID,
const AABox &inLeafBounds,
int inLeafNumBodies);
305 NodeID BuildTree(
const BodyVector &inBodies, TrackingVector &ioTracking, NodeID *ioNodeIDs,
int inNumber,
uint inMaxDepthMarkChanged, AABox &outBounds);
309 static void sPartition(NodeID *ioNodeIDs, Vec3 *ioNodeCenters,
int inNumber,
int &outMidPoint);
314 static void sPartition4(NodeID *ioNodeIDs, Vec3 *ioNodeCenters,
int inBegin,
int inEnd,
int *outSplit);
319 void ValidateTree(
const BodyVector &inBodies,
const TrackingVector &inTracking,
uint32 inNodeIndex,
uint32 inNumExpectedBodies)
const;
322#ifdef JPH_DUMP_BROADPHASE_TREE
324 void DumpTree(
const NodeID &inRoot,
const char *inFileNamePrefix)
const;
328 Allocator * mAllocator =
nullptr;
331 Allocator::Batch mFreeNodeBatch;
340 RootNode mRootNode[2];
341 atomic<uint32> mRootNodeIndex { 0 };
344 atomic<bool> mIsDirty =
false;
346#ifdef JPH_TRACK_BROADPHASE_STATS
348 mutable Mutex mStatsMutex;
354 uint64 mBodiesVisited = 0;
357 uint64 mCollectorTicks = 0;
360 using LayerToStats = UnorderedMap<String, Stat>;
363 uint64 GetTicks100Pct(
const LayerToStats &inLayer)
const;
366 void ReportStats(
const char *inName,
const LayerToStats &inLayer,
uint64 inTicks100Pct)
const;
368 mutable LayerToStats mCastRayStats;
369 mutable LayerToStats mCollideAABoxStats;
370 mutable LayerToStats mCollideSphereStats;
371 mutable LayerToStats mCollidePointStats;
372 mutable LayerToStats mCollideOrientedBoxStats;
373 mutable LayerToStats mCastAABoxStats;
377 uint GetMaxTreeDepth(
const NodeID &inNodeID)
const;
380 template <
class Visitor>
381 JPH_INLINE
void WalkTree(
const ObjectLayerFilter &inObjectLayerFilter,
const TrackingVector &inTracking, Visitor &ioVisitor
JPH_IF_TRACK_BROADPHASE_STATS(, LayerToStats &ioStats))
const;
383#if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED)
385 const char * mName =
"Layer";
Array< Body * > BodyVector
Array of bodies.
Definition BodyManager.h:37
#define JPH_IF_TRACK_BROADPHASE_STATS(...)
Definition BroadPhase.h:16
CollisionCollector< BodyPair, CollisionCollectorTraitsCollideShape > BodyPairCollector
Definition BroadPhase.h:22
CollisionCollector< BroadPhaseCastResult, CollisionCollectorTraitsCastRay > RayCastBodyCollector
Definition BroadPhaseQuery.h:22
CollisionCollector< BodyID, CollisionCollectorTraitsCollideShape > CollideShapeBodyCollector
Definition BroadPhaseQuery.h:24
CollisionCollector< BroadPhaseCastResult, CollisionCollectorTraitsCastShape > CastShapeBodyCollector
Definition BroadPhaseQuery.h:23
#define JPH_EXPORT
Definition Core.h:275
#define JPH_CACHE_LINE_SIZE
Definition Core.h:545
std::uint64_t uint64
Definition Core.h:504
unsigned int uint
Definition Core.h:500
#define JPH_NAMESPACE_END
Definition Core.h:425
std::uint32_t uint32
Definition Core.h:503
#define JPH_NAMESPACE_BEGIN
Definition Core.h:419
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
const Vec3 Vec3Arg
Definition MathTypes.h:19
#define JPH_OVERRIDE_NEW_DELETE
Macro to override the new and delete functions.
Definition Memory.h:50
Axis aligned box.
Definition AABox.h:16
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:59
uint8 Type
Definition BroadPhaseLayer.h:20
Definition FixedSizeFreeList.h:18
static const int ObjectStorageSize
Definition FixedSizeFreeList.h:79
Filter class for object layers.
Definition ObjectLayer.h:28
Filter class to test if two objects can collide based on their object layer. Used while finding colli...
Definition ObjectLayer.h:50
Oriented box.
Definition OrientedBox.h:18
const char * GetName() const
Definition QuadTree.h:177
bool HasBodies() const
Check if there is anything in the tree.
Definition QuadTree.h:181
void CastRay(const RayCast &inRay, RayCastBodyCollector &ioCollector, const ObjectLayerFilter &inObjectLayerFilter, const TrackingVector &inTracking) const
Cast a ray and get the intersecting bodies in ioCollector.
Definition QuadTree.cpp:1081
void FindCollidingPairs(const BodyVector &inBodies, const BodyID *inActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, BodyPairCollector &ioPairCollector, const ObjectLayerPairFilter &inObjectLayerPairFilter) const
Find all colliding pairs between dynamic bodies, calls ioPairCollector for every pair found.
Definition QuadTree.cpp:1433
void CollideOrientedBox(const OrientedBox &inBox, CollideShapeBodyCollector &ioCollector, const ObjectLayerFilter &inObjectLayerFilter, const TrackingVector &inTracking) const
Get bodies intersecting with an oriented box and any hits to ioCollector.
Definition QuadTree.cpp:1311
void AddBodiesAbort(TrackingVector &ioTracking, const AddState &inState)
Definition QuadTree.cpp:860
void DiscardOldTree()
Will throw away the previous frame's nodes so that we can start building a new tree in the background...
Definition QuadTree.cpp:246
void AddBodiesPrepare(const BodyVector &inBodies, TrackingVector &ioTracking, BodyID *ioBodyIDs, int inNumber, AddState &outState)
Definition QuadTree.cpp:815
AABox GetBounds() const
Get the bounding box for this tree.
Definition QuadTree.cpp:263
void CollideAABox(const AABox &inBox, CollideShapeBodyCollector &ioCollector, const ObjectLayerFilter &inObjectLayerFilter, const TrackingVector &inTracking) const
Get bodies intersecting with inBox in ioCollector.
Definition QuadTree.cpp:1143
void NotifyBodiesAABBChanged(const BodyVector &inBodies, const TrackingVector &inTracking, const BodyID *ioBodyIDs, int inNumber)
Call whenever the aabb of a body changes.
Definition QuadTree.cpp:937
bool IsDirty() const
Check if the tree needs an UpdatePrepare/Finalize().
Definition QuadTree.h:184
void UpdateFinalize(const BodyVector &inBodies, const TrackingVector &inTracking, const UpdateState &inUpdateState)
Definition QuadTree.cpp:396
void CastAABox(const AABoxCast &inBox, CastShapeBodyCollector &ioCollector, const ObjectLayerFilter &inObjectLayerFilter, const TrackingVector &inTracking) const
Cast a box and get intersecting bodies in ioCollector.
Definition QuadTree.cpp:1365
bool CanBeUpdated() const
Check if this tree can get an UpdatePrepare/Finalize() or if it needs a DiscardOldTree() first.
Definition QuadTree.h:187
void AddBodiesFinalize(TrackingVector &ioTracking, int inNumberBodies, const AddState &inState)
Finalize adding bodies to the quadtree, supply the same number of bodies as in AddBodiesPrepare.
Definition QuadTree.cpp:837
void CollidePoint(Vec3Arg inPoint, CollideShapeBodyCollector &ioCollector, const ObjectLayerFilter &inObjectLayerFilter, const TrackingVector &inTracking) const
Get bodies intersecting with a point and any hits to ioCollector.
Definition QuadTree.cpp:1257
void CollideSphere(Vec3Arg inCenter, float inRadius, CollideShapeBodyCollector &ioCollector, const ObjectLayerFilter &inObjectLayerFilter, const TrackingVector &inTracking) const
Get bodies intersecting with a sphere in ioCollector.
Definition QuadTree.cpp:1197
Array< Tracking > TrackingVector
Definition QuadTree.h:169
void UpdatePrepare(const BodyVector &inBodies, TrackingVector &ioTracking, UpdateState &outUpdateState, bool inFullRebuild)
Definition QuadTree.cpp:274
void SetName(const char *inName)
Name of the tree for debugging purposes.
Definition QuadTree.h:176
void RemoveBodies(const BodyVector &inBodies, TrackingVector &ioTracking, const BodyID *ioBodyIDs, int inNumber)
Remove inNumber bodies in ioBodyIDs from the quadtree.
Definition QuadTree.cpp:901
FixedSizeFreeList< Node > Allocator
Class that allocates tree nodes, can be shared between multiple trees.
Definition QuadTree.h:150
Structure that holds AABox moving linearly through 3d space.
Definition AABoxCast.h:13
Temporary data structure to pass information between AddBodiesPrepare and AddBodiesFinalize/Abort.
Definition QuadTree.h:210
AABox mLeafBounds
Definition QuadTree.h:212
NodeID mLeafID
Definition QuadTree.h:211
atomic< BroadPhaseLayer::Type > mBroadPhaseLayer
Definition QuadTree.h:164
static const uint32 cInvalidBodyLocation
Invalid body location identifier.
Definition QuadTree.h:162
Tracking(const Tracking &inRHS)
Definition QuadTree.h:159
atomic< ObjectLayer > mObjectLayer
Definition QuadTree.h:165
atomic< uint32 > mBodyLocation
Definition QuadTree.h:166
Tracking()=default
Constructor to satisfy the vector class.
Definition QuadTree.h:193
NodeID mRootNodeID
This will be the new root node id.
Definition QuadTree.h:194