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,48 @@
// 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 PXG_CONTACT_MANAGER_H
#define PXG_CONTACT_MANAGER_H
#include "foundation/PxSimpleTypes.h"
namespace physx
{
struct PX_ALIGN_PREFIX(16) PxgContactManagerInput
{
//Body refs are not needed here. World-space transforms are computed using transforCacheRefs instead!
PxU32 shapeRef0; //Ref to shape 0
PxU32 shapeRef1; //Ref to shape 1
PxU32 transformCacheRef0; //Ref to shape0's transforms in transform cache
PxU32 transformCacheRef1; //Ref to shape1's transform in transform cache
}
PX_ALIGN_SUFFIX(16);
}
#endif

View File

@@ -0,0 +1,69 @@
// 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 PXG_CONVEX_CONVEX_SHAPE_H
#define PXG_CONVEX_CONVEX_SHAPE_H
#include "geometry/PxMeshScale.h"
#define PXG_MAX_PCM_CONTACTS 4
namespace physx
{
template<PxU32 byteSize>
class FlexiblePad
{
PxU8 pad[byteSize];
};
template<>
class FlexiblePad<0>
{
};
//ML: PxgShape don't need to have contactOffset because we will dma a separated contact offset array later
struct PX_ALIGN_PREFIX(16) PxgShape
{
PxMeshScale scale; //28
PxU32 materialIndex; //32
size_t hullOrMeshPtr; //36 or 40
PxU32 type; //40 or 44
PxU32 particleOrSoftbodyId; //44 or 48
//FlexiblePad<16 - sizeof(size_t) - sizeof(PxU32)> pad; //48
#if !PX_P64_FAMILY
PxU32 pad0;
#endif
}
PX_ALIGN_SUFFIX(16);
PX_COMPILE_TIME_ASSERT(sizeof(PxgShape) == 48);
}
#endif

View File

@@ -0,0 +1,218 @@
// 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 PXG_GEOMETRY_MANAGER_H
#define PXG_GEOMETRY_MANAGER_H
#include "foundation/PxPreprocessor.h"
#include "foundation/PxArray.h"
#include "foundation/PxHashMap.h"
#include "foundation/PxSimpleTypes.h"
#include "PxgCopyManager.h"
#if PX_LINUX && PX_CLANG
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation"
#pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
#endif
#include "cuda.h"
#if PX_LINUX && PX_CLANG
#pragma clang diagnostic pop
#endif
// AD: PxgGeometryManager manages the CPU/GPU data transfers and the lifetime of collision geometries: Convex Hulls, Trimeshes, SDFs, Heightfields.
/*
Short overview:
- geometries are added using the add* functions.
- during add, device memory is allocated and indices are given to geometries. We need to allocate the device memory here despite not writing to it
because the pointer is uploaded to GPU together with the shapeInstance data, which happens before we perform the final copy of the geometry in scheduleCopyHtoD.
- We also accumulate the pinned memory requirements for the staging buffer during add.
- scheduleCopyHtoD is performing the bulk of the work:
- we allocate the proper amount of pinned memory
- for each scheduled geometry, we lay it out in the pinned memory
- we push the copy descriptor to the copy manager.
- the pinned memory is deallocated and the queues reset in resetAfterMemCopyCompleted().
Future things:
- look into the sequences of device uploads: we might be able to defer device memory allocations and use pools if we can rearrange things such that
we don't need the device pointer upfront.
- The pinned memory is contiguous, so the copy manager taking pairs of (src, dest) could potentially be replaced by a linear thing.
*/
namespace physx
{
class PxgHeapMemoryAllocatorManager;
class PxgHeapMemoryAllocator;
class PxCudaContext;
namespace Gu
{
struct ConvexHullData;
class TriangleMesh;
struct HeightFieldData;
};
template<typename ArrayT>
class PxgFreeIndicesProvider
{
PX_NOCOPY(PxgFreeIndicesProvider)
public:
PxgFreeIndicesProvider(ArrayT& ref): mDataArray(ref) {}
PxU32 getFreeIndex()
{
if (!mFreeIndices.empty())
{
return mFreeIndices.popBack();
}
else
{
PxU32 currSz = mDataArray.size();
if (currSz + 1 > mDataArray.capacity())
{
mDataArray.reserve(currSz * 2);
}
mDataArray.resize(currSz + 1);
return currSz;
}
}
void setFreeIndex(PxU32 idx)
{
PX_ASSERT(idx < mDataArray.size());
mDeferredFreeIndices.pushBack(idx);
}
void releaseFreeIndices()
{
for (PxU32 a = 0; a < mDeferredFreeIndices.size(); ++a)
{
mFreeIndices.pushBack(mDeferredFreeIndices[a]);
}
mDeferredFreeIndices.forceSize_Unsafe(0);
}
private:
PxArray<PxU32> mDeferredFreeIndices;
PxArray<PxU32> mFreeIndices;
ArrayT& mDataArray;
};
struct PxgMeshTextureData
{
CUarray cuArray;
CUtexObject cuTexRef;
CUarray cuArraySubgrids;
CUtexObject cuTexRefSubgrids;
};
struct HullOrMeshData
{
void* mDeviceMemPointer;
PxU32 mCopyDescIndex;
static const PxU32 INVALID_COPY_DESC_INDEX = 0xFFffFFff;
};
class PxgGeometryManager;
// Holds all the data needed to upload a geometry to the GPU. Created when calling add* functions, read during scheduleCopyHtoD.
struct ScheduledCopyData
{
private:
// AD this is local, not intended for widespread usage.
struct UploadGeometryType
{
enum Enum
{
eTRIANGLEMESH = 1,
eCONVEXHULL = 2,
eHEIGHTFIELD = 3,
eBOXHULL = 4
};
};
public:
PxgCopyManager::CopyDesc mCopyDesc; //!< Copy descriptor for upload to GPU. lives until copy completed.
PxU32 mHullOrTrimeshIdx; //!< Index into mGeometrydata
UploadGeometryType::Enum mType; //!< Geometry type: see UploadGeometryType. Needed for deferred pinned memory allocation.
PxU32 mNumPolyVertices; //!< Number of polygon vertices in case this is a convex hull
const void* mGeometryPtr; //!< Pointer to CPU geometry data.
friend class PxgGeometryManager;
};
class PxgGeometryManager
{
PX_NOCOPY(PxgGeometryManager)
using UploadGeometryType = ScheduledCopyData::UploadGeometryType;
public:
PxgGeometryManager(PxgHeapMemoryAllocatorManager* heapMemoryManager);
virtual ~PxgGeometryManager();
PxU32 addHull(const Gu::ConvexHullData& hull);
PxU32 addTriMesh(const Gu::TriangleMesh& triMesh);
PxU32 addHeightfield(const Gu::HeightFieldData& hf);
void addBoxHull();
void removeGeometry(PxU32 idx);
void scheduleCopyHtoD(PxgCopyManager& copyMan, PxCudaContext& cudaContext, CUstream stream);
CUdeviceptr getGeometryDevPtrByIndex(PxU32 idx) const;
CUdeviceptr getBoxHullDevPtr() const;
void resetAfterMemcpyCompleted();
private:
PxU32 addGeometryInternal(PxU64 byteSize, const void* geomPtr, UploadGeometryType::Enum type, PxU32 numPolyVertices = 0);
PxgHeapMemoryAllocator* mDeviceMemoryAllocator; //device memory
PxgHeapMemoryAllocator* mPinnedMemoryAllocator; //mapped memory
void* mPinnedMemoryBasePtr; //stores the pointer to the current pinned memory allocation.
PxU64 mPinnedHostMemoryRequirements; // accumulates pinned memory requirements for copies.
PxArray<ScheduledCopyData> mScheduledCopies; // copies in current step, cleared after scheduleCopyHtoD
PxArray<HullOrMeshData> mGeometryData; //persistent geometry data, holds idx -> device pointer mapping
PxgFreeIndicesProvider<PxArray<HullOrMeshData> > mFreeGeometryIndices; //freeIndex provider for mGeometry.
PxU32 mBoxHullIdx; //index into mGeometryData for hardcoded convex hull for box.
PxHashMap<void*, PxgMeshTextureData> mMeshToTextureMap; //maps meshes to SDF textures for lifetime management
};
};
#endif

View File

@@ -0,0 +1,39 @@
// 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 PXG_NARROWPHASE_H
#define PXG_NARROWPHASE_H
namespace physx
{
//this is needed to force PhysXNarrowphaseGpu linkage as Static Library!
void createPxgNarrowphase();
}
#endif

View File

