feat(physics): wire physx sdk into build

This commit is contained in:
2026-04-15 12:22:15 +08:00
parent 5bf258df6d
commit 31f40e2cbb
2044 changed files with 752623 additions and 1 deletions

View File

@@ -0,0 +1,217 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef BP_AABBMANAGER_H
#define BP_AABBMANAGER_H
#include "foundation/PxHashSet.h"
#include "foundation/PxHashMap.h"
#include "BpAABBManagerTasks.h"
#include "BpAABBManagerBase.h"
namespace physx
{
namespace Cm
{
class FlushPool;
}
namespace Bp
{
struct BroadPhasePair;
class Aggregate;
class PersistentPairs;
class PersistentActorAggregatePair;
class PersistentAggregateAggregatePair;
class PersistentSelfCollisionPairs;
struct AggPair
{
PX_FORCE_INLINE AggPair() {}
PX_FORCE_INLINE AggPair(ShapeHandle index0, ShapeHandle index1) : mIndex0(index0), mIndex1(index1) {}
ShapeHandle mIndex0;
ShapeHandle mIndex1;
PX_FORCE_INLINE bool operator==(const AggPair& p) const
{
return (p.mIndex0 == mIndex0) && (p.mIndex1 == mIndex1);
}
};
typedef PxCoalescedHashMap<AggPair, PersistentPairs*> AggPairMap;
// PT: TODO: isn't there a generic pair structure somewhere? refactor with AggPair anyway
struct Pair
{
PX_FORCE_INLINE Pair(PxU32 id0, PxU32 id1) : mID0(id0), mID1(id1) {}
PX_FORCE_INLINE Pair(){}
PX_FORCE_INLINE bool operator<(const Pair& p) const
{
const PxU64 value0 = *reinterpret_cast<const PxU64*>(this);
const PxU64 value1 = *reinterpret_cast<const PxU64*>(&p);
return value0 < value1;
}
PX_FORCE_INLINE bool operator==(const Pair& p) const
{
const PxU64 value0 = *reinterpret_cast<const PxU64*>(this);
const PxU64 value1 = *reinterpret_cast<const PxU64*>(&p);
return value0 == value1;
}
PX_FORCE_INLINE bool operator!=(const Pair& p) const
{
const PxU64 value0 = *reinterpret_cast<const PxU64*>(this);
const PxU64 value1 = *reinterpret_cast<const PxU64*>(&p);
return value0 != value1;
}
PxU32 mID0;
PxU32 mID1;
};
class AABBManager;
class PostBroadPhaseStage2Task : public Cm::Task
{
Cm::FlushPool* mFlushPool;
AABBManager& mManager;
PX_NOCOPY(PostBroadPhaseStage2Task)
public:
PostBroadPhaseStage2Task(PxU64 contextID, AABBManager& manager) : Cm::Task(contextID), mFlushPool(NULL), mManager(manager)
{
}
virtual const char* getName() const { return "PostBroadPhaseStage2Task"; }
void setFlushPool(Cm::FlushPool* pool) { mFlushPool = pool; }
virtual void runInternal();
};
class ProcessAggPairsBase;
/**
\brief A structure responsible for:
* storing an aabb representation for each active shape in the related scene
* managing the creation/removal of aabb representations when their related shapes are created/removed
* updating all aabbs that require an update due to modification of shape geometry or transform
* updating the aabb of all aggregates from the union of the aabbs of all shapes that make up each aggregate
* computing and reporting the incremental changes to the set of overlapping aabb pairs
*/
class AABBManager : public AABBManagerBase
{
PX_NOCOPY(AABBManager)
public:
AABBManager(BroadPhase& bp, BoundsArray& boundsArray, PxFloatArrayPinned& contactDistance,
PxU32 maxNbAggregates, PxU32 maxNbShapes, PxVirtualAllocator& allocator, PxU64 contextID,
PxPairFilteringMode::Enum kineKineFilteringMode, PxPairFilteringMode::Enum staticKineFilteringMode);
virtual ~AABBManager() {}
// AABBManagerBase
virtual void destroy() PX_OVERRIDE PX_FINAL;
virtual AggregateHandle createAggregate(BoundsIndex index, Bp::FilterGroup::Enum group, void* userData, PxU32 maxNumShapes, PxAggregateFilterHint filterHint, PxU32 envID) PX_OVERRIDE PX_FINAL;
virtual bool destroyAggregate(BoundsIndex& index, Bp::FilterGroup::Enum& group, AggregateHandle aggregateHandle) PX_OVERRIDE PX_FINAL;
virtual bool addBounds(BoundsIndex index, PxReal contactDistance, Bp::FilterGroup::Enum group, void* userdata, AggregateHandle aggregateHandle, ElementType::Enum volumeType, PxU32 envID) PX_OVERRIDE PX_FINAL;
virtual bool removeBounds(BoundsIndex index) PX_OVERRIDE PX_FINAL;
virtual void updateBPFirstPass(PxU32 numCpuTasks, Cm::FlushPool& flushPool, bool hasContactDistanceUpdated, PxBaseTask* continuation) PX_OVERRIDE PX_FINAL;
virtual void updateBPSecondPass(PxcScratchAllocator* scratchAllocator, PxBaseTask* continuation) PX_OVERRIDE PX_FINAL;
virtual void postBroadPhase(PxBaseTask*, Cm::FlushPool& flushPool) PX_OVERRIDE PX_FINAL;
virtual void reallocateChangedAABBMgActorHandleMap(const PxU32 size) PX_OVERRIDE PX_FINAL;
virtual bool getOutOfBoundsObjects(OutOfBoundsData& data) PX_OVERRIDE PX_FINAL;
virtual void clearOutOfBoundsObjects() PX_OVERRIDE PX_FINAL;
virtual void visualize(PxRenderOutput& out) PX_OVERRIDE PX_FINAL;
virtual void releaseDeferredAggregateIds() PX_OVERRIDE PX_FINAL {}
//~AABBManagerBase
void preBpUpdate_CPU(PxU32 numCpuTasks);
// PT: TODO: what is that BpCacheData for?
BpCacheData* getBpCacheData();
void putBpCacheData(BpCacheData*);
void resetBpCacheData();
PxMutex mMapLock;
private:
//void reserveShapeSpace(PxU32 nbShapes);
void postBpStage2(PxBaseTask*, Cm::FlushPool&);
void postBpStage3(PxBaseTask*);
PostBroadPhaseStage2Task mPostBroadPhase2;
Cm::DelegateTask<AABBManager, &AABBManager::postBpStage3> mPostBroadPhase3;
PreBpUpdateTask mPreBpUpdateTask;
PxU32 mTimestamp;
PxU32 mFirstFreeAggregate;
PxArray<Aggregate*> mAggregates; // PT: indexed by AggregateHandle
PxArray<Aggregate*> mDirtyAggregates;
AggPairMap mActorAggregatePairs;
AggPairMap mAggregateAggregatePairs;
PxArray<ProcessAggPairsBase*> mAggPairTasks;
PxHashSet<Pair> mCreatedPairsTmp; // PT: temp hashset for dubious post filtering, persistent to minimize allocs
PxSList mBpThreadContextPool;
PxArray<void*> mOutOfBoundsObjects;
PxArray<void*> mOutOfBoundsAggregates;
PX_FORCE_INLINE Aggregate* getAggregateFromHandle(AggregateHandle handle)
{
PX_ASSERT(handle<mAggregates.size());
return mAggregates[handle];
}
void startAggregateBoundsComputationTasks(PxU32 nbToGo, PxU32 numCpuTasks, Cm::FlushPool& flushPool);
PersistentActorAggregatePair* createPersistentActorAggregatePair(ShapeHandle volA, ShapeHandle volB);
PersistentAggregateAggregatePair* createPersistentAggregateAggregatePair(ShapeHandle volA, ShapeHandle volB);
void updatePairs(PersistentPairs& p, BpCacheData* data = NULL);
void handleOriginShift();
public:
void processBPCreatedPair(const BroadPhasePair& pair);
void processBPDeletedPair(const BroadPhasePair& pair);
friend class PersistentActorAggregatePair;
friend class PersistentAggregateAggregatePair;
friend class ProcessSelfCollisionPairsParallel;
friend class PostBroadPhaseStage2Task;
};
} //namespace Bp
} //namespace physx
#endif //BP_AABBMANAGER_H