@@ -0,0 +1,817 @@
// 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 PXG_NARROWPHASE_CORE_H
#define PXG_NARROWPHASE_CORE_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxTransform.h"
#include "foundation/PxPinnedArray.h"
#include "foundation/PxUserAllocated.h"
#include "task/PxTask.h"
#include "geometry/PxMeshScale.h"
#include "foundation/PxMutex.h"
#include "PxsContactManagerState.h"
#include "PxgContactManager.h"
#include "PxgPersistentContactManifold.h"
#include "PxgCudaBuffer.h"
#include "cudaNpCommon.h"
#include "PxgCudaPagedLinearAllocator.h"
#include "PxgCopyManager.h"
#include "PxgConvexConvexShape.h"
#include "PxgGeometryManager.h"
#include "PxvNphaseImplementationContext.h"
#include "PxgHeapMemAllocator.h"
#include "PxgShapeManager.h"
#include "PxgRadixSortDesc.h"
#include "geometry/PxParticleSystemGeometry.h"
#include "PxvGeometry.h"
namespace physx
{
class PxsTransformCache;
struct PxsMaterialData;
struct PxsCachedTransform;
struct PxcDataStreamPool;
class PxgCudaKernelWranglerManager;
class PxgNphaseImplementationContext;
class PxRenderOutput;
class PxgGpuContext;
struct PxTriangleMeshGeometryLL;
class PxgParticleSystemCore;
struct PxgFemFemContactInfo;
struct PxgFemOtherContactInfo;
namespace Gu
{
struct ConvexHullData;
class TriangleMesh;
class DeformableVolumeMesh;
class BVTetrahedronMesh;
struct HeightFieldData;
class PersistentContactManifold;
}
namespace Cm
{
class FlushPool;
}
namespace IG
{
class IslandSim;
}
struct GPU_BUCKET_ID
{
enum Enum
{
eFallback = 0,
eConvex = 1, //manifold
eConvexPlane = 2, //manifold
eConvexTrimesh = 3, //multi-manifold
eConvexHeightfield = 4, //multi-manifold
eSphereTrimesh = 5, //multi-manifold
eSphereHeightfield = 6, //multi-manifold
eTrianglePlane = 7, //multi-manifold - technically could be single manifold but needs 6 points
eSphere = 8, //no manifold
eBoxBox = 9,
eConvexCorePlane = 10,
eConvexCoreConvex = 11,
eConvexCoreTrimesh = 12,
eConvexCoreTetmesh = 13,
eConvexCoreClothmesh = 14,
eTriangleHeightfield = 15, //no mainfold
eTriangleTriangle = 16, //no manifold
eSoftbody = 17, //no manifold
eSoftbodies = 18, //no manifold
eSoftbodyFemCloth = 19, //no manifold
eSoftbodyTrimesh = 20, //no manifold
eSoftbodySdfTrimesh = 21, //no manifold
eSoftbodyHeightfield = 22, //no manifold
eFemClothSphere = 23, //no manifold
eFemClothPlane = 24, //no manifold
eFemClothBox = 25, //no manifold
eFemClothConvexes = 26, //no manifold
eFemClothes = 27, //no manifold
eFemClothTrimesh = 28, //no manifold
eFemClothSdfTrimesh = 29,
eFemClothHeightfield = 30, //no manifold
eConvexParticle = 31, //no manifold
eParticlesystems = 32, //no manifold
eParticlesystemSoftbody = 33, //no manifold
eParticlesystemFemCloth = 34, //no manifold
eParticlesystemTrimesh = 35, //no manifold
eParticlesystemSdfTrimesh = 36, //no manifold
eParticlesystemHeightfield = 37, //no manifold
eCount
};
};
const PxU32 BUCKET_ManifoldSize[GPU_BUCKET_ID::eCount] = {
0, //0
sizeof(PxgPersistentContactManifold), //1
sizeof(PxgPersistentContactManifold), //2
sizeof(PxgPersistentContactMultiManifold), //3
sizeof(PxgPersistentContactMultiManifold), //4
sizeof(PxgPersistentContactMultiManifold), //5
sizeof(PxgPersistentContactMultiManifold), //6
sizeof(PxgPersistentContactMultiManifold), //7
0, //8
0, //9
0, //10
0, //11
0, //12
0, //13
0, //14
0, //15
0, //16
0, //17
0, //18
0, //19
0, //20
0, //21
0, //22
0, //23
0, //24
0, //25
0, //26
0, //27
0, //28
0, //29
0, //30
0, //31
0, //32
0, //33
0, //34
0, //35
0, //36
0, //37
};
struct PxgContactManagers : public PxsContactManagerBase
{
PxgContactManagers(const PxU32 bucketId, const PxVirtualAllocator& allocator) : PxsContactManagerBase(bucketId),
mGpuInputContactManagers(allocator),
mCpuContactManagerMapping(allocator),
mShapeInteractions(allocator),
mRestDistances(allocator),
mTorsionalProperties(allocator)
{
}
PxPinnedArray<PxgContactManagerInput> mGpuInputContactManagers;
PxPinnedArray<PxsContactManager*> mCpuContactManagerMapping;
PxPinnedArray<const Sc::ShapeInteraction*> mShapeInteractions;
PxFloatArrayPinned mRestDistances;
PxPinnedArray<PxsTorsionalFrictionData> mTorsionalProperties;
void clear()
{
mGpuInputContactManagers.forceSize_Unsafe(0);
mCpuContactManagerMapping.forceSize_Unsafe(0);
mShapeInteractions.forceSize_Unsafe(0);
mRestDistances.forceSize_Unsafe(0);
mTorsionalProperties.forceSize_Unsafe(0);
}
void preallocateNewBuffers(PxU32 nbToPreallocate)
{
mGpuInputContactManagers.reserve(nbToPreallocate);
mCpuContactManagerMapping.reserve(nbToPreallocate);
mShapeInteractions.reserve(nbToPreallocate);
mRestDistances.reserve(nbToPreallocate);
mTorsionalProperties.reserve(nbToPreallocate);
}
private:
PX_NOCOPY(PxgContactManagers)
};
struct PxgNewContactManagers : public PxgContactManagers
{
PxPinnedArray<PxsContactManagerOutput> mGpuOutputContactManagers;
PxgNewContactManagers(const PxU32 bucketIndex, const PxVirtualAllocator& allocator) : PxgContactManagers(bucketIndex, allocator),
mGpuOutputContactManagers(allocator)
{
}
void clear()
{
PxgContactManagers::clear();
mGpuOutputContactManagers.forceSize_Unsafe(0);
}
void preallocateNewBuffers(PxU32 nbToPreallocate)
{
mGpuOutputContactManagers.reserve(nbToPreallocate);
PxgContactManagers::preallocateNewBuffers(nbToPreallocate);
}
};
struct PxgGpuContactManagers
{
PxgTypedCudaBuffer<PxgContactManagerInput> mContactManagerInputData;
PxgTypedCudaBuffer<PxsContactManagerOutput> mContactManagerOutputData;
PxgCudaBuffer mPersistentContactManifolds;
PxgTypedCudaBuffer<PxU32> mTempRunsumArray;
PxgTypedCudaBuffer<PxU32> mTempRunsumArray2;
PxgTypedCudaBuffer<PxU32> mBlockAccumulationArray;
PxgTypedCudaBuffer<PxsContactManagerOutputCounts> mLostFoundPairsOutputData;
PxgTypedCudaBuffer<PxsContactManager*> mLostFoundPairsCms;
PxgTypedCudaBuffer<PxsContactManager*> mCpuContactManagerMapping;
PxgTypedCudaBuffer<Sc::ShapeInteraction*> mShapeInteractions;
PxgTypedCudaBuffer<PxReal> mRestDistances;
PxgTypedCudaBuffer<PxsTorsionalFrictionData> mTorsionalProperties;
uint2* mLostAndTotalReportedPairsCountPinned;
const PxU32 mBucketIndex;
PxgGpuContactManagers(const PxU32 bucketIndex, PxgHeapMemoryAllocatorManager* manager) :
mContactManagerInputData(manager, PxsHeapStats::eNARROWPHASE),
mContactManagerOutputData(manager, PxsHeapStats::eNARROWPHASE),
mPersistentContactManifolds(manager, PxsHeapStats::eNARROWPHASE),
mTempRunsumArray(manager, PxsHeapStats::eNARROWPHASE),
mTempRunsumArray2(manager, PxsHeapStats::eNARROWPHASE),
mBlockAccumulationArray(manager, PxsHeapStats::eNARROWPHASE),
mLostFoundPairsOutputData(manager, PxsHeapStats::eNARROWPHASE),
mLostFoundPairsCms(manager, PxsHeapStats::eNARROWPHASE),
mCpuContactManagerMapping(manager, PxsHeapStats::eNARROWPHASE),
mShapeInteractions(manager, PxsHeapStats::eNARROWPHASE),
mRestDistances(manager, PxsHeapStats::eNARROWPHASE),
mTorsionalProperties(manager, PxsHeapStats::eNARROWPHASE),
mLostAndTotalReportedPairsCountPinned(NULL),
mBucketIndex(bucketIndex)
{
PX_ASSERT(bucketIndex < (1 << PxsContactManagerBase::MaxBucketBits));
}
private:
PX_NOCOPY(PxgGpuContactManagers)
};
struct PxgGpuPairManagementBuffers
{
PxgCudaBuffer mTempRunsumArray;
PxgCudaBuffer mBlockAccumulationArray;
PxgCudaBuffer mRemovedIndicesArray;
PxgGpuPairManagementBuffers(PxgHeapMemoryAllocatorManager* manager):
mTempRunsumArray(manager, PxsHeapStats::eNARROWPHASE), mBlockAccumulationArray(manager, PxsHeapStats::eNARROWPHASE), mRemovedIndicesArray(manager, PxsHeapStats::eNARROWPHASE)
{
}
private:
PX_NOCOPY(PxgGpuPairManagementBuffers)
};
class PxgMirroredContactManagerPair : public PxUserAllocated
{
public:
PxgMirroredContactManagerPair(const PxU32 bucketId, const PxVirtualAllocator& allocator) :
mContactManagers(bucketId, allocator),
mNewContactManagers(bucketId, allocator)
{
}
PX_FORCE_INLINE PxU32 getNbFirstPassTests() { return mContactManagers.mCpuContactManagerMapping.size(); }
PX_FORCE_INLINE PxU32 getNbSecondPassTests() { return mNewContactManagers.mCpuContactManagerMapping.size(); }
PX_FORCE_INLINE PxU32 getNbPassTests() { return mContactManagers.mCpuContactManagerMapping.size() + mNewContactManagers.mCpuContactManagerMapping.size(); }
PX_FORCE_INLINE void allocateContactManagers()
{
const PxU32 newPairCount = mContactManagers.mGpuInputContactManagers.size() + mNewContactManagers.mGpuInputContactManagers.size();
if (newPairCount > mContactManagers.mGpuInputContactManagers.capacity())
{
PxU32 newSize = PxMax(newPairCount, mContactManagers.mGpuInputContactManagers.capacity() * 2);
mContactManagers.mGpuInputContactManagers.reserve(newSize);
//mContactManagers.mCpuContactManagerMapping.reserve(newSize);
}
}
PxgContactManagers mContactManagers; //existing contact managers
PxgNewContactManagers mNewContactManagers; //new contact managers
};
class PxgGpuContactManagerPair : public PxUserAllocated
{
public:
PxgGpuContactManagerPair(const PxU32 bucketId, PxgHeapMemoryAllocatorManager* manager) :
mContactManagers(bucketId, manager),
mNewContactManagers(bucketId, manager)
{
}
PX_FORCE_INLINE void allocateBlockAccumulationArray(const PxU32 size)
{
mContactManagers.mBlockAccumulationArray.allocate(sizeof(PxU32) * size, PX_FL);
mNewContactManagers.mBlockAccumulationArray.allocate(sizeof(PxU32) * size, PX_FL);
}
PX_FORCE_INLINE void allocateLostAndTotalReportedPairsCount(PxsHeapMemoryAllocator* mappedMemoryAllocators)
{
mContactManagers.mLostAndTotalReportedPairsCountPinned = reinterpret_cast<uint2*>(mappedMemoryAllocators->allocate(sizeof(uint2), PxsHeapStats::eNARROWPHASE, PX_FL));
mNewContactManagers.mLostAndTotalReportedPairsCountPinned = reinterpret_cast<uint2*>(mappedMemoryAllocators->allocate(sizeof(uint2), PxsHeapStats::eNARROWPHASE, PX_FL));
}
PX_FORCE_INLINE PxU32 getTotalLostFoundPairs()
{
return mContactManagers.mLostAndTotalReportedPairsCountPinned->y + mNewContactManagers.mLostAndTotalReportedPairsCountPinned->y;
}
PX_FORCE_INLINE PxU32 getTotalLostFoundPatches()
{
return mContactManagers.mLostAndTotalReportedPairsCountPinned->x + mNewContactManagers.mLostAndTotalReportedPairsCountPinned->x;
}
PxgGpuContactManagers mContactManagers;
PxgGpuContactManagers mNewContactManagers;
};
struct PxsShapeCore;
struct PxgKernelIds;
class PxgGpuNarrowphaseCore : public PxUserAllocated
{
PX_NOCOPY(PxgGpuNarrowphaseCore)
public:
PxgMirroredContactManagerPair* mContactManagers[GPU_BUCKET_ID::eCount]; //some order as BUCKET_ID. 0 is fallback and it will be NULL in this array
PxgGpuContactManagerPair* mGpuContactManagers[GPU_BUCKET_ID::eCount]; //some order as BUCKET_ID. 0 is fallback and it will be NULL in this array
PxgGpuPairManagementBuffers mPairManagementBuffers;
PxgCudaBuffer mGpuTransformCache;
PxgCudaBuffer mGpuContactDistance;
typedef PxInt32ArrayPinned RemovedIndicesArray;
RemovedIndicesArray* mRemovedIndices[GPU_BUCKET_ID::eCount];
PxBitMap mKeepMap;
PxPinnedArray<PxsContactManagerOutputCounts> mLostFoundPairsOutputData;
PxPinnedArray<PxsContactManager*> mLostFoundPairsCms;
PxU32 mTotalLostFoundPairs;
PxU32 mTotalLostFoundPatches;
PxU32 mTotalNumPairs;
PxgPairManagementData* mPairManagementData[GPU_BUCKET_ID::eCount]; //mapped memory
PxgCudaBuffer mGpuPairManagementData;
PxPinnedArray<PxgRadixSortDesc> mRSDesc;
PxgCudaBufferN<2> mRadixSortDescBuf; //radix sort with rank
PxgCudaBuffer mTempGpuRigidIndiceBuf;
PxgCudaBuffer mTempGpuShapeIndiceBuf;
PxgCudaBuffer mRadixCountTotalBuf;
CUdeviceptr mContactStream;
CUdeviceptr mPatchStream;
CUdeviceptr mForceAndIndiceStream;
PxgTypedCudaBuffer<PxgPatchAndContactCounters> mPatchAndContactCountersOnDevice; //device memory
PxgPatchAndContactCounters* mPatchAndContactCountersReadback; //host memory
PxgShapeManager mGpuShapesManager;
PxgMaterialManager mGpuMaterialManager;
PxgFEMSoftBodyMaterialManager mGpuFEMMaterialManager;
PxgFEMClothMaterialManager mGpuFEMClothMaterialManager;
PxgPBDMaterialManager mGpuPBDMaterialManager;
//device memory
PxgCudaPagedLinearAllocator<PxgHeapMemoryAllocator> mIntermStackAlloc;
CUstream mStream;
CUstream mSolverStream; //this is the stream handle belong to the solver, we can't destroy the solver stream
PxgCudaKernelWranglerManager* mGpuKernelWranglerManager;
PxCudaContextManager* mCudaContextManager;
PxCudaContext* mCudaContext;
PxgHeapMemoryAllocatorManager* mHeapMemoryManager;
PxgCopyManager mCopyMan;
PxgCopyManager mCopyManBp;
PxgGeometryManager mGeometryManager;
IG::IslandSim* mIslandSim;
PxgNphaseImplementationContext* mNphaseImplContext;
PxgGpuContext* mGpuContext;
PxU32 mCollisionStackSizeBytes;
PxU32* mMaxConvexMeshTempMemory;
struct RefcountedRecord
{
PxU32 refCnt;
PxU32 idx;
};
typedef PxHashMap<size_t, RefcountedRecord> RefcountedRecordsMap;
RefcountedRecordsMap* mShapesMap;
RefcountedRecordsMap* mGeometriesMap;
RefcountedRecordsMap* mMaterialsMap;
RefcountedRecordsMap* mFEMMaterialsMap;
RefcountedRecordsMap* mFEMClothMaterialsMap;
RefcountedRecordsMap* mPBDMaterialsMap;
PxgCudaBuffer mGpuMultiManifold;
PxgCudaBuffer mGpuManifold;
CUevent mParticleEvent;
CUevent mSoftbodyEvent;
CUevent mFemClothEvent;
CUevent mDirectApiDmaEvent;
#if PX_ENABLE_SIM_STATS
PxU32 mGpuDynamicsRigidContactCountStats;
PxU32 mGpuDynamicsRigidPatchCountStats;
PxU32 mGpuDynamicsCollisionStackSizeStats;
#else
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
#endif
void createGpuStreamsAndEvents();
void releaseGpuStreamsAndEvents();
void removeLostPairsGpu(const PxU32 bucketID, const PxU16 stage5KernelID, const bool copyManifold);
void appendContactManagersGpu(PxU32 nbExistingManagers, PxU32 nbNewManagers, PxgGpuContactManagers& gpuContactManagers, PxgGpuContactManagers& newGpuContactManagers, PxU32 manifoldSize);
void drawManifold(PxgPersistentContactManifold* manifolds, PxgContactManagerInput* cmInput, PxsCachedTransform* cachedTransform, const PxU32 numTests, PxRenderOutput& renderOutput,
const PxU32 color, const PxF32 size);
void drawPoint(PxRenderOutput& renderOutput, PxVec3 point, const PxU32 color, const PxF32 size);
void drawLine(PxRenderOutput& out, PxVec3 a, const PxVec3 b, const PxU32 color);
template <typename ManagementData, typename Manifold>
void removeLostPairsGpuInternal( ManagementData& cpuBuffer, CUdeviceptr gpuBuffer,
PxgContactManagers& contactManagers, PxgGpuContactManagers& gpuContactManagers, PxInt32ArrayPinned& removedIndices, PxgGpuPairManagementBuffers& pairManagementBuffers,
PxU16 stage5KernelID, const bool copyManifold = true);
public:
PxgGpuNarrowphaseCore(PxgCudaKernelWranglerManager* gpuKernelWrangler, PxCudaContextManager* cudaContextManager, const PxGpuDynamicsMemoryConfig& gpuDynamicsConfig, void* contactStreamBase,
void* patchStreamBase, void* forceAndIndiceStreamBase, IG::IslandSim* islandSim, CUstream solverStream, PxgHeapMemoryAllocatorManager* heapMemoryManager,
PxgNphaseImplementationContext* nphaseImplContext);
virtual ~PxgGpuNarrowphaseCore();
void testSDKSphereGpu(PxgGpuContactManagers& gpuManagers, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces, PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit,
PxRenderOutput* renderOutput);
void testSDKBoxBoxGpu(PxgGpuContactManagers& gpuManagers, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces, PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit,
PxRenderOutput* renderOutput);
void testSDKConvexConvexGjkEpaGpu(PxgGpuContactManagers& gpuManagers, bool insertAveragePoint, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces, PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit,
PxRenderOutput* renderOutput);
void testSDKConvexPlaneGjkEpaGpu(PxgGpuContactManagers& gpuManagers, bool insertAveragePoint, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces, PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit,
PxRenderOutput* renderOutput);
void testSDKConvexCorePlaneGjkEpaGpu(PxgGpuContactManagers& gpuManagers, bool insertAveragePoint, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces, PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit,
PxRenderOutput* renderOutput);
void testSDKConvexCoreConvexGjkEpaGpu(PxgGpuContactManagers& gpuManagers, bool insertAveragePoint, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces, PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit,
PxRenderOutput* renderOutput);
void testSDKConvexCoreTrimeshGjkEpaGpu(PxgGpuContactManagers& gpuManagers, bool insertAveragePoint, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces, PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit,
PxRenderOutput* renderOutput);
void testSDKConvexCoreTetmeshGjkEpaGpu(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKConvexCoreClothmeshGjkEpaGpu(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKSphereTriMeshSATGpu(PxgGpuContactManagers& gpuManagers, bool insertAveragePoint, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces,
PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit);
void testSDKSphereHeightfieldGpu(PxgGpuContactManagers& gpuManagers, bool insertAveragePoint, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces,
PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit);
void testSDKTriMeshPlaneGpu(PxgGpuContactManagers& gpuManagers, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces,
PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit);
void testSDKTriMeshHeightfieldGpu(PxgGpuContactManagers& gpuManagers, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces,
PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit);
void testSDKTriMeshTriMeshGpu(PxgGpuContactManagers& gpuManagers,const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces,
PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit);
void testSDKConvexTriMeshSATGpu(PxgGpuContactManagers& gpuManagers, bool insertAveragePoint, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces,
PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit);
void testSDKConvexHeightfieldGpu(PxgGpuContactManagers& gpuManagers, bool insertAveragePoint, const PxU32 numTests,
PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces,
PxU32 patchBytesLimit, PxU32 contactBytesLimit, PxU32 forceBytesLimit);
void testSDKParticleSystemGpu(PxgGpuContactManagers& gpuManagers, const PxU32 numTests);
void testSDKParticleSoftbody(PxgGpuContactManagers& gpuManagers, const PxU32 numTests,
PxRenderOutput* renderOutput);
void testSDKParticleFemCloth(PxgGpuContactManagers& gpuManagers, const PxU32 numTests,
PxRenderOutput* renderOutput);
void testSDKConvexParticle(PxgGpuContactManagers& gpuManagers, const PxU32 numTests);
void testSDKParticleSdfTriMesh(PxgGpuContactManagers& gpuManagers, const PxU32 numTests);
void testSDKParticleTriMesh(PxgGpuContactManagers& gpuManagers,const PxU32 numTests);
void testSDKParticleHeightfield(PxgGpuContactManagers& gpuManagers, const PxU32 numTests);
void testSDKSoftbody(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKSoftbodies(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKSoftbodyCloth(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKSoftbodyTrimesh(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKSoftbodySdfTrimesh(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKSoftbodyHeightfield(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKFemClothSphere(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKFemClothPlane(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKFemClothBox(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKFemClothConvexes(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKFemClothCloth(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKFemClothSdfTrimesh(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKFemClothTrimesh(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void testSDKFemClothHeightfield(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxRenderOutput* renderOutput);
void updateFrictionPatches(PxgGpuContactManagers& gpuManagers, PxU32 count, PxU8* baseContactPatches, PxU8* baseFrictionPatches);
void fetchNarrowPhaseResults(PxcDataStreamPool* contactStreamPool, PxcDataStreamPool* patchStreamPool, PxcDataStreamPool* forceStreamPool,
PxsContactManagerOutput* cmOutputs, const Sc::ShapeInteraction*const* shapeInteractions, const PxReal* restDistances, const PxsTorsionalFrictionData* torsionalData, PxU32 nbFallbackPairs,
const PxsContactManagerOutputCounts* foundPatchCounts, const PxsContactManager*const* foundPatchManagers, PxU32 nbFoundPatchManagers);
void syncNotRigidWithNp();
void acquireContext();
void releaseContext();
CUstream getStream();
void registerContactManager(PxsContactManager* cm, const Sc::ShapeInteraction* shapeInteraction, PxsContactManagerOutput& output, const PxU32 bucketId);
void unregisterContactManager(PxsContactManager* manager, const PxU32 bucketId);
void refreshContactManager(PxsContactManager* manager, PxsContactManagerOutput* cmOutputs, PxgContactManagerInput& input, const PxU32 bucketId);
void removeLostPairs();
void appendContactManagers(PxsContactManagerOutput* cmOutputs, PxU32 nbFallbackPairs);
void prepareTempContactManagers();
template <GPU_BUCKET_ID::Enum>
void prepareTempContactManagers();
void prepareTempContactManagersTasks(Cm::FlushPool& flushPool, PxBaseTask* continuation);
bool isMeshGPUCompatible(const PxTriangleMeshGeometryLL& meshData);
bool isClothMeshGPUCompatible(const PxTriangleMeshGeometryLL& meshData); // skipping material counts
bool isTetMeshGPUCompatible(const Gu::BVTetrahedronMesh* meshData);
void computeRigidsToShapes();
void prepareGpuNarrowphase(PxsTransformCache& cache, const PxReal* contactDistances, bool hasContactDistanceChanged);
PxsContactManagerOutput* getGPUContactManagerOutputBase() { return reinterpret_cast<PxsContactManagerOutput*>(mGpuContactManagers[GPU_BUCKET_ID::eConvex]->mContactManagers.mContactManagerOutputData.getDevicePtr()); }
PxReal* getGPURestDistances() { return reinterpret_cast<PxReal*>(mGpuContactManagers[GPU_BUCKET_ID::eConvex]->mContactManagers.mRestDistances.getDevicePtr()); }
PxsTorsionalFrictionData* getGPUTorsionalData() { return reinterpret_cast<PxsTorsionalFrictionData*>(mGpuContactManagers[GPU_BUCKET_ID::eConvex]->mContactManagers.mTorsionalProperties.getDevicePtr()); }
Sc::ShapeInteraction** getGPUShapeInteractions() { return reinterpret_cast<Sc::ShapeInteraction**>(mGpuContactManagers[GPU_BUCKET_ID::eConvex]->mContactManagers.mShapeInteractions.getDevicePtr()); }
PxgContactManagers& getExistingContactManagers(GPU_BUCKET_ID::Enum type) { return mContactManagers[type]->mContactManagers; }
PxgNewContactManagers& getNewContactManagers(GPU_BUCKET_ID::Enum type) { return mContactManagers[type]->mNewContactManagers; }
PxgGpuContactManagers& getExistingGpuContactManagers(GPU_BUCKET_ID::Enum type) { return mGpuContactManagers[type]->mContactManagers; }
PxgGpuContactManagers& getNewGpuContactManagers(GPU_BUCKET_ID::Enum type) { return mGpuContactManagers[type]->mNewContactManagers; }
PxPinnedArray<PxsContactManagerOutputCounts>& getLostFoundPairsOutput() { return mLostFoundPairsOutputData; }
PxPinnedArray<PxsContactManager*>& getLostFoundPairsCms() { return mLostFoundPairsCms; }
PxgCudaBuffer& getTransformCache() { return mGpuTransformCache; }
PxU32 getTotalNbLostFoundPairs() const { return mTotalLostFoundPairs; }
PxU32 getTotalNbLostFoundPatches() const { return mTotalLostFoundPatches; }
void preallocateNewBuffers(PxU32 nbNewPairs);
void pushBuffer();
PxU32 addHull(const Gu::ConvexHullData& hull);
PxU32 getHullIdxByHostPtr(const Gu::ConvexHullData* hull);
void removeGeometry(PxU32 idx);
//schedules data copies on the near phase stream
void uploadDataChunksToGpu();
void waitAndResetCopyQueues();
//schedules particle material copies on the broad phase stream,
//because particle materials are already accessed in pre integreation
//- we migth be able to remove this dependency
void uploadDataChunksToGpuBp();
void waitAndResetCopyQueuesBp();
PxU32 addTriMesh(const Gu::TriangleMesh& mesh);
PxU32 getTriMeshIdxByHostPtr(const Gu::TriangleMesh* mesh);
PxU32 addHeightfield(const Gu::HeightFieldData& hf);
PxU32 getHeightfieldIdxByHostPtr(const Gu::HeightFieldData* hf);
void registerShape(const PxNodeIndex& nodeIndex, const PxsShapeCore& shapeCore, const PxU32 transformCacheID, const bool isFemCloth, PxActor* actor);
void updateShapeMaterial(const PxsShapeCore& shapeCore);
PxU32 getShapeIndex(const PxsShapeCore& shapeCore);
void unregisterShape(const PxsShapeCore& shapeCore, const PxU32 transformCacheID, const bool isFemCloth);
void registerAggregate(const PxU32 transformCacheID);
void registerMaterial(const PxsMaterialCore& materialCore);
void updateMaterial(const PxsMaterialCore& materialCore);
void unregisterMaterial(const PxsMaterialCore& materialCore);
void registerFEMMaterial(const PxsDeformableSurfaceMaterialCore& materialCore);
void updateFEMMaterial(const PxsDeformableSurfaceMaterialCore& materialCore);
void unregisterFEMMaterial(const PxsDeformableSurfaceMaterialCore& materialCore);
void registerFEMMaterial(const PxsDeformableVolumeMaterialCore& materialCore);
void updateFEMMaterial(const PxsDeformableVolumeMaterialCore& materialCore);
void unregisterFEMMaterial(const PxsDeformableVolumeMaterialCore& materialCore);
void registerParticleMaterial(const PxsPBDMaterialCore& materialCore);
void updateParticleMaterial(const PxsPBDMaterialCore& materialCore);
void unregisterParticleMaterial(const PxsPBDMaterialCore& materialCore);
//direct gpu contact access
bool copyContactData(void* data, PxU32* numContactPairs, const PxU32 maxContactPairs, CUevent startEvent,
CUevent finishEvent, PxU8* baseContactPatches, PxU8* baseContactPoints, PxU8* baseContactForces);
bool evaluateSDFDistances(PxVec4* localGradientAndSDFConcatenated, const PxShapeGPUIndex* shapeIndices, const PxVec4* localSamplePointsConcatenated, const PxU32* samplePointCountPerShape, PxU32 nbElements, PxU32 maxPointCount, CUevent startEvent, CUevent finishEvent);
void synchronizedStreams(CUstream artiStream);
PxgShapeManager& getGpuShapeManager() { return mGpuShapesManager; }
template <class MaterialData>
void mapMaterialIndices(PxU16* gpuMaterialIndices, const PxU16* materialIndices, PxU32 numMaterialIndices);
private:
void compactLostFoundPairs(PxgGpuContactManagers& gpuManagers, const PxU32 numTests, PxU32* touchChangeFlags, PxsContactManagerOutput* cmOutputs);
void softbodyOtherContactApplyCollisionToSimMeshMapping(
PxgDevicePointer<float4> contactsd,
PxgDevicePointer<float4> barycentricsd,
PxgDevicePointer<PxgFemOtherContactInfo> contactInfosd,
PxgDevicePointer<PxU32> totalNumCountsd,
PxgDevicePointer<PxU32> prevNumCountsd);
public:
void softbodyFemContactApplyCollisionToSimMeshMapping(
PxgDevicePointer<float4> barycentrics0d,
PxgDevicePointer<float4> barycentrics1d,
PxgDevicePointer<PxgFemFemContactInfo> contactInfosd,
PxgDevicePointer<PxU32> totalNumCountsd,
PxgDevicePointer<PxU32> prevNumCountsd, bool isSelfCollision, bool isCloth);
private:
void adjustNpIndices(PxgNewContactManagers& newContactManagers, PxPinnedArray<PxgContactManagerInput>& itMainInputs,
PxPinnedArray<PxsContactManager*>& itCms, PxPinnedArray<const Sc::ShapeInteraction*>& itSIs,
PxFloatArrayPinned& itR, PxPinnedArray<PxsTorsionalFrictionData>& itTor,
PxPinnedArray<PxgContactManagerInput>& itNewInputs,
PxPinnedArray<PxsContactManager*>& itNewCms,
PxPinnedArray<const Sc::ShapeInteraction*>& itNewSIs, PxFloatArrayPinned& itNewR,
PxPinnedArray<PxsTorsionalFrictionData>& itNewTor);
void registerContactManagerInternal(PxsContactManager* cm, const Sc::ShapeInteraction* shapeInteraction, PxgContactManagerInput* input, PxsContactManagerOutput& output, PxgNewContactManagers& newContactManagers);
void unregisterContactManagerInternal(PxsContactManager* cm, PxInt32ArrayPinned& removedIndices, PxgNewContactManagers& newContactManagers);
void refreshContactManagerInternal(PxsContactManager* cm, PxsContactManagerOutput* cmOutputs, const Sc::ShapeInteraction** shapeInteractions, PxgContactManagerInput& input, PxgNewContactManagers& newContactManagers,
PxInt32ArrayPinned& removedIndices);
template <typename Manifold>
void prepareTempContactManagers(PxgGpuContactManagers& gpuManagers, PxgNewContactManagers& newManagers, Manifold* emptyManifold);
void prepareTempContactManagers(PxgGpuContactManagers& gpuManagers, PxgNewContactManagers& newManagers);
void removeLostPairsInternal(PxInt32ArrayPinned& removedIndices, PxgContactManagers& contactManagers);
void prepareTempContactManagersInternal(PxgNewContactManagers& newManagers, Cm::FlushPool& flushPool, PxBaseTask* continuation);
void drawContacts(PxRenderOutput& out, CUdeviceptr contactsd, CUdeviceptr normalPensd, const PxU32 numContacts);
template <typename MaterialCore, typename MaterialData>
PxU32 registerMaterialInternal(const MaterialCore& materialCore, RefcountedRecordsMap* materialsMap, PxgMaterialManager& materialManager);
template <typename MaterialCore, typename MaterialData >
void updateMaterialInternal(const MaterialCore& materialCore, RefcountedRecordsMap* materialsMap, PxgMaterialManager& materialManager);
template <typename MaterialData>
PxU16 mapMaterialIndex(PxU16 sdkMaterialIndex, RefcountedRecordsMap* materialsMap, PxgMaterialManager& materialManager)
{
return mapMaterialIndexInternal(sdkMaterialIndex, materialsMap, materialManager, sizeof(MaterialData));
}
PxU16 mapMaterialIndexInternal(PxU16 sdkMaterialIndex, RefcountedRecordsMap* materialsMap,
PxgMaterialManager& materialManager, PxU32 materialDataByteSize);
template <typename MaterialCore>
void unregisterMaterialInternal(const MaterialCore& materialCore, RefcountedRecordsMap* materialsMap, PxgMaterialManager& materialManager);
void updateContactDistance(const PxReal* contactDistances, const PxU32 numContactDistance);
};
template <>
PX_FORCE_INLINE void PxgGpuNarrowphaseCore::mapMaterialIndices<PxsPBDMaterialData>(PxU16* gpuMaterialIndices,
const PxU16* materialIndices, PxU32 numMaterialIndices)
{
PxgGpuNarrowphaseCore::RefcountedRecordsMap* map = mPBDMaterialsMap;
PxgPBDMaterialManager& manager = mGpuPBDMaterialManager;
for(PxU32 i = 0; i < numMaterialIndices; ++i)
{
const PxU16 gpuIndex = mapMaterialIndex<PxsPBDMaterialData>(materialIndices[i], map, manager);
gpuMaterialIndices[i] = gpuIndex;
}
}
}
#endif

View File

@@ -0,0 +1,71 @@
// 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 PXG_NP_KERNEL_INDICES_H
#define PXG_NP_KERNEL_INDICES_H
#define MIDPHASE_WARPS_PER_BLOCK 2
#define NP_TRIMESH_WARPS_PER_BLOCK 2
#define CORRELATE_WARPS_PER_BLOCK 2
#define PS_MIDPHASE_COLLISION_WAPRS_PER_BLOCK 1
#define SB_REFIT_WAPRS_PER_BLOCK 32
namespace physx
{
struct PxgNarrowPhaseBlockDims
{
enum
{
REMOVE_CONTACT_MANAGERS = 512,
COMPACT_LOST_FOUND_PAIRS = 512,
FINISH_CONTACTS = 128,
EARLY_OUT_KERNEL = 128,
COLLIDE_KERNEL = 128,
INITIALIZE_MANIFOLDS = 512,
COMPRESS_CONTACT = 256
};
};
struct PxgNarrowPhaseGridDims
{
enum
{
REMOVE_CONTACT_MANAGERS = 32,
COMPACT_LOST_FOUND_PAIRS = 32,
EARLY_OUT_KERNEL = 32,
COLLIDE_KERNEL = 32,
INITIALIZE_MANIFOLDS = 128,
COMPRESS_CONTACT = 32,
};
};
}
#endif

View File

@@ -0,0 +1,305 @@
// 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 PXG_NPHASE_IMPLEMENTATION_CONTEXT_H
#define PXG_NPHASE_IMPLEMENTATION_CONTEXT_H
#include "CmTask.h"
#include "foundation/PxMutex.h"
#include "PxvNphaseImplementationContext.h"
#include "PxgNarrowphaseCore.h"
#include "PxgSimulationCore.h"
#include "foundation/PxHashMap.h"
#include "PxsContactManagerState.h"
#include "PxgContactManager.h"
#include "PxgPersistentContactManifold.h"
#include "PxgHeapMemAllocator.h"
namespace physx
{
struct PxcNpWorkUnit;
class PxgNphaseImplementationContext;
class PxgGpuContext;
class PxgParticleSystemCore;
class PxsKernelWranglerManager;
namespace Bp
{
class BpNonVirtualMemAllocator;
}
namespace Dy
{
class Context;
}
class PxgCMGpuDiscreteUpdateBase: public Cm::Task
{
private:
PX_NOCOPY(PxgCMGpuDiscreteUpdateBase)
public:
PxgCMGpuDiscreteUpdateBase(PxgNphaseImplementationContext* context):
Cm::Task(0), mDt(FLT_MAX), mContext(context)
{
}
virtual ~PxgCMGpuDiscreteUpdateBase()
{}
void setDt(PxReal dt)
{
mDt = dt;
}
void processContactManagers(PxgContactManagers& managers, PxgGpuContactManagers& managersGPU, GPU_BUCKET_ID::Enum type);
protected:
PxReal mDt; //we could probably retrieve from context to save space?
PxgNphaseImplementationContext* mContext;
};
class PxgCMGpuDiscreteUpdateFallbackTask : public Cm::Task
{
public:
PxgCMGpuDiscreteUpdateFallbackTask(PxgNphaseImplementationContext* context) :
Cm::Task(0), mDt(FLT_MAX), mContext(context)
{
}
virtual ~PxgCMGpuDiscreteUpdateFallbackTask()
{}
void setDt(PxReal dt)
{
mDt = dt;
}
virtual const char* getName() const
{
return "PxgCMGpuDiscreteUpdateFallbackTask";
}
void runInternal();
protected:
PxReal mDt;
PxgNphaseImplementationContext* mContext;
};
class PxgCMGpuDiscreteUpdateTask : public PxgCMGpuDiscreteUpdateBase
{
PxBaseTask* mFirstPassNpContinuation;
PxBaseTask* mPostBroadPhaseTask;
public:
PxgCMGpuDiscreteUpdateTask(PxgNphaseImplementationContext* context) : PxgCMGpuDiscreteUpdateBase(context), mFirstPassNpContinuation(NULL)
{
mPostBroadPhaseTask = NULL;
}
virtual ~PxgCMGpuDiscreteUpdateTask()
{
}
virtual void setPostBroadPhaseTask(PxBaseTask* postBroadPhaseTask)
{
mPostBroadPhaseTask = postBroadPhaseTask;
}
virtual void release()
{
if(mFirstPassNpContinuation)
mFirstPassNpContinuation->removeReference();
PxgCMGpuDiscreteUpdateBase::release();
}
void setFirstPassContinuation(PxBaseTask* firstPassContinuation) { mFirstPassNpContinuation = firstPassContinuation; }
void runInternal();
virtual const char* getName() const
{
return "PxgNphaseImplementationContext.firstContactManagerDiscreteUpdate";
}
};
class PxgCMGpuDiscreteSecondPassUpdateTask : public PxgCMGpuDiscreteUpdateBase
{
public:
PxgCMGpuDiscreteSecondPassUpdateTask(PxgNphaseImplementationContext* context): PxgCMGpuDiscreteUpdateBase(context)
{
}
virtual ~PxgCMGpuDiscreteSecondPassUpdateTask()
{}
void runInternal();
virtual const char* getName() const
{
return "PxgNphaseImplementationContext.secondContactManagerDiscreteUpdate";
}
protected:
};
class PxgNphaseImplementationContext : public PxvNphaseImplementationContext
{
private:
PX_NOCOPY(PxgNphaseImplementationContext)
public:
PxgNphaseImplementationContext(PxsContext& context, PxsKernelWranglerManager* gpuKernelWrangler, PxvNphaseImplementationFallback* fallbackForUnsupportedCMs,
const PxGpuDynamicsMemoryConfig& gpuDynamicsConfig, void* contactStreamBase, void* patchStreamBase, void* forceAndIndiceStreamBase,
PxBoundsArrayPinned& bounds, IG::IslandSim* islandSim,
physx::Dy::Context* dynamicsContext, PxgHeapMemoryAllocatorManager* heapMemoryManager,
bool useGPUNP);
virtual ~PxgNphaseImplementationContext();
virtual void destroy() PX_OVERRIDE PX_FINAL;
virtual void updateContactManager(PxReal dt, bool hasContactDistanceChanged, PxBaseTask* continuation, PxBaseTask* firstPassNpContinuation, Cm::FanoutTask* updateBoundAndShapeTask) PX_OVERRIDE PX_FINAL;
void updateContactManagersFallback(PxReal dt, PxBaseTask* continuation);
virtual void postBroadPhaseUpdateContactManager(PxBaseTask* continuation) PX_OVERRIDE PX_FINAL;
virtual void secondPassUpdateContactManager(PxReal dt, PxBaseTask* continuation) PX_OVERRIDE PX_FINAL;
virtual void fetchUpdateContactManager() PX_OVERRIDE PX_FINAL;
virtual void preallocateNewBuffers(PxU32 nbNewPairs, PxU32 maxIndex) PX_OVERRIDE PX_FINAL;
virtual void registerContactManager(PxsContactManager* cm, const Sc::ShapeInteraction* shapeInteraction, PxI32 touching, PxU32 numPatches) PX_OVERRIDE PX_FINAL;
virtual void unregisterContactManager(PxsContactManager* cm) PX_OVERRIDE PX_FINAL;
virtual void refreshContactManager(PxsContactManager* cm) PX_OVERRIDE PX_FINAL;
virtual void registerShape(const PxNodeIndex& nodeIndex, const PxsShapeCore& shapeCore, const PxU32 transformCacheID, PxActor* actor, const bool isFemCloth) PX_OVERRIDE PX_FINAL;
virtual void updateShapeMaterial(const PxsShapeCore& shapeCore) PX_OVERRIDE PX_FINAL;
virtual void unregisterShape(const PxsShapeCore& shapeCore, const PxU32 transformCacheID, const bool isFemCloth) PX_OVERRIDE PX_FINAL;
virtual void registerAggregate(const PxU32 transformCacheID) PX_OVERRIDE PX_FINAL;
virtual void registerMaterial(const PxsMaterialCore& materialCore) PX_OVERRIDE PX_FINAL;
virtual void updateMaterial(const PxsMaterialCore& materialCore) PX_OVERRIDE PX_FINAL;
virtual void unregisterMaterial(const PxsMaterialCore& materialCore) PX_OVERRIDE PX_FINAL;
virtual void registerMaterial(const PxsDeformableSurfaceMaterialCore& materialCore) PX_OVERRIDE PX_FINAL;
virtual void updateMaterial(const PxsDeformableSurfaceMaterialCore& materialCore) PX_OVERRIDE PX_FINAL;
virtual void unregisterMaterial(const PxsDeformableSurfaceMaterialCore& materialCore) PX_OVERRIDE PX_FINAL;
virtual void registerMaterial(const PxsDeformableVolumeMaterialCore& materialCore) PX_OVERRIDE PX_FINAL;
virtual void updateMaterial(const PxsDeformableVolumeMaterialCore& materialCore) PX_OVERRIDE PX_FINAL;
virtual void unregisterMaterial(const PxsDeformableVolumeMaterialCore& materialCore) PX_OVERRIDE PX_FINAL;
virtual void registerMaterial(const PxsPBDMaterialCore& materialCore) PX_OVERRIDE PX_FINAL;
virtual void updateMaterial(const PxsPBDMaterialCore& materialCore) PX_OVERRIDE PX_FINAL;
virtual void unregisterMaterial(const PxsPBDMaterialCore& materialCore) PX_OVERRIDE PX_FINAL;
virtual PxsContactManagerOutput& getNewContactManagerOutput(PxU32 npId) PX_OVERRIDE PX_FINAL;
virtual void appendContactManagers() PX_OVERRIDE PX_FINAL;
virtual PxsContactManagerOutputIterator getContactManagerOutputs() PX_OVERRIDE PX_FINAL;
virtual void setContactModifyCallback(PxContactModifyCallback* callback) PX_OVERRIDE PX_FINAL { mFallbackForUnsupportedCMs->setContactModifyCallback(callback); }
void updateNarrowPhaseShape();
void mergeContactManagers(PxBaseTask* continuation);
void processResults();
virtual void startNarrowPhaseTasks() PX_OVERRIDE PX_FINAL;
PxReal getToleranceLength();
PxgGpuNarrowphaseCore* getGpuNarrowphaseCore() { return mGpuNarrowphaseCore; }
PxgSimulationCore* getSimulationCore() { return mGpuSimulationCore; }
void setSimulationCore(PxgSimulationCore* sc) { mGpuSimulationCore = sc; }
virtual void acquireContext() PX_OVERRIDE PX_FINAL;
virtual void releaseContext() PX_OVERRIDE PX_FINAL;
virtual void lock() PX_OVERRIDE PX_FINAL { mFallbackForUnsupportedCMs->lock();}
virtual void unlock() PX_OVERRIDE PX_FINAL { mFallbackForUnsupportedCMs->unlock(); }
PxsContext& getContext() { return mContext; }
virtual PxsContactManagerOutputCounts* getLostFoundPatchOutputCounts() PX_OVERRIDE PX_FINAL;
virtual PxsContactManager** getLostFoundPatchManagers() PX_OVERRIDE PX_FINAL;
virtual PxU32 getNbLostFoundPatchManagers() PX_OVERRIDE PX_FINAL;
virtual PxsContactManagerOutput* getGPUContactManagerOutputBase() PX_OVERRIDE PX_FINAL;
virtual PxReal* getGPURestDistances() PX_OVERRIDE PX_FINAL;
virtual Sc::ShapeInteraction** getGPUShapeInteractions() PX_OVERRIDE PX_FINAL;
virtual PxsTorsionalFrictionData* getGPUTorsionalData() PX_OVERRIDE PX_FINAL;
protected:
void prepareTempContactManagers(PxBaseTask* continuation);
void removeLostPairs();
void registerContactManagerInternal(PxsContactManager* cm, const PxcNpWorkUnit& workUnit, PxU32 patchCount, PxI32 touching,
const Sc::ShapeInteraction* shapeInteraction, GPU_BUCKET_ID::Enum bucketId);
PxvNphaseImplementationFallback* mFallbackForUnsupportedCMs;
//those arrays logically belongs to the task, but we keep it here to avoid reallocations each frame
friend class PxgCMGpuDiscreteUpdateBase;
friend class PxgCMGpuDiscreteUpdateTask;
friend class PxgCMGpuDiscreteSecondPassUpdateTask;
friend class PxgCMGpuDiscreteUpdateConvexTriMeshTask;
friend class PxgCMGpuDiscreteSecondPassUpdateConvexTriMeshTask;
PxgCMGpuDiscreteUpdateTask mUpdateCMsFirstPassTask;
PxgCMGpuDiscreteSecondPassUpdateTask mUpdateCMsSecondPassTask;
PxgCMGpuDiscreteUpdateFallbackTask mUpdateFallbackPairs;
PxPinnedArray<PxsContactManagerOutput> mContactManagerOutputs;
PxBitMap mGpuContactManagerBitMap[GPU_BUCKET_ID::eCount];
PxU32 mRecordedGpuPairCount[GPU_BUCKET_ID::eCount];
PxU32 mNbPairCount[GPU_BUCKET_ID::eCount];
PxgGpuNarrowphaseCore* mGpuNarrowphaseCore;
PxgSimulationCore* mGpuSimulationCore;
PxgGpuContext* mGpuDynamicContext;
PxU32 mTotalNbPairs;
PxBoundsArrayPinned& mBounds;
bool mHasContactDistanceChanged;
bool mUseGPUBP;
PxU32 mMaxPatches;
};
}
#endif

View File

@@ -0,0 +1,98 @@
// 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 PXG_PERSISTENT_CONTACT_MANIFOLD_H
#define PXG_PERSISTENT_CONTACT_MANIFOLD_H
#include "cutil_math.h"
#include "AlignedTransform.h"
#define PXG_MAX_PCM_CONTACTS 4
#define PXG_MULTIMANIFOLD_MAX_SUBMANIFOLDS 4
#define PXG_SUBMANIFOLD_MAX_CONTACTS 6
namespace physx
{
struct PX_ALIGN_PREFIX(16) PxgPersistentContactManifold
{
float4 mLocalNormal_PenW[PXG_MAX_PCM_CONTACTS]; //local normal + penetration
float4 mLocalContactA[PXG_MAX_PCM_CONTACTS]; //local contact in body A's space
float4 mLocalContactB[PXG_MAX_PCM_CONTACTS]; //local contact in body B's space
float4 mRelativePos; //Cached relative transforms
PxAlignedQuat mQuatA; //Cached body A's quatenion
PxAlignedQuat mQuatB; //Cached body B's quatenion
PxU32 mNbContacts; //NbContacts
PxU32 mNbWarmStartPoints; //Nb warm start points
PxU32 mWarmStartA; //GJK warm-start mask for shape A
PxU32 mWarmStartB; //GJK warm-start mask for shape B
PX_FORCE_INLINE void clear()
{
mNbContacts = 0;
mNbWarmStartPoints = 0;
mRelativePos = make_float4(PX_MAX_REAL, PX_MAX_REAL, PX_MAX_REAL, PX_MAX_REAL);
mQuatA = PxAlignedQuat(0.f, 0.f, 0.f, 1.f);
mQuatB = PxAlignedQuat(0.f, 0.f, 0.f, 1.f);
}
//KS - TODO - extend and add functionality as is required...
}
PX_ALIGN_SUFFIX(16);
struct PX_ALIGN_PREFIX(16) PxgContact
{
PxVec3 pointA;
PxVec3 pointB;
PxVec3 normal;
PxReal penetration;
PxU32 triIndex;
PxU32 pad;
} // 48 due to padding
PX_ALIGN_SUFFIX(16);
struct PX_ALIGN_PREFIX(16) PxgPersistentContactMultiManifold
{
PxgContact mContacts[PXG_MULTIMANIFOLD_MAX_SUBMANIFOLDS][PXG_SUBMANIFOLD_MAX_CONTACTS]; // 1152
PxU32 mNbContacts[PXG_MULTIMANIFOLD_MAX_SUBMANIFOLDS]; // 1168
PxAlignedTransform mRelativeTransform; // 1200
PxU32 mNbManifolds; // 1216 due to padding
PX_FORCE_INLINE void clear()
{
mNbManifolds = 0;
mRelativeTransform.p = make_float4(PX_MAX_REAL, PX_MAX_REAL, PX_MAX_REAL, PX_MAX_REAL);
mRelativeTransform.q = PxAlignedQuat(0.f, 0.f, 0.f, 1.f);
}
}
PX_ALIGN_SUFFIX(16);
}
#endif

View File

@@ -0,0 +1,163 @@
// 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 PXG_SHAPE_MANAGER_H
#define PXG_SHAPE_MANAGER_H
#include "foundation/PxPreprocessor.h"
#include "PxSceneDesc.h"
#include "foundation/PxPinnedArray.h"
#include "CmIDPool.h"
#include "PxgCudaBuffer.h"
#include "foundation/PxBitMap.h"
#include "PxsMaterialCore.h"
#include "PxsDeformableSurfaceMaterialCore.h"
#include "PxsDeformableVolumeMaterialCore.h"
#include "PxsPBDMaterialCore.h"
#include "PxgConvexConvexShape.h"
namespace physx
{
class PxCudaContext;
class PxgHeapMemoryAllocatorManager;
class PxgCopyManager;
class PxNodeIndex;
class PxgShapeManager
{
public:
PxgShapeManager(PxgHeapMemoryAllocatorManager* heapManager);
~PxgShapeManager(){}
//this method push CopyDesc to PxgCopyManager
void initialize(PxCudaContext* cudaContext, CUstream stream);
void scheduleCopyHtoD(PxgCopyManager& copyManager, PxCudaContext* cudaContext, CUstream stream);
PxU32 registerShape(PxgShape& shape);
void registerShapeInstance(const PxNodeIndex& nodeIndex, const PxU32 transformCacheID, PxActor* actor, bool aggregate = false);
void unregisterShape(const PxU32 shapeId);
void unregisterShapeInstance(const PxU32 transformCacheID);
void updateShapeMaterial(const PxU32 materalIndex, const PxU32 id);
void releaseIDs() { mIdPool.processDeferredIds(); }
Cm::DeferredIDPool mIdPool;
PxgHeapMemoryAllocatorManager* mHeapManager;
PxPinnedArray<PxgShape> mHostShapes;
PxPinnedArray<PxNodeIndex> mHostShapesRemapTable;//remap table from shape to node index
PxInt32ArrayPinned mHostShapeIdTable;
PxPinnedArray<PxActor*> mHostTransformCacheIdToActorTable; // remap table from transformCacheId to PxActor
PxgCudaBuffer mGpuShapesBuffer;
PxgCudaBuffer mGpuShapesRemapTableBuffer; // shape to rigid
PxgCudaBuffer mGpuTransformCacheIdToActorTableBuffer; // transformCacheId to PxActor
PxgCudaBuffer mGpuRigidIndiceBuffer; // 00011 nodeIndex 0 has shape(0, 2, 3), nodeIndex 1 has shape(1, 4)(it can be either articulation link or rigid body)
PxgCudaBuffer mGpuShapeIndiceBuffer; // 02314
PxgCudaBuffer mGpuUnsortedShapeIndicesBuffer; // needed when recomputing the shape to rigids mapping
PxgCudaBuffer mGpuTempRigidBitIndiceBuffer; //either the lower 32 bits or higher 32 bits of mGpuRigidIndiceBuffer
PxgCudaBuffer mGpuTempRigidIndiceBuffer;
PxBitMap mDirtyShapeMap;
PxBitMap mDirtyTransformCacheMap;
bool mResizeRequired;
bool mTransformCacheResizeRequired;
PxI32 mMaxShapeId;
PxI32 mMaxTransformCacheID;
bool mHasShapeChanged;
bool mHasShapeInstanceChanged;
private:
PX_NOCOPY(PxgShapeManager)
};
class PxgMaterialManager
{
PX_NOCOPY(PxgMaterialManager)
public:
PxgMaterialManager(PxgHeapMemoryAllocatorManager* heapManager, const PxU32 elemSize = sizeof(PxsMaterialData));
virtual ~PxgMaterialManager(){}
//this method push CopyDesc to PxgCopyManager
virtual void scheduleCopyHtoD(PxgCopyManager& copyManager, PxCudaContext* cudaContext, CUstream stream, const PxU32 elemSize);
PxU32 registerMaterial(const PxU8* materialData, const PxU32 elemSize);
void updateMaterial(const PxU8* materialData, const PxU32 elemSize, const PxU32 id);
void unregisterMaterial(const PxU32 materialId);
void releaseIDs() { mIdPool.processDeferredIds(); }
PxgCudaBuffer mGpuMaterialBuffer;
protected:
Cm::DeferredIDPool mIdPool;
PxgHeapMemoryAllocatorManager* mHeapManager;
PxInt8ArrayPinned mHostMaterial;
PxBitMap mDirtyMaterialMap;
bool mResizeRequired;
};
class PxgFEMMaterialManager : public PxgMaterialManager
{
public:
PxgFEMMaterialManager(PxgHeapMemoryAllocatorManager* heapManager, const PxU32 elemSize);
virtual void scheduleCopyHtoD(PxgCopyManager& copyManager, PxCudaContext* cudaContext, CUstream stream, const PxU32 elemSize);
};
class PxgFEMSoftBodyMaterialManager : public PxgFEMMaterialManager
{
public:
PxgFEMSoftBodyMaterialManager(PxgHeapMemoryAllocatorManager* heapManager);
};
class PxgFEMClothMaterialManager : public PxgMaterialManager
{
public:
PxgFEMClothMaterialManager(PxgHeapMemoryAllocatorManager* heapManager) :
PxgMaterialManager(heapManager, sizeof(PxsDeformableSurfaceMaterialData))
{
}
PxsDeformableSurfaceMaterialData* getCPUMaterialData()
{
return reinterpret_cast<PxsDeformableSurfaceMaterialData*>(mHostMaterial.begin());
}
};
class PxgPBDMaterialManager : public PxgMaterialManager
{
public:
PxgPBDMaterialManager(PxgHeapMemoryAllocatorManager* heapManager) :
PxgMaterialManager(heapManager, sizeof(PxsPBDMaterialData))
{
}
};
}
#endif

View File

@@ -0,0 +1,137 @@
// 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 CONVEX_FORMAT_H
#define CONVEX_FORMAT_H
#include "foundation/PxVec3.h"
#include "foundation/PxVec4.h"
#include "foundation/PxBounds3.h"
#include "foundation/PxPlane.h"
#include "foundation/PxMat44.h"
#include "foundation/PxMemory.h"
#include "foundation/PxUtilities.h"
namespace physx
{
struct ConvexHullCooked
{
struct Valency
{
PxU16 mCount;
PxU16 mOffset;
};
struct BigConvexRawData
{
// Support vertex map
PxU16 mSubdiv; // "Gaussmap" subdivision
PxU16 mNbSamples; // Total #samples in gaussmap PT: this is not even needed at runtime!
PxU8* mSamples; //mNbSamples * 2 elements
PX_FORCE_INLINE const PxU8* getSamples2() const
{
return mSamples + mNbSamples;
}
//~Support vertex map
// Valencies data
PxU32 mNbVerts; //!< Number of vertices
PxU32 mNbAdjVerts; //!< Total number of adjacent vertices ### PT: this is useless at runtime and should not be stored here
Valency* mValencies; //!< A list of mNbVerts valencies (= number of neighbors) mNbVerts elements
PxU8* mAdjacentVerts; //!< List of adjacent vertices
//~Valencies data
};
struct InternalObjectsData
{
PxReal mRadius;
PxReal mExtents[3];
PX_FORCE_INLINE void reset()
{
mRadius = 0.0f;
mExtents[0] = 0.0f;
mExtents[1] = 0.0f;
mExtents[2] = 0.0f;
}
};
struct HullPolygon
{
PxPlane mPlane; //!< Plane equation for this polygon //Could drop 4th elem as it can be computed from any vertex as: d = - p.dot(n);
PxU16 mVRef8; //!< Offset of vertex references in hull vertex data (CS: can we assume indices are tightly packed and offsets are ascending?? DrawObjects makes and uses this assumption)
PxU8 mNbVerts; //!< Number of vertices/edges in the polygon
PxU8 mMinIndex; //!< Index of the polygon vertex that has minimal projection along this plane's normal.
PX_FORCE_INLINE PxReal getMin(const PxVec3* PX_RESTRICT hullVertices) const //minimum of projection of the hull along this plane normal
{
return mPlane.n.dot(hullVertices[mMinIndex]);
}
PX_FORCE_INLINE PxReal getMax() const { return -mPlane.d; } //maximum of projection of the hull along this plane normal
};
PxBounds3 mAABB;
PxVec3 mCenterOfMass;
PxU16 mNbEdges;
PxU8 mNbHullVertices;
PxU8 mNbPolygons;
HullPolygon* mPolygons; //!< Array of mNbPolygons structures
PxVec3* mVertices; //mNbHullVertices elements
PxU8* mFacesByEdges8; //mNbEdges * 2 elements
PxU8* mFacesByVertices8; //mNbHullVertices * 3 elements
PxU16* mVerticesByEdges16; //mNbEdges * 2 elements
PxU8* mVertexData8; //G-d knows how many elements
BigConvexRawData* mBigConvexRawData; //!< Hill climbing data, only for large convexes! else NULL.
InternalObjectsData mInternal;
bool isGpuFriendly()
{
bool ret = mNbHullVertices <= 64;
if(!ret)
return false;
for(PxU32 i = 0; i < mNbPolygons; ++i)
ret &= mPolygons[i].mNbVerts <= 31;
return ret;
}
};
}
#endif

View File

@@ -0,0 +1,306 @@
// 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 __CONVEXNPCOMMON_H__
#define __CONVEXNPCOMMON_H__
#define NUM_TMP_CONTACTS_PER_PAIR 32
#define CVX_TRI_MAX_CONTACTS 5
#define MAX_MESH_MESH_PATCHES 128
// Patches correlation - same normal threshold
// 8 degrees
//#define PATCH_ACCEPTANCE_EPS 0.990268f
// 5 degrees
#define PATCH_ACCEPTANCE_EPS 0.996194698f
// 3 degrees
//#define PATCH_ACCEPTANCE_EPS 0.99862953f
#define CONVEX_TRIMESH_CACHED 0xFFffFFff
// AD: used to specify sizes of shared memory structs
// for collisions involving convexes. Make sure you
// know what you are doing if you change this.
#define CONVEX_MAX_VERTICES_POLYGONS 64
#include "foundation/PxPreprocessor.h"
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec3.h"
#include "foundation/PxQuat.h"
#include "foundation/PxTransform.h"
#include "geometry/PxMeshScale.h"
#include "GuBV32.h"
#include "PxgCommonDefines.h"
#include <vector_types.h>
namespace physx
{
struct ConvexMeshPair
{
physx::PxTransform aToB; // pB = aToB.transform(pA + normal * separation) 28
int startIndex; // start index in the ConvexTriContacts and ConvexTriPairs arrays 32
int count; // the number of triangles in the ConvexTriContacts and ConvexTriPairs 36
int cmIndex; // index of the original CM, to index into the output buffer and pass on to contact reporting 40
int roundedStartIndex; // start index in the sorted triangle index array. For each pair, the number of indices 44
// assigned to is the number of triangles padded to a multiple of 4 and duplicated to have
// space for the temp buffer for the radix sort. The start index is aligned to a mutliple of 4.
int pad; // pad 48
uint2 materialIndices; // material index for shape0 and shape1 56
};
struct ConvexTriNormalAndIndex
{
static const PxU32 DeferredContactMask = 0x80000000;
static const PxU32 NbContactsShift = 27;
physx::PxVec3 normal; // normal
int index; // isDeferredContact is in bit 31, nbContacts is in bits 27-30, rest is cpu mesh index for the triangle
static PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getTriangleIndex(PxU32 index)
{
return (index & ((1<<NbContactsShift)-1));
}
static PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getNbContacts(PxU32 index)
{
return (index & (~DeferredContactMask)) >> NbContactsShift;
}
static PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 isDeferred(const PxU32 index)
{
return index & DeferredContactMask;
}
};
struct ConvexTriContacts
{
PxU32 index;
};
struct ConvexTriContact
{
float4 contact_sepW;
};
//each convex triangle pairs will generate the intermediate data in case we need to
//do post process of this pair
struct ConvexTriIntermediateData
{
//Enums to indicate the barycentric weighting of the contacts
enum VoronoiState: PxU32
{
eV0 = 1u << 29,
eV1 = 2u << 29,
eV2 = 3u << 29,
eE01 = 4u << 29,
eE02 = 5u << 29,
eE12 = 6u << 29,
eMASK = 0xe0000000
};
physx::PxU32 gpuTriIndex; //gpu triangle index
static PX_CUDA_CALLABLE PX_FORCE_INLINE bool isEdgeContact(const PxU32 mask)
{
return mask & 0x80000000;
}
};
typedef ConvexMeshPair SphereMeshPair;
typedef ConvexTriContacts SphereTriContacts;
typedef ConvexTriNormalAndIndex SphereTriNormalAndIndex;
typedef ConvexTriIntermediateData SphereTriIntermediateData;
}
#if PX_CUDA_COMPILER
#include "PxgCommonDefines.h"
namespace physx
{
PX_ALIGN_PREFIX(16)
struct MidphaseScratch
{
const float4 * PX_RESTRICT trimeshVerts;
const uint4 * PX_RESTRICT trimeshTriIndices;
PxTransform shapeToMeshNoScale;
PxTransform meshToWorld;
PxMeshScale trimeshScale;
PxVec3 inflatedExtents;
PxVec3 center;
PxU32 shape_materialIndex;
PxU32 trimeshShape_materialIndex;
//bv32 tree
const Gu::BV32DataPacked* bv32PackedNodes;
//stack for traversal
int sBv32Nodes[320]; //10 depth of the bv32 tree
}PX_ALIGN_SUFFIX(16);
PX_COMPILE_TIME_ASSERT(sizeof(MidphaseScratch) <= WARP_SIZE * 16 * sizeof(PxU32));
}
#include "schlockShared.h"
//0 is primitive, 1 is tetrahedron world space
struct TetCollideScratch
{
physx::PxVec3 vA[CONVEX_MAX_VERTICES_POLYGONS];
physx::PxVec3 vB[4];
schlock::GjkCachedData cachedData;
schlock::GjkOutput gjkOutput;
physx::PxQuat rot0;
physx::PxVec3 scale0;
physx::PxReal contactDistance;
physx::PxReal inSphereRadius0;
physx::PxReal inSphereRadius1;
physx::PxVec3 searchDir;
physx::PxU8 nbVertices0;
physx::PxU8 nbVertices1;
physx::PxU32 tetIndex0;
physx::PxU32 tetIndex1;
__device__ void Clear()
{
if (threadIdx.x == 0)
cachedData.size = 0;
__syncwarp();
}
};
#include "epa.cuh"
#include "gjk.cuh"
__device__ static schlock::GjkResult::Enum tetPrimitivesCollide2(
squawk::EpaScratch& ss_epa_scratch,
TetCollideScratch& ss_scratch,
const physx::PxU32 globalWarpIndex)
{
typedef schlock::GjkResult GjkResult;
const physx::PxReal convergenceRatio = 1 - 0.000225f;
assert(ss_scratch.nbVertices0 <= 64);
assert(ss_scratch.nbVertices1 <= 64);
physx::PxVec3 initialDir(1, 0, 0);
physx::PxVec3 aToB_p = ss_scratch.searchDir; // ss_scratch.aToB.p;
if (aToB_p.magnitudeSquared() > 0)
initialDir = aToB_p; // GJK's initial start dir is usually from the warm cache => lazy normalize inside GJK
GjkResult::Enum gjkResult = squawk::gjk(
ss_scratch.vA, ss_scratch.nbVertices0,
ss_scratch.vB, ss_scratch.nbVertices1,
initialDir,
ss_scratch.contactDistance,
convergenceRatio,
ss_scratch.gjkOutput, ss_scratch.cachedData);
__syncwarp();
if (gjkResult == GjkResult::eDISTANT)
{
return GjkResult::eDISTANT;
}
bool separated = (gjkResult == GjkResult::eCLOSE);
bool anomaly = separated && ss_scratch.gjkOutput.closestPointDir.dot(ss_scratch.gjkOutput.direction) < 0.999f;
GjkResult::Enum result = GjkResult::eCLOSE;
if (!separated || anomaly)
{
GjkResult::Enum epaResult = squawk::epa(ss_epa_scratch,
ss_scratch.vA, ss_scratch.nbVertices0,
ss_scratch.vB, ss_scratch.nbVertices1,
&(ss_scratch.cachedData),
convergenceRatio,
0.5f * (ss_scratch.inSphereRadius0 + ss_scratch.inSphereRadius1),
ss_scratch.gjkOutput);
//separated = epaResult == GjkResult::eCLOSE;
result = epaResult;
__syncwarp();
if (ss_scratch.gjkOutput.degenerate)
{
//we need to re-run gjk epa with other configurations
ss_scratch.cachedData.size = 0;
//we need to re-run gjk epa with other configurations
initialDir = physx::PxVec3(0.f, 1.f, 0.f);
GjkResult::Enum gjkResult = squawk::gjk(
ss_scratch.vA, ss_scratch.nbVertices0,
ss_scratch.vB, ss_scratch.nbVertices1,
initialDir,
ss_scratch.contactDistance,
convergenceRatio,
ss_scratch.gjkOutput, ss_scratch.cachedData);
__syncwarp();
GjkResult::Enum epaResult = squawk::epa(ss_epa_scratch,
ss_scratch.vA, ss_scratch.nbVertices0,
ss_scratch.vB, ss_scratch.nbVertices1,
&(ss_scratch.cachedData),
convergenceRatio,
0.5f * (ss_scratch.inSphereRadius0 + ss_scratch.inSphereRadius1),
ss_scratch.gjkOutput);
//separated = epaResult == GjkResult::eCLOSE;
result = epaResult;
}
__syncwarp();
}
return result;
}
#endif
#endif

View File

@@ -0,0 +1,424 @@
// 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 CUDA_NP_COMMON_H
#define CUDA_NP_COMMON_H
#include "foundation/PxVec3.h"
#include <stdio.h>
#include "convexFormat.h"
#include "cutil_math.h"
#include "PxgCommonDefines.h"
#include "PxgPersistentContactManifold.h"
#include "assert.h"
#define CONVEX_PLANE_WARPS_PER_BLOCK 4
#define GJK_EPA_WARPS_PER_BLOCK 1
#define NUM_TMP_CONTACTS_PER_PAIR 32
//The smallest epsilon we will permit (scaled by PxTolerancesScale.length)
#define PCM_WITNESS_POINT_LOWER_EPS 1e-2f
//The largest epsilon we will permit (scaled by PxTolerancesScale.length)
#define PCM_WITNESS_POINT_UPPER_EPS 5e-2f
namespace physx
{
struct PxgPersistentContactManifold;
struct PxgPersistentContactMultiManifold;
struct PxgContactManagerInput;
struct PxsContactManagerOutput;
class PxsContactManager;
struct PxsTorsionalFrictionData;
namespace Sc
{
class ShapeInteraction;
}
struct PxgPairManagementData
{
PxgContactManagerInput* mContactManagerInputData;
PxsContactManagerOutput* mContactManagerOutputData;
PxsContactManager** mCpuContactManagerMapping;
Sc::ShapeInteraction** mShapeInteractions;
PxReal* mRestDistances;
PxsTorsionalFrictionData* mTorsionalData;
PxU32* mTempAccumulator;
PxU32* mBlockSharedAccumulator;
PxU32* mRemoveIndices;
PxU32 mNbPairs;
PxU32 mNbToRemove;
void* mPersistentContactManagers;// either PxgPersistentContactManifold or PxgPersistentMultiManagementData
PxgPairManagementData() : mContactManagerInputData(NULL), mContactManagerOutputData(NULL), mCpuContactManagerMapping(NULL), mShapeInteractions(NULL),
mRestDistances(NULL), mTorsionalData(NULL), mTempAccumulator(NULL), mBlockSharedAccumulator(NULL), mNbPairs(0)
{
}
};
struct PX_ALIGN_PREFIX(16) PxgPatchAndContactCounters
{
enum OverflowError
{
NO_OVERFLOW = 0,
CONTACT_BUFFER_OVERFLOW = 1 << 0,
FORCE_BUFFER_OVERFLOW = 1 << 1,
PATCH_BUFFER_OVERFLOW = 1 << 2
};
PxU32 patchesBytes;
PxU32 contactsBytes;
PxU32 forceAndIndiceBytes;
PxU32 overflowError;
__device__
void setOverflowError(const OverflowError& err)
{
PX_UNUSED(err);
#if __CUDA_ARCH__
atomicOr(&overflowError, PxU32(err));
#endif
}
__host__ __device__
PxU32 getOverflowError() const
{
return overflowError;
}
} PX_ALIGN_SUFFIX(16);
}
__host__ __device__ inline
physx::ConvexHullCooked::Valency u32ToValency(physx::PxU32 countOffset)
{
physx::ConvexHullCooked::Valency v;
v.mCount = u32High(countOffset);
v.mOffset = u32Low(countOffset);
return v;
}
__host__ __device__ inline
physx::PxU32 valencyToPxU32(const physx::ConvexHullCooked::Valency& v)
{
return merge(v.mCount, v.mOffset);
}
__host__ __device__ inline
physx::PxU8 getNbAdjVerts(physx::PxU32 val)
{
return u16Low(u32Low(val));
}
__host__ __device__ inline
physx::PxU16 getNbEdges(physx::PxU32 val)
{
return u32High(val);
}
__host__ __device__ inline
physx::PxU8 getNbPolygons(physx::PxU32 val)
{
return u16Low(u32Low(val));
}
__host__ __device__ inline
physx::PxU16 getVRef8(physx::PxU32 val)
{
return u32High(val);
}
__host__ __device__ inline
physx::PxU8 getNbVerts(physx::PxU32 val)
{
return u16High(u32Low(val));
}
__host__ __device__ inline
physx::PxU8 getMinIndex(physx::PxU32 val)
{
return u16Low(u32Low(val));
}
__host__ __device__ inline
physx::PxU32 merge(physx::PxU16 hi, physx::PxU8 lohi, physx::PxU8 lolo)
{
return merge(hi, merge(lohi, lolo));
}
__host__ __device__ inline bool isValidTet(const physx::PxVec3& worldV0, const physx::PxVec3& worldV1, const physx::PxVec3& worldV2, const physx::PxVec3& worldV3)
{
return (worldV1 - worldV0).dot((worldV2 - worldV0).cross(worldV3 - worldV0)) > 1e-9f;
}
//device only functions
#if PX_CUDA_COMPILER
#include "reduction.cuh"
class MeshScaling
{
public:
__device__ MeshScaling(const physx::PxVec3& scale_, const physx::PxQuat& rotation_)
{
scale = scale_;
rotation = rotation_;
idtMeshScale = (scale.x == 1.0f && scale.y == 1.0f && scale.z == 1.0f);
flipNormal = ((scale.x * scale.y * scale.z) < 0.0f);
}
__device__ inline physx::PxVec3 vertex2Shape(const physx::PxVec3& v) const
{
using namespace physx;
PxVec3 temp = rotation.rotate(v);
temp.x *= scale.x;
temp.y *= scale.y;
temp.z *= scale.z;
return rotation.rotateInv(temp);
}
__device__ inline physx::PxVec3 shape2Vertex(const physx::PxVec3& v) const
{
using namespace physx;
PxVec3 temp = rotation.rotate(v);
temp.x /= scale.x;
temp.y /= scale.y;
temp.z /= scale.z;
return rotation.rotateInv(temp);
}
//Transforms a normal vector from vertex to shape space. This keeps the normal vector perpendicular to surfaces that get scaled with the same transform.
//Does not preserve length. Is applicable to other covariant vectors too.
__device__ inline physx::PxVec3 vertex2ShapeNormalVector(const physx::PxVec3& normal) const
{
return shape2Vertex(normal);
}
//Transforms a normal vector from shape to vertex space. This keeps the normal vector perpendicular to surfaces that get scaled with the same transform.
//Does not preserve length. Is applicable to other covariant vectors too.
__device__ inline physx::PxVec3 shape2VertexNormalVector(const physx::PxVec3& normal) const
{
return vertex2Shape(normal);
}
__device__ inline void getShapeSpaceVert(physx::PxVec3& triV0, physx::PxVec3& triV1, physx::PxVec3& triV2,
physx::PxVec3& v0, physx::PxVec3& v1, physx::PxVec3& v2) const
{
if (idtMeshScale)
{
v0 = triV0;
v1 = triV1;
v2 = triV2;
}
else
{
// Triangle scaling, triangle verts in shape space
triV0 = vertex2Shape(triV0);
triV1 = vertex2Shape(triV1);
triV2 = vertex2Shape(triV2);
v0 = triV0;
v1 = flipNormal ? triV2 : triV1;
v2 = flipNormal ? triV1 : triV2;
}
}
physx::PxVec3 scale;
physx::PxQuat rotation;
bool idtMeshScale;
bool flipNormal;
};
//Applies a potentially non-uniform scaling to the point v. The scaling can be expressed in a rotated coordinate frame defined by the quaternion called rotation.
__device__ inline
physx::PxVec3 vertex2Shape(const physx::PxVec3& v, const physx::PxVec3& scale, const physx::PxQuat& rotation)
{
using namespace physx;
PxVec3 temp = rotation.rotate(v);
temp.x *= scale.x;
temp.y *= scale.y;
temp.z *= scale.z;
return rotation.rotateInv(temp);
}
//Removes a potentially non-uniform scaling from the point v. The scaling can be expressed in a rotated coordinate frame defined by the quaternion called rotation.
__device__ inline
physx::PxVec3 shape2Vertex(const physx::PxVec3& v, const physx::PxVec3& scale, const physx::PxQuat& rotation)
{
using namespace physx;
PxVec3 temp = rotation.rotate(v);
temp.x /= scale.x;
temp.y /= scale.y;
temp.z /= scale.z;
return rotation.rotateInv(temp);
}
//Transforms a normal vector from vertex to shape space. This keeps the normal vector perpendicular to surfaces that get scaled with the same transform.
//Does not preserve length. Is applicable to other covariant vectors too.
__device__ inline
physx::PxVec3 vertex2ShapeNormalVector(const physx::PxVec3& normal, const physx::PxVec3& scale, const physx::PxQuat& rotation)
{
return shape2Vertex(normal, scale, rotation);
}
//Transforms a normal vector from shape to vertex space. This keeps the normal vector perpendicular to surfaces that get scaled with the same transform.
//Does not preserve length. Is applicable to other covariant vectors too.
__device__ inline
physx::PxVec3 shape2VertexNormalVector(const physx::PxVec3& normal, const physx::PxVec3& scale, const physx::PxQuat& rotation)
{
return vertex2Shape(normal, scale, rotation);
}
__device__ inline static
void prepareVertices(const PxTransform& transf,
PxVec3 scale, PxQuat rot,
PxU32 nbHullVertices,
const float4* pVertices,
PxVec3* s_vertices
)
{
assert(transf.isFinite());
for (PxU32 i = threadIdx.x; i < nbHullVertices; i += WARP_SIZE)
{
float4 f = pVertices[i];
s_vertices[i] = transf.transform(vertex2Shape(PxVec3(f.x, f.y, f.z), scale, rot));
assert(s_vertices[i].isFinite());
}
}
__device__ inline static
void prepareVertices(PxVec3 scale, PxQuat rot,
PxU32 nbHullVertices,
const float4* pVertices,
PxVec3* s_vertices
)
{
for (PxU32 i = threadIdx.x; i < nbHullVertices; i += WARP_SIZE)
{
float4 f = pVertices[i];
s_vertices[i] = vertex2Shape(PxVec3(f.x, f.y, f.z), scale, rot);
}
}
#define MESH_MANIFOLD_EPSILON 0.05f
#define BOX_MARGIN_RATIO 0.25f
__device__ inline static
PxReal calculatePCMConvexMargin(const float4& extents_, const PxVec3& scale, const PxReal toleranceLength)
{
using namespace physx;
const PxVec3 extents = PxVec3(extents_.x * scale.x,
extents_.y * scale.y,
extents_.z * scale.z);
const PxReal min = fminf(fminf(extents.x, extents.y), extents.z);
const PxReal toleranceMargin = toleranceLength * MESH_MANIFOLD_EPSILON;
//ML: 25% of the minimum extents of the internal AABB as this convex hull's margin
return fminf((min * BOX_MARGIN_RATIO), toleranceMargin);
}
__device__ inline static
PxReal calculatePCMConvexMargin(const PxVec3& extents, const PxReal toleranceLength)
{
using namespace physx;
const PxReal min = fminf(fminf(extents.x, extents.y), extents.z);
const PxReal toleranceMargin = toleranceLength * MESH_MANIFOLD_EPSILON;
//ML: 25% of the minimum extents of the internal AABB as this convex hull's margin
return fminf((min * BOX_MARGIN_RATIO), toleranceMargin);
}
__device__ inline static physx::PxReal maxTransformPositionDelta(const physx::PxVec3& curP, const physx::PxVec3& preP)
{
using namespace physx;
const PxVec3 deltaP = curP - preP;
return PxMax(PxAbs(deltaP.x), PxMax(PxAbs(deltaP.y), PxAbs(deltaP.z)));
}
__constant__ __device__ PxF32 local_invalidateThresholdsConvex[5] = { 0.5f, 0.125f, 0.25f, 0.375f, 0.375f };
__constant__ __device__ PxF32 local_invalidateQuatThresholdsConvex[5] = { 0.9998f, 0.9999f, 0.9999f, 0.9999f, 0.9999f };
__constant__ __device__ PxF32 local_invalidateThresholdsSphere[3] = { 0.5f, 0.1f, 0.75f };
__constant__ __device__ PxF32 local_invalidateQuatThresholdsSphere[3] = { 0.9995f, 0.9999f, 0.9997f };
__constant__ __device__ PxF32 local_invalidateQuatThresholdsConvexPlane[5] = { 0.99996f, 0.99996f, 0.99996f, 0.99996f, 0.99996f };
__device__ inline static
PxU32 invalidate_BoxConvex(const PxVec3& curRelPos, const PxQuat& curQuatA, const PxQuat& curQuatB,
const PxVec3& preRelPos, const PxQuat& preRelQuatA, const PxQuat& preRelQuatB,
const physx::PxReal minMargin, const physx::PxReal radiusA, const physx::PxReal radiusB,
const physx::PxU8 manifold_NumContacts, PxF32* local_invalidateThresholds, PxF32* local_invalidateQuatThresholds)
{
using namespace physx;
//This is the translational threshold used in invalidate_BoxConvexHull. 0.5 is 50% of the object margin. we use different threshold between
//0 and 4 points. This threashold is a scale that is multiplied by the objects' margins.
const PxReal ratio = local_invalidateThresholds[manifold_NumContacts];
const PxReal thresholdP = minMargin * ratio;
const PxReal deltaP = maxTransformPositionDelta(curRelPos, preRelPos);
//This is the rotational threshold used in invalidate_BoxConvexHull. 0.9998 is a threshold for quat difference
//between previous and current frame
const PxReal thresholdQ = local_invalidateQuatThresholds[manifold_NumContacts];
const PxReal deltaQA = curQuatA.dot(preRelQuatA);
const PxReal deltaQB = curQuatB.dot(preRelQuatB);
bool generateContacts = (deltaP > thresholdP) || (thresholdQ > deltaQA) || (thresholdQ > deltaQB);
if (!generateContacts)
{
const PxReal aRadian = deltaQA < 1.0f ? acosf(deltaQA) : 0.f;
const PxReal bRadian = deltaQB < 1.0f ? acosf(deltaQB) : 0.f;
const PxReal travelDistA = aRadian * radiusA;
const PxReal travelDistB = bRadian * radiusB;
generateContacts = (travelDistA > thresholdP) || (travelDistB > thresholdP);
}
return generateContacts;
}
#endif
#endif

View File

@@ -0,0 +1,230 @@
// 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 GU_SCHLOCKSHARED_H
#define GU_SCHLOCKSHARED_H
#include "foundation/PxVec3.h"
#include "foundation/PxMat33.h"
#include "foundation/PxTransform.h"
#include "geometry/PxMeshScale.h"
#include <assert.h>
#include <stdio.h>
#define GJK_LOGGING 0
#define EPA_REPLACE_TRIANGLE_LOGGING 0
#define EPA_LOGGING 0
#define EPA_LOG_DEGENERATE_CASES 0
#if GJK_LOGGING
#define GJK_LOG(...) if(gjkDebug) printf(__VA_ARGS__)
#else
#define GJK_LOG(...)
#endif
namespace schlock
{
extern bool epaDebug;
using namespace physx;
template<typename T>
PX_CUDA_CALLABLE PX_FORCE_INLINE void swap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU32 encodeIndices(PxU8 a, PxU8 b) { return 0x3f800000u | b<<8 | a;}
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU8 aIndex(PxU32 indices) { return indices&0xff; }
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU8 bIndex(PxU32 indices) { return (indices>>8)&0xff; }
struct CachedVertex
{
PxVec3 v;
PxU32 indices;
PX_FORCE_INLINE PX_CUDA_CALLABLE CachedVertex() {}
PX_FORCE_INLINE PX_CUDA_CALLABLE CachedVertex(PxU8 iA, PxU8 iB, const PxVec3& iV): v(iV), indices(encodeIndices(iA,iB)) {}
PX_FORCE_INLINE PX_CUDA_CALLABLE CachedVertex(const CachedVertex& other): v(other.v), indices(other.indices) {}
PX_FORCE_INLINE PX_CUDA_CALLABLE void operator=(const CachedVertex& other) { v = other.v, indices = other.indices; }
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU8 a() const { return aIndex(indices); }
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU8 b() const { return bIndex(indices); }
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU8 a() const volatile { return aIndex(indices); }
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU8 b() const volatile { return bIndex(indices); }
PX_FORCE_INLINE PX_CUDA_CALLABLE PxVec3 getV() const volatile { return PxVec3(v.x, v.y, v.z); }
};
struct GjkCachedData
{
CachedVertex vertices[4];
struct
{
PxVec3 n;
PxReal d;
} normals[4];
PxU32 size;
PX_FORCE_INLINE PX_CUDA_CALLABLE GjkCachedData(){}
__device__ void Reset() { size = 0; __syncwarp(); }
};
struct GjkResult
{
enum Enum
{
eDISTANT,
eCLOSE,
eOVERLAP
};
};
struct GjkOutput
{
PxVec3 direction; // unit witness for lower bound
PxReal lowerBound; // provable lower bound
PxReal upperBound; // provable upper bound
PxVec3 closestPointA; // witnesses for upper bound
PxVec3 closestPointB;
bool degenerate;
PxVec3 closestPointDir;
};
PX_CUDA_CALLABLE PX_FORCE_INLINE void barycentrics(const PxVec3& a, const PxVec3& b, const PxVec3& c, float &u, float &v, float &w, const PxVec3& p)
{
PxVec3 m = (b - a).cross(c - a), ma = m.abs(), a1 = (b-p).cross(c-p), a2 = (c-p).cross(a-p);
PxReal d;
// area ratios in plane with largest normal component
if (ma.x >= ma.y && ma.x >= ma.z)
d = 1.0f/m.x, u = a1.x * d, v = a2.x * d;
else if (ma.y >= ma.z)
d = 1.0f/m.y, u = a1.y * d, v = a2.y * d;
else
d = 1.0f/m.z, u = a1.z * d, v = a2.z * d;
w = 1.0f - u - v;
}
// top-level functions
// unit-level functions for testing
static const PxU32 EPA_MAX_VERTS = 18, EPA_MAX_FACES = 2*EPA_MAX_VERTS-4; // for N verts, we'll have 2(N-2) faces.
typedef int EPABitMap;
#define MAKE_Vec3I8(A, B, C) (physx::PxU32(A) | (physx::PxU32(B) << 8) | (physx::PxU32(C) << 16))
struct Vec3I8
{
PxU32 a;
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU8 get(PxU32 i) const { return (a >> (i << 3)) & 0xFFul; }
PX_FORCE_INLINE PX_CUDA_CALLABLE void set(PxU32 i, PxU8 v) { a = (a & ~(0xFFul << (i << 3))) | (PxU32(v) << (i << 3)); }
PX_FORCE_INLINE PX_CUDA_CALLABLE void setInt(int i) { a = i; }
PX_FORCE_INLINE PX_CUDA_CALLABLE int getInt() { return a; }
PX_FORCE_INLINE PX_CUDA_CALLABLE const Vec3I8& operator=(const Vec3I8& other) {a = other.a; return *this;}
bool operator==(const Vec3I8& other) { return (a & 0xFFffFFul) == (other.a & 0xFFffFFul); }
};
struct EPATriangle
{
PxVec3 normal; // unit normal
PxReal distance; // *plane* distance from origin
Vec3I8 v; // vertices
};
struct EPAHullData
{
PxVec3 v[EPA_MAX_VERTS];
PxU32 i[EPA_MAX_VERTS];
EPATriangle t[EPA_MAX_FACES];
Vec3I8 a[EPA_MAX_FACES];
PxU8 nbVertices;
EPABitMap liveMap;
};
// GJK routine.
//
// Input:
// convexA, convexB: two convexes in the same space
// initialDir: an unnormalized start direction for GJK iteration
// minSep: the minimum distance at which the two objects are judged to be separated. Must be positive.
// convergenceRatio: minimum ratio of lowerBound/upperBound for convergence (a number close to, but less than, 1)
//
// returns DISTANT if a lower bound on distance is found that is > minSep
// OVERLAP if the objects are provably overlapping
// else CLOSE.
//
// for OVERLAP, the cachedData (vertex indices & search directions) can be passed to EPA
// for DISTANT, a direction is generated which provides a witness for the lower bound
// for CLOSE, a pair of closest points is generated, which provide (in MS space) a witness for the upper bound, and
// if nondegenerate, also a direction which witnesses the lower bound
//
// the degenerate flag is raised in the output if the algorithm encountered geometric instability while the minSep value is in [lower, upper].
// In particular, we are not overlapping (lower>minSep) nor overlapping (upper == 0), so this can only accompany a result of CLOSE.
// geometric instability can only happen very close to convergence, so unless very high tolerances are necessary, convergence can be assumed.
// in this case if the lower bound is zero, then the the lower bound witness direction is not generated.
// So when CLOSE is returned, the upper bound should be used as the authoritative distance, and the direction should be taken from the closest points
// EPA routine.
//
// Input:
// convexA, convexB: two convexes in the same space
// cache: a cache of initial vertices produced by GJK. Must have size at least 2
// convergenceRatio: minimum ratio of lowerBound/upperBound for convergence (a number close to, but less than, 1)
//
// on output, the following are emitted:
// * a pair of closest points which are the best depenetration found in the allowed space
// * a lower bound and upper bound on penetration depth.
// * a direction corresponding to the lower bound (this direction *opposes* closestB - closestA), so if we translate object B by lowerBound * direction, we
// should approximately separate the shapes
//
// the degenerate flag is raised in the output if the algorithm encountered geometric instability before convergence, or ran out of space.
// in this case, the bounds, direction and closest points are still generated.
//
// The algorithm returns GjkResult::eOVERLAP in almost all cases. However, it's possible for EPA to find separation even if GJK found penetration,
// and in this anomalous case it returns GjkResult::eCLOSE
//
// // There is currently no direction for the upper bound, which would allow for reliable (if not minimal) separation in degenerate cases
}
#endif

View File

@@ -0,0 +1,87 @@
// 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 __TRI32DATA_H__
#define __TRI32DATA_H__
struct Triangle32Data
{
PxU32 v[3];
Triangle32Data() {}
Triangle32Data(PxU32 v0,PxU32 v1,PxU32 v2)
{
v[0]=v0;
v[1]=v1;
v[2]=v2;
}
};
struct Triangle32DataPad
{
PxU32 v[3];
PxU32 pad;
PX_CUDA_CALLABLE Triangle32DataPad() {}
PX_CUDA_CALLABLE Triangle32DataPad(PxU32 v0, PxU32 v1, PxU32 v2, PxU32 v3)
{
v[0] = v0;
v[1] = v1;
v[2] = v2;
pad = v3;
}
PX_CUDA_CALLABLE Triangle32DataPad(PxU32 v0, PxU32 v1, PxU32 v2)
{
v[0] = v0;
v[1] = v1;
v[2] = v2;
pad = 0;
}
PX_CUDA_CALLABLE Triangle32DataPad(Triangle32Data t)
{
v[0] = t.v[0];
v[1] = t.v[1];
v[2] = t.v[2];
pad = 0;
}
PX_CUDA_CALLABLE Triangle32DataPad(Triangle32Data t, PxU32 ipad = 0)
{
v[0] = t.v[0];
v[1] = t.v[1];
v[2] = t.v[2];
pad = ipad;
}
};
#endif

View File

@@ -0,0 +1,62 @@
// 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 __TYPEHELPERS_H__
#define __TYPEHELPERS_H__
PX_CUDA_CALLABLE static inline PxVec3 float4ToVec3(const float4 & data)
{
return PxVec3(data.x, data.y, data.z);
}
PX_CUDA_CALLABLE static inline float4 vec3ToFloat4(const PxVec3 & data)
{
return make_float4(data.x, data.y, data.z, 0.0f);
}
PX_CUDA_CALLABLE static inline PxQuat float4ToQuat(const float4 & data)
{
return PxQuat(data.x, data.y, data.z, data.w);
}
PX_CUDA_CALLABLE static inline float4 quatToFloat4(const PxQuat & data)
{
return make_float4(data.x, data.y, data.z, data.w);
}
PX_CUDA_CALLABLE static inline void transformToFloat4s(float4 & pos, float4 & rot, const PxTransform & transform)
{
pos = make_float4(transform.p.x, transform.p.y, transform.p.z, 0.0f);
rot = make_float4(transform.q.x, transform.q.y, transform.q.z, transform.q.w);
}
PX_CUDA_CALLABLE static inline void float4sToTransform(PxTransform & transform, const float4 & pos, const float4 & rot)
{
transform.p = PxVec3(pos.x, pos.y, pos.z);
transform.q = PxQuat(rot.x, rot.y, rot.z, rot.w);
}
#endif