View File

@@ -0,0 +1,396 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef BP_AABBMANAGER_BASE_H
#define BP_AABBMANAGER_BASE_H
#include "foundation/PxAllocator.h"
#include "foundation/PxPinnedArray.h"
#include "foundation/PxBitMap.h"
#include "foundation/PxSList.h"
#include "foundation/PxBitUtils.h"
#include "BpVolumeData.h"
#include "BpBroadPhaseUpdate.h"
#include "GuBounds.h"
#include "PxFiltering.h"
#include "PxAggregate.h"
#include "foundation/PxSimpleTypes.h"
namespace physx
{
class PxcScratchAllocator;
class PxRenderOutput;
class PxBaseTask;
namespace Cm
{
class FlushPool;
}
namespace Bp
{
typedef PxU32 BoundsIndex;
//typedef PxU32 ActorHandle;
/**
\brief Changes to the configuration of overlap pairs are reported as void* pairs.
\note Each void* in the pair corresponds to the void* passed to AABBManager::createVolume.
\see AABBManager::createVolume, AABBManager::getCreatedOverlaps, AABBManager::getDestroyedOverlaps
*/
struct AABBOverlap
{
PX_FORCE_INLINE AABBOverlap() {}
PX_FORCE_INLINE AABBOverlap(void* userData0, void* userData1/*, ActorHandle pairHandle*/) : mUserData0(userData0), mUserData1(userData1)/*, mPairHandle(pairHandle)*/
{
// PT: TODO: why is this forbidden?
PX_ASSERT(userData0 != userData1);
}
// PT: these will eventually be the userData pointers passed to addBounds(), i.e. Sc::ElementSim pointers in PhysX. This may not be
// necessary at all, since in the current design the bounds indices themselves come from BP clients (they're not handles managed by the BP).
// So there's a 1:1 mapping between bounds-indices (which are effectively edlement IDs in PhysX) and the userData pointers (Sc::ElementSim).
// Thus we could just return bounds indices directly to users - at least in the context of PhysX, maybe the standalone BP is different.
void* mUserData0;
void* mUserData1;
// PT: TODO: not sure what happened there but mPairUserData is not used inside the BP itself so we need to revisit this.
/* union
{
ActorHandle mPairHandle; //For created pairs, this is the index into the pair in the pair manager
void* mUserData; //For deleted pairs, this is the user data written by the application to the pair
};*/
void* mPairUserData; //For deleted pairs, this is the user data written by the application to the pair
};
struct BpCacheData : public PxSListEntry
{
PxArray<AABBOverlap> mCreatedPairs[2];
PxArray<AABBOverlap> mDeletedPairs[2];
void reset()
{
mCreatedPairs[0].resizeUninitialized(0);
mCreatedPairs[1].resizeUninitialized(0);
mDeletedPairs[0].resizeUninitialized(0);
mDeletedPairs[1].resizeUninitialized(0);
}
};
typedef PxPinnedArray<Bp::FilterGroup::Enum> GroupsArrayPinned;
typedef PxPinnedArray<VolumeData> VolumeDataArrayPinned;
typedef PxPinnedArray<ShapeHandle> ShapeHandleArrayPinned;
class BoundsArray : public PxUserAllocated
{
PX_NOCOPY(BoundsArray)
public:
BoundsArray(PxVirtualAllocator& allocator) : mBounds(allocator), mHasAnythingChanged(true) {} //needs to be set explicitly for PxgBounds first copy
virtual ~BoundsArray(){}
PX_FORCE_INLINE void initEntry(PxU32 index)
{
index++; // PT: always pretend we need one more entry, to make sure reading the last used entry will be SIMD-safe.
const PxU32 oldCapacity = mBounds.capacity();
if (index >= oldCapacity)
{
const PxU32 newCapacity = PxNextPowerOfTwo(index);
mBounds.reserve(newCapacity);
mBounds.forceSize_Unsafe(newCapacity);
}
}
virtual void updateBounds(const PxTransform& transform, const PxGeometry& geom, PxU32 index, PxU32 /*indexFrom*/)
{
Gu::computeBounds(mBounds[index], geom, transform, 0.0f, 1.0f);
mHasAnythingChanged = true;
}
virtual void setBounds(const PxBounds3& bounds, PxU32 index)
{
// PX_CHECK_AND_RETURN(bounds.isValid() && !bounds.isEmpty(), "BoundsArray::setBounds - illegal bounds\n");
mBounds[index] = bounds;
mHasAnythingChanged = true;
}
PX_FORCE_INLINE const PxBounds3* begin() const { return mBounds.begin(); }
PX_FORCE_INLINE PxBounds3* begin() { return mBounds.begin(); }
PX_FORCE_INLINE PxBoundsArrayPinned& getBounds() { return mBounds; }
PX_FORCE_INLINE const PxBounds3& getBounds(PxU32 index) const { return mBounds[index]; }
PX_FORCE_INLINE PxU32 size() const { return mBounds.size(); }
PX_FORCE_INLINE bool hasChanged() const { return mHasAnythingChanged; }
PX_FORCE_INLINE void resetChangedState() { mHasAnythingChanged = false; }
PX_FORCE_INLINE void setChangedState() { mHasAnythingChanged = true; }
void shiftOrigin(const PxVec3& shift)
{
// we shift some potential NaNs here because we don't know what's active, but should be harmless
const PxU32 nbBounds = mBounds.size();
for(PxU32 i=0; i<nbBounds; i++)
{
mBounds[i].minimum -= shift;
mBounds[i].maximum -= shift;
}
mHasAnythingChanged = true;
}
protected:
PxBoundsArrayPinned mBounds;
bool mHasAnythingChanged;
};
/**
\brief A structure responsible for:
* storing an aabb representation for each active shape in the related scene
* managing the creation/removal of aabb representations when their related shapes are created/removed
* updating all aabbs that require an update due to modification of shape geometry or transform
* updating the aabb of all aggregates from the union of the aabbs of all shapes that make up each aggregate
* computing and reporting the incremental changes to the set of overlapping aabb pairs
*/
class AABBManagerBase : public PxUserAllocated
{
PX_NOCOPY(AABBManagerBase)
public:
AABBManagerBase(BroadPhase& bp, BoundsArray& boundsArray, PxFloatArrayPinned& contactDistance,
PxU32 maxNbAggregates, PxU32 maxNbShapes, PxVirtualAllocator& allocator, PxU64 contextID,
PxPairFilteringMode::Enum kineKineFilteringMode, PxPairFilteringMode::Enum staticKineFilteringMode);
virtual ~AABBManagerBase() {}
virtual void destroy() = 0;
virtual AggregateHandle createAggregate(BoundsIndex index, Bp::FilterGroup::Enum group, void* userData, PxU32 maxNumShapes, PxAggregateFilterHint filterHint, PxU32 envID) = 0;
virtual bool destroyAggregate(BoundsIndex& index, Bp::FilterGroup::Enum& group, AggregateHandle aggregateHandle) = 0;
virtual bool addBounds(BoundsIndex index, PxReal contactDistance, Bp::FilterGroup::Enum group, void* userdata, AggregateHandle aggregateHandle, ElementType::Enum volumeType, PxU32 envID) = 0;
virtual bool removeBounds(BoundsIndex index) = 0;
void reserveSpaceForBounds(BoundsIndex index);
PX_FORCE_INLINE PxIntBool isMarkedForRemove(BoundsIndex index) const { return mRemovedHandleMap.boundedTest(index); }
// PX_FORCE_INLINE PxIntBool isMarkedForAdd(BoundsIndex index) const { return mAddedHandleMap.boundedTest(index); }
PX_FORCE_INLINE BroadPhase* getBroadPhase() const { return &mBroadPhase; }
PX_FORCE_INLINE BoundsArray& getBoundsArray() { return mBoundsArray; }
PX_FORCE_INLINE PxU32 getNbActiveAggregates() const { return mNbAggregates; }
PX_FORCE_INLINE const float* getContactDistances() const { return mContactDistance.begin(); }
PX_FORCE_INLINE PxBitMapPinned& getChangedAABBMgActorHandleMap() { return mChangedHandleMap; }
PX_FORCE_INLINE void* getUserData(const BoundsIndex index) const { return (index<mVolumeData.size()) ? mVolumeData[index].getUserData() : NULL; }
void setContactDistance(BoundsIndex handle, PxReal offset)
{
// PT: this works even for aggregated shapes, since the corresponding bit will also be set in the 'updated' map.
mContactDistance.begin()[handle] = offset;
setPersistentStateChanged();
mChangedHandleMap.growAndSet(handle);
}
void setBPGroup(BoundsIndex index, Bp::FilterGroup::Enum group)
{
PX_ASSERT((index + 1) < mVolumeData.size());
PX_ASSERT(group != Bp::FilterGroup::eINVALID); // PT: we use group == Bp::FilterGroup::eINVALID to mark removed/invalid entries
mGroups[index] = group;
}
virtual void updateBPFirstPass(PxU32 numCpuTasks, Cm::FlushPool& flushPool, bool hasContactDistanceUpdated, PxBaseTask* continuation) = 0;
virtual void updateBPSecondPass(PxcScratchAllocator* scratchAllocator, PxBaseTask* continuation) = 0;
virtual void postBroadPhase(PxBaseTask*, Cm::FlushPool& flushPool) = 0;
virtual void reallocateChangedAABBMgActorHandleMap(const PxU32 size) = 0;
AABBOverlap* getCreatedOverlaps(ElementType::Enum type, PxU32& count)
{
PX_ASSERT(type < ElementType::eCOUNT);
count = mCreatedOverlaps[type].size();
return mCreatedOverlaps[type].begin();
}
AABBOverlap* getDestroyedOverlaps(ElementType::Enum type, PxU32& count)
{
PX_ASSERT(type < ElementType::eCOUNT);
count = mDestroyedOverlaps[type].size();
return mDestroyedOverlaps[type].begin();
}
void freeBuffers();
struct OutOfBoundsData
{
PxU32 mNbOutOfBoundsObjects;
PxU32 mNbOutOfBoundsAggregates;
void** mOutOfBoundsObjects;
void** mOutOfBoundsAggregates;
};
virtual bool getOutOfBoundsObjects(OutOfBoundsData&) { return false; }
virtual void clearOutOfBoundsObjects() {}
void shiftOrigin(const PxVec3& shift);
virtual void visualize(PxRenderOutput& out) = 0;
virtual void releaseDeferredAggregateIds() = 0;
virtual void setGPUStateChanged() {}
virtual void setPersistentStateChanged() {}
#if PX_ENABLE_SIM_STATS
PxU32 getGpuDynamicsLostFoundPairsStats() { return mGpuDynamicsLostFoundPairsStats; }
PxU32 getGpuDynamicsTotalAggregatePairsStats() { return mGpuDynamicsTotalAggregatePairsStats; }
PxU32 getGpuDynamicsLostFoundAggregatePairsStats() { return mGpuDynamicsLostFoundAggregatePairsStats; }
#else
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
#endif
protected:
void reserveShapeSpace(PxU32 nbShapes);
// PT: we have bitmaps here probably to quickly handle added/removed objects during same frame.
// PT: TODO: consider replacing with plain arrays (easier to parse, already existing below, etc)
PxBitMapPinned mAddedHandleMap; // PT: indexed by BoundsIndex
PxBitMapPinned mRemovedHandleMap; // PT: indexed by BoundsIndex
PxBitMapPinned mChangedHandleMap;
//Returns true if the bounds was pending insert, false otherwise
PX_FORCE_INLINE bool removeBPEntry(BoundsIndex index) // PT: only for objects passed to the BP
{
if (mAddedHandleMap.test(index)) // PT: if object had been added this frame...
{
mAddedHandleMap.reset(index); // PT: ...then simply revert the previous operation locally (it hasn't been passed to the BP yet).
return true;
}
else
mRemovedHandleMap.set(index); // PT: else we need to remove it from the BP
return false;
}
PX_FORCE_INLINE void addBPEntry(BoundsIndex index)
{
if (mRemovedHandleMap.test(index))
mRemovedHandleMap.reset(index);
else
mAddedHandleMap.set(index);
}
//ML: we create mGroups and mContactDistance in the AABBManager constructor. PxArray will take PxVirtualAllocator as a parameter. Therefore, if GPU BP is using,
//we will passed a pinned host memory allocator, otherwise, we will just pass a normal allocator.
GroupsArrayPinned mGroups; // NOTE: we stick Bp::FilterGroup::eINVALID in this slot to indicate that the entry is invalid (removed or never inserted.)
PxInt32ArrayPinned mEnvIDs; // PT: should ideally be in the GPU class
PxFloatArrayPinned& mContactDistance;
VolumeDataArrayPinned mVolumeData;
BpFilter mFilters;
PX_FORCE_INLINE void initEntry(BoundsIndex index, PxReal contactDistance, Bp::FilterGroup::Enum group, void* userData)
{
if ((index + 1) >= mVolumeData.size())
reserveShapeSpace(index + 1);
// PT: TODO: why is this needed at all? Why aren't size() and capacity() enough?
mUsedSize = PxMax(index + 1, mUsedSize);
PX_ASSERT(group != Bp::FilterGroup::eINVALID); // PT: we use group == Bp::FilterGroup::eINVALID to mark removed/invalid entries
mGroups[index] = group;
mContactDistance.begin()[index] = contactDistance;
mVolumeData[index].setUserData(userData);
}
PX_FORCE_INLINE void initEntry(BoundsIndex index, PxReal contactDistance, Bp::FilterGroup::Enum group, void* userData, ElementType::Enum volumeType)
{
initEntry(index, contactDistance, group, userData);
mVolumeData[index].setVolumeType(volumeType); // PT: must be done after setUserData
}
PX_FORCE_INLINE void resetEntry(BoundsIndex index)
{
mGroups[index] = Bp::FilterGroup::eINVALID;
mContactDistance.begin()[index] = 0.0f;
mVolumeData[index].reset();
if(index<mEnvIDs.size())
mEnvIDs[index] = PX_INVALID_U32;
}
// PT: TODO: remove confusion between BoundsIndex and ShapeHandle here!
ShapeHandleArrayPinned mAddedHandles;
ShapeHandleArrayPinned mUpdatedHandles; // PT: TODO: only on CPU
ShapeHandleArrayPinned mRemovedHandles;
BroadPhase& mBroadPhase;
BoundsArray& mBoundsArray;
PxArray<AABBOverlap> mCreatedOverlaps[ElementType::eCOUNT];
PxArray<AABBOverlap> mDestroyedOverlaps[ElementType::eCOUNT];
PxU32 mUsedSize; // highest used value + 1
PxU32 mNbAggregates;
#if PX_ENABLE_SIM_STATS
PxU32 mGpuDynamicsLostFoundPairsStats;
PxU32 mGpuDynamicsTotalAggregatePairsStats;
PxU32 mGpuDynamicsLostFoundAggregatePairsStats;
#else
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
#endif
#if BP_USE_AGGREGATE_GROUP_TAIL
// PT: TODO: even in the 3.4 trunk this stuff is a clumsy mess: groups are "BpHandle" suddenly passed
// to BroadPhaseUpdateData as "ShapeHandle".
//Free aggregate group ids.
PxU32 mAggregateGroupTide;
PxArray<Bp::FilterGroup::Enum> mFreeAggregateGroups; // PT: TODO: remove this useless array
#endif
PxU64 mContextID;
bool mOriginShifted;
#if BP_USE_AGGREGATE_GROUP_TAIL
PX_FORCE_INLINE void releaseAggregateGroup(const Bp::FilterGroup::Enum group)
{
PX_ASSERT(group != Bp::FilterGroup::eINVALID);
mFreeAggregateGroups.pushBack(group);
}
PX_FORCE_INLINE Bp::FilterGroup::Enum getAggregateGroup()
{
PxU32 id;
if (mFreeAggregateGroups.size())
id = mFreeAggregateGroups.popBack();
else
{
id = mAggregateGroupTide--;
id <<= BP_FILTERING_TYPE_SHIFT_BIT;
id |= FilterType::AGGREGATE;
}
const Bp::FilterGroup::Enum group = Bp::FilterGroup::Enum(id);
PX_ASSERT(group != Bp::FilterGroup::eINVALID);
return group;
}
#endif
};
} //namespace Bp
} //namespace physx
#endif //BP_AABBMANAGER_BASE_H

View File

@@ -0,0 +1,95 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef BP_AABB_MANAGER_TASKS_H
#define BP_AABB_MANAGER_TASKS_H
#include "foundation/PxUserAllocated.h"
#include "CmTask.h"
namespace physx
{
namespace Bp
{
class AABBManager;
class Aggregate;
class AggregateBoundsComputationTask : public Cm::Task, public PxUserAllocated
{
PX_NOCOPY(AggregateBoundsComputationTask)
public:
AggregateBoundsComputationTask(PxU64 contextId) :
Cm::Task (contextId),
mManager (NULL),
mStart (0),
mNbToGo (0),
mAggregates (NULL)
{}
~AggregateBoundsComputationTask() {}
virtual const char* getName() const { return "AggregateBoundsComputationTask"; }
virtual void runInternal();
void Init(AABBManager* manager, PxU32 start, PxU32 nb, Aggregate** aggregates)
{
mManager = manager;
mStart = start;
mNbToGo = nb;
mAggregates = aggregates;
}
private:
AABBManager* mManager;
PxU32 mStart;
PxU32 mNbToGo;
Aggregate** mAggregates;
};
class PreBpUpdateTask : public Cm::Task, public PxUserAllocated
{
PX_NOCOPY(PreBpUpdateTask)
public:
PreBpUpdateTask(PxU64 contextId) : Cm::Task(contextId), mManager(NULL), mNumCpuTasks(0) {}
~PreBpUpdateTask() {}
virtual const char* getName() const { return "PreBpUpdateTask"; }
virtual void runInternal();
void Init(AABBManager* manager, PxU32 numCpuTasks)
{
mManager = manager;
mNumCpuTasks = numCpuTasks;
}
private:
AABBManager* mManager;
PxU32 mNumCpuTasks;
};
}
} //namespace physx
#endif // BP_AABB_MANAGER_TASKS_H

View File

@@ -0,0 +1,214 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef BP_BROADPHASE_H
#define BP_BROADPHASE_H
#include "foundation/PxUserAllocated.h"
#include "PxBroadPhase.h"
#include "BpBroadPhaseUpdate.h"
namespace physx
{
class PxcScratchAllocator;
class PxBaseTask;
namespace Bp
{
class BroadPhaseUpdateData;
/**
\brief Base broad phase class. Functions only relevant to MBP.
*/
class BroadPhaseBase : public PxBroadPhaseRegions, public PxUserAllocated
{
public:
BroadPhaseBase() {}
virtual ~BroadPhaseBase() {}
/**
\brief Gets broad-phase caps.
\param caps [out] Broad-phase caps
*/
virtual void getCaps(PxBroadPhaseCaps& caps) const
{
caps.mMaxNbRegions = 0;
}
// PxBroadPhaseRegions
virtual PxU32 getNbRegions() const PX_OVERRIDE { return 0; }
virtual PxU32 getRegions(PxBroadPhaseRegionInfo*, PxU32, PxU32) const PX_OVERRIDE { return 0; }
virtual PxU32 addRegion(const PxBroadPhaseRegion&, bool, const PxBounds3*, const PxReal*) PX_OVERRIDE { return 0xffffffff;}
virtual bool removeRegion(PxU32) PX_OVERRIDE { return false; }
virtual PxU32 getNbOutOfBoundsObjects() const PX_OVERRIDE { return 0; }
virtual const PxU32* getOutOfBoundsObjects() const PX_OVERRIDE { return NULL; }
//~PxBroadPhaseRegions
};
/*
\brief Structure used to report created and deleted broadphase pairs
\note The indices mVolA and mVolB correspond to the bounds indices
BroadPhaseUpdateData::mCreated used by BroadPhase::update
\see BroadPhase::getCreatedPairs, BroadPhase::getDeletedPairs
*/
struct BroadPhasePair
{
BroadPhasePair(ShapeHandle volA, ShapeHandle volB) :
mVolA (PxMin(volA, volB)),
mVolB (PxMax(volA, volB))
{
}
BroadPhasePair() :
mVolA (BP_INVALID_BP_HANDLE),
mVolB (BP_INVALID_BP_HANDLE)
{
}
ShapeHandle mVolA; // NB: mVolA < mVolB
ShapeHandle mVolB;
};
class BroadPhase : public BroadPhaseBase
{
public:
/**
\brief Instantiate a BroadPhase instance.
\param[in] bpType - the bp type (either mbp or sap). This is typically specified in PxSceneDesc.
\param[in] maxNbRegions is the expected maximum number of broad-phase regions.
\param[in] maxNbBroadPhaseOverlaps is the expected maximum number of broad-phase overlaps.
\param[in] maxNbStaticShapes is the expected maximum number of static shapes.
\param[in] maxNbDynamicShapes is the expected maximum number of dynamic shapes.
\param[in] contextID is the context ID parameter sent to the profiler
\return The instantiated BroadPhase.
\note maxNbRegions is only used if mbp is the chosen broadphase (PxBroadPhaseType::eMBP)
\note maxNbRegions, maxNbBroadPhaseOverlaps, maxNbStaticShapes and maxNbDynamicShapes are typically specified in PxSceneLimits
*/
static BroadPhase* create(
const PxBroadPhaseType::Enum bpType,
const PxU32 maxNbRegions,
const PxU32 maxNbBroadPhaseOverlaps,
const PxU32 maxNbStaticShapes,
const PxU32 maxNbDynamicShapes,
PxU64 contextID);
virtual PxBroadPhaseType::Enum getType() const = 0;
/**
\brief Shutdown of the broadphase.
*/
virtual void release() = 0;
/**
\brief Updates the broadphase and computes the lists of created/deleted pairs.
\param[in] scratchAllocator - a PxcScratchAllocator instance used for temporary memory allocations.
This must be non-null.
\param[in] updateData a description of changes to the collection of aabbs since the last broadphase update.
The changes detail the indices of the bounds that have been added/updated/removed as well as an array of all
bound coordinates and an array of group ids used to filter pairs with the same id.
\see BroadPhaseUpdateData
\param[in] continuation the task that is in the queue to be executed immediately after the broadphase has completed its update. NULL is not supported.
\note In PX_CHECKED and PX_DEBUG build configurations illegal input data (that does not conform to the BroadPhaseUpdateData specifications) triggers
a special code-path that entirely bypasses the broadphase and issues a warning message to the error stream. No guarantees can be made about the
correctness/consistency of broadphase behavior with illegal input data in PX_RELEASE and PX_PROFILE configs because validity checks are not active
in these builds.
*/
virtual void update(PxcScratchAllocator* scratchAllocator, const BroadPhaseUpdateData& updateData, physx::PxBaseTask* continuation) = 0;
/**
\brief prepare broad phase data.
*/
virtual void preBroadPhase(const Bp::BroadPhaseUpdateData& updateData) = 0;
/**
\brief Fetch the results of any asynchronous broad phase work.
*/
virtual void fetchBroadPhaseResults() = 0;
/*
\brief Get created pairs.
Note that each overlap pair is reported only on the frame when the overlap first occurs. The overlap persists
until the pair appears in the list of deleted pairs or either of the bounds in the pair is removed from the broadphase.
A created overlap must involve at least one of the bounds of the overlap pair appearing in either the created or updated list.
It is impossible for the same pair to appear simultaneously in the list of created and deleted overlap pairs.
An overlap is defined as a pair of bounds that overlap on all three axes; that is when maxA > minB and maxB > minA for all three axes.
\param nbCreatedPairs [out] The number of created aabb overlap pairs computed in the execution of update() that has just completed.
\return The array of created aabb overlap pairs computed in the execution of update() that has just completed.
*/
virtual const BroadPhasePair* getCreatedPairs(PxU32& nbCreatedPairs) const = 0;
/**
\brief Get deleted pairs.
Note that a deleted pair can only be reported if that pair has already appeared in the list of created pairs in an earlier update.
A lost overlap occurs when a pair of bounds previously overlapped on all three axes but have now separated on at least one axis.
A lost overlap must involve at least one of the bounds of the lost overlap pair appearing in the updated list.
Lost overlaps arising from removal of bounds from the broadphase do not appear in the list of deleted pairs.
It is impossible for the same pair to appear simultaneously in the list of created and deleted pairs.
\param nbDeletedPairs [out] The number of deleted overlap pairs computed in the execution of update() that has just completed.
\return The array of deleted overlap pairs computed in the execution of update() that has just completed.
*/
virtual const BroadPhasePair* getDeletedPairs(PxU32& nbDeletedPairs) const = 0;
/**
\brief After the broadphase has completed its update() function and the created/deleted pairs have been queried
with getCreatedPairs/getDeletedPairs it is desirable to free any memory that was temporarily acquired for the update but is
is no longer required post-update. This can be achieved with the function freeBuffers().
*/
virtual void freeBuffers() = 0;
/**
\brief Adjust internal structures after all bounds have been adjusted due to a scene origin shift.
*/
virtual void shiftOrigin(const PxVec3& shift, const PxBounds3* boundsArray, const PxReal* contactDistances) = 0;
#if PX_CHECKED
/**
\brief Test that the created/updated/removed lists obey the rules that
1. object ids can only feature in the created list if they have never been previously added or if they were previously removed.
2. object ids can only be added to the updated list if they have been previously added without being removed.
3. objects ids can only be added to the removed list if they have been previously added without being removed.
*/
virtual bool isValid(const BroadPhaseUpdateData& updateData) const = 0;
#endif
};
} //namespace Bp
} //namespace physx
#endif //BP_BROADPHASE_H

View File

@@ -0,0 +1,214 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef BP_BROADPHASE_UPDATE_H
#define BP_BROADPHASE_UPDATE_H
#include "BpFiltering.h"
#include "foundation/PxBounds3.h"
#include "foundation/PxUnionCast.h"
namespace physx
{
namespace Bp
{
typedef PxU32 ShapeHandle;
typedef PxU32 BpHandle;
#define BP_INVALID_BP_HANDLE 0x3fffffff
class BroadPhase;
class BroadPhaseUpdateData
{
public:
/**
\brief A structure detailing the changes to the collection of aabbs, whose overlaps are computed in the broadphase.
The structure consists of per-object arrays of object bounds and object groups, and three arrays that index
into the per-object arrays, denoting the bounds which are to be created, updated and removed in the broad phase.
* each entry in the object arrays represents the same shape or aggregate from frame to frame.
* each entry in an index array must be less than the capacity of the per-object arrays.
* no index value may appear in more than one index array, and may not occur more than once in that array.
An index value is said to be "in use" if it has appeared in a created list in a previous update, and has not
since occurred in a removed list.
\param[in] created an array of indices describing the bounds that must be inserted into the broadphase.
Each index in the array must not be in use.
\param[in] updated an array of indices (referencing the boxBounds and boxGroups arrays) describing the bounds
that have moved since the last broadphase update. Each index in the array must be in use, and each object
whose index is in use and whose AABB has changed must appear in the update list.
\param[in] removed an array of indices describing the bounds that must be removed from the broad phase. Each index in
the array must be in use.
\param[in] boxBounds an array of bounds coordinates for the AABBs to be processed by the broadphase.
An entry is valid if its values are integer bitwise representations of floating point numbers that satisfy max>min in each dimension,
along with a further rule that minima(maxima) must have even(odd) values.
Each entry whose index is either in use or appears in the created array must be valid. An entry whose index is either not in use or
appears in the removed array need not be valid.
\param[in] boxGroups an array of group ids, one for each bound, used for pair filtering. Bounds with the same group id will not be
reported as overlap pairs by the broad phase. Zero is reserved for static bounds.
Entries in this array are immutable: the only way to change the group of an object is to remove it from the broad phase and reinsert
it at a different index (recall that each index must appear at most once in the created/updated/removed lists).
\param[in] boxesCapacity the length of the boxBounds and boxGroups arrays.
\see BroadPhase::update
*/
BroadPhaseUpdateData(
const ShapeHandle* created, PxU32 createdSize,
const ShapeHandle* updated, PxU32 updatedSize,
const ShapeHandle* removed, PxU32 removedSize,
const PxBounds3* boxBounds, const Bp::FilterGroup::Enum* boxGroups, const PxReal* boxContactDistances, const PxU32* boxEnvIDs, PxU32 boxesCapacity,
const BpFilter& filter,
bool stateChanged,
bool gpuStateChanged
) :
mCreated (created),
mCreatedSize (createdSize),
mUpdated (updated),
mUpdatedSize (updatedSize),
mRemoved (removed),
mRemovedSize (removedSize),
mBoxBounds (boxBounds),
mBoxGroups (boxGroups),
mBoxDistances (boxContactDistances),
mBoxEnvIDs (boxEnvIDs),
mBoxesCapacity (boxesCapacity),
mFilter (filter),
mStateChanged (stateChanged),
mGpuStateChanged(gpuStateChanged)
{
}
BroadPhaseUpdateData(
const ShapeHandle* created, PxU32 createdSize,
const ShapeHandle* updated, PxU32 updatedSize,
const ShapeHandle* removed, PxU32 removedSize,
const PxBounds3* boxBounds, const Bp::FilterGroup::Enum* boxGroups, const PxReal* boxContactDistances, PxU32 boxesCapacity,
const BpFilter& filter,
bool stateChanged,
bool gpuStateChanged
) :
mCreated (created),
mCreatedSize (createdSize),
mUpdated (updated),
mUpdatedSize (updatedSize),
mRemoved (removed),
mRemovedSize (removedSize),
mBoxBounds (boxBounds),
mBoxGroups (boxGroups),
mBoxDistances (boxContactDistances),
mBoxEnvIDs (NULL),
mBoxesCapacity (boxesCapacity),
mFilter (filter),
mStateChanged (stateChanged),
mGpuStateChanged(gpuStateChanged)
{
}
BroadPhaseUpdateData(const BroadPhaseUpdateData& other) :
mCreated (other.mCreated),
mCreatedSize (other.mCreatedSize),
mUpdated (other.mUpdated),
mUpdatedSize (other.mUpdatedSize),
mRemoved (other.mRemoved),
mRemovedSize (other.mRemovedSize),
mBoxBounds (other.mBoxBounds),
mBoxGroups (other.mBoxGroups),
mBoxDistances (other.mBoxDistances),
mBoxEnvIDs (other.mBoxEnvIDs),
mBoxesCapacity (other.mBoxesCapacity),
mFilter (other.mFilter),
mStateChanged (other.mStateChanged),
mGpuStateChanged(other.mGpuStateChanged)
{
}
BroadPhaseUpdateData& operator=(const BroadPhaseUpdateData& other);
PX_FORCE_INLINE const ShapeHandle* getCreatedHandles() const { return mCreated; }
PX_FORCE_INLINE PxU32 getNumCreatedHandles() const { return mCreatedSize; }
PX_FORCE_INLINE const ShapeHandle* getUpdatedHandles() const { return mUpdated; }
PX_FORCE_INLINE PxU32 getNumUpdatedHandles() const { return mUpdatedSize; }
PX_FORCE_INLINE const ShapeHandle* getRemovedHandles() const { return mRemoved; }
PX_FORCE_INLINE PxU32 getNumRemovedHandles() const { return mRemovedSize; }
PX_FORCE_INLINE const PxBounds3* getAABBs() const { return mBoxBounds; }
PX_FORCE_INLINE const Bp::FilterGroup::Enum* getGroups() const { return mBoxGroups; }
PX_FORCE_INLINE const PxReal* getContactDistance() const { return mBoxDistances; }
PX_FORCE_INLINE const PxU32* getEnvIDs() const { return mBoxEnvIDs; }
PX_FORCE_INLINE PxU32 getCapacity() const { return mBoxesCapacity; }
PX_FORCE_INLINE const BpFilter& getFilter() const { return mFilter; }
PX_FORCE_INLINE bool getStateChanged() const { return mStateChanged; }
PX_FORCE_INLINE bool getGpuStateChanged() const { return mGpuStateChanged; }
#if PX_CHECKED
static bool isValid(const BroadPhaseUpdateData& updateData, const BroadPhase& bp, const bool skipBoundValidation, PxU64 contextID);
bool isValid(const bool skipBoundValidation) const;
#endif
private:
const ShapeHandle* mCreated;
const PxU32 mCreatedSize;
const ShapeHandle* mUpdated;
const PxU32 mUpdatedSize;
const ShapeHandle* mRemoved;
const PxU32 mRemovedSize;
const PxBounds3* mBoxBounds;
const Bp::FilterGroup::Enum* mBoxGroups;
const PxReal* mBoxDistances;
const PxU32* mBoxEnvIDs;
const PxU32 mBoxesCapacity;
const BpFilter& mFilter;
const bool mStateChanged;
const bool mGpuStateChanged;
};
} //namespace Bp
} //namespace physx
#endif

View File

@@ -0,0 +1,130 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef BP_FILTERING_H
#define BP_FILTERING_H
#include "PxvConfig.h"
#include "foundation/PxAssert.h"
namespace physx
{
namespace Bp
{
#define BP_USE_AGGREGATE_GROUP_TAIL 1
#define BP_FILTERING_TYPE_SHIFT_BIT 3
#define BP_FILTERING_TYPE_MASK 7
/*
\brief AABBManager volumes with the same filter group value are guaranteed never to generate an overlap pair.
\note To ensure that static pairs never overlap, add static shapes with eSTATICS.
The value eDYNAMICS_BASE provides a minimum recommended group value for dynamic shapes.
If dynamics shapes are assigned group values greater than or equal to eDYNAMICS_BASE then
they are allowed to generate broadphase overlaps with statics, and other dynamic shapes provided
they have different group values.
\see AABBManager::createVolume
*/
struct FilterGroup
{
enum Enum
{
eSTATICS = 0,
eDYNAMICS_BASE = 1,
#if BP_USE_AGGREGATE_GROUP_TAIL
eAGGREGATE_BASE = 0xfffffffe,
#endif
eINVALID = 0xffffffff
};
};
struct FilterType
{
enum Enum
{
STATIC = 0,
KINEMATIC = 1,
DYNAMIC = 2,
AGGREGATE = 3,
DEFORMABLE_SURFACE = 4,
DEFORMABLE_VOLUME = 5,
PARTICLESYSTEM = 6,
COUNT = 7
};
};
PX_FORCE_INLINE Bp::FilterGroup::Enum getFilterGroup_Statics()
{
return Bp::FilterGroup::eSTATICS;
}
PX_FORCE_INLINE Bp::FilterGroup::Enum getFilterGroup_Dynamics(PxU32 rigidId, bool isKinematic)
{
const PxU32 group = rigidId + Bp::FilterGroup::eDYNAMICS_BASE;
const PxU32 type = isKinematic ? FilterType::KINEMATIC : FilterType::DYNAMIC;
return Bp::FilterGroup::Enum((group<< BP_FILTERING_TYPE_SHIFT_BIT)|type);
}
PX_FORCE_INLINE Bp::FilterGroup::Enum getFilterGroup(bool isStatic, PxU32 rigidId, bool isKinematic)
{
return isStatic ? getFilterGroup_Statics() : getFilterGroup_Dynamics(rigidId, isKinematic);
}
PX_FORCE_INLINE bool groupFiltering(const Bp::FilterGroup::Enum group0, const Bp::FilterGroup::Enum group1, const bool* PX_RESTRICT lut)
{
/* const int g0 = group0 & ~3;
const int g1 = group1 & ~3;
if(g0==g1)
return false;*/
if(group0==group1)
{
PX_ASSERT((group0 & ~BP_FILTERING_TYPE_MASK)==(group1 & ~BP_FILTERING_TYPE_MASK));
return false;
}
const int type0 = group0 & BP_FILTERING_TYPE_MASK;
const int type1 = group1 & BP_FILTERING_TYPE_MASK;
return lut[type0*Bp::FilterType::COUNT+type1];
}
class BpFilter
{
public:
BpFilter(bool discardKineKine, bool discardStaticKine);
~BpFilter();
PX_FORCE_INLINE const bool* getLUT() const { return &mLUT[0][0]; }
bool mLUT[Bp::FilterType::COUNT][Bp::FilterType::COUNT];
};
}
}
#endif

View File

@@ -0,0 +1,123 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef BP_VOLUME_DATA_H
#define BP_VOLUME_DATA_H
#include "PxvConfig.h"
#include "foundation/PxAssert.h"
namespace physx
{
namespace Bp
{
typedef PxU32 AggregateHandle; // PT: currently an index in mAggregates array
struct ElementType
{
enum Enum
{
eSHAPE = 0,
eTRIGGER,
eCOUNT
};
};
PX_COMPILE_TIME_ASSERT(ElementType::eCOUNT <= 4); // 2 bits reserved for type
#define PX_CUDA_INLINE PX_CUDA_CALLABLE PX_FORCE_INLINE
struct VolumeData
{
PX_CUDA_INLINE void reset()
{
mAggregate = PX_INVALID_U32;
mUserData = NULL;
}
PX_CUDA_INLINE void setSingleActor() { mAggregate = PX_INVALID_U32; }
PX_CUDA_INLINE bool isSingleActor() const { return mAggregate == PX_INVALID_U32; }
PX_CUDA_INLINE void setUserData(void* userData)
{
// PX_ASSERT(!(size_t(userData) & 3));
mUserData = userData;
}
PX_CUDA_INLINE void* getUserData() const
{
return reinterpret_cast<void*>(size_t(mUserData)& (~size_t(3)));
}
PX_CUDA_INLINE void setVolumeType(ElementType::Enum volumeType)
{
PX_ASSERT(volumeType < 2);
mUserData = reinterpret_cast<void*>(size_t(getUserData()) | size_t(volumeType));
}
PX_CUDA_INLINE ElementType::Enum getVolumeType() const
{
return ElementType::Enum(size_t(mUserData) & 3);
}
PX_CUDA_INLINE void setAggregate(AggregateHandle handle)
{
PX_ASSERT(handle != PX_INVALID_U32);
mAggregate = (handle << 1) | 1;
}
PX_CUDA_INLINE bool isAggregate() const { return !isSingleActor() && ((mAggregate & 1) != 0); }
PX_CUDA_INLINE void setAggregated(AggregateHandle handle)
{
PX_ASSERT(handle != PX_INVALID_U32);
mAggregate = (handle << 1) | 0;
}
PX_CUDA_INLINE bool isAggregated() const
{
return !isSingleActor() && ((mAggregate & 1) == 0);
}
PX_CUDA_INLINE AggregateHandle getAggregateOwner() const { return mAggregate >> 1; }
PX_CUDA_INLINE AggregateHandle getAggregate() const { return mAggregate >> 1; }
private:
void* mUserData; // PT: in PhysX this is an Sc::ElementSim ptr
// PT: TODO: consider moving this to a separate array, which wouldn't be allocated at all for people not using aggregates.
// PT: current encoding:
// aggregate == PX_INVALID_U32 => single actor
// aggregate != PX_INVALID_U32 => aggregate index<<1|LSB. LSB==1 for aggregates, LSB==0 for aggregated actors.
AggregateHandle mAggregate;
};
}
}
#endif