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,200 @@
// 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_ALGORITHMS_H
#define PXG_ALGORITHMS_H
#include "foundation/PxSimpleTypes.h"
#include "PxgAlgorithmsData.h"
#include "PxgKernelLauncher.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
class PxgKernelLauncher;
/**
\brief Performs a sort operation on the GPU
*/
template<typename T>
class PxGpuRadixSort
{
protected:
PxgKernelLauncher* mKernelLauncher;
PxU32 mTempBufferSize;
PxInt4x4* mTempBlockSumsGpuPtr;
PxInt4x4* mTempBlockSumScanGpuPtr;
PxInt4x4* mTotalSum;
PxU32 mNumThreadsPerBlock = 0;
PxU32 mNumElements = 0;
T* mReorderBuffer;
PxU16* mOffsetBuffer;
//Optional, reorder buffer when sorting key-value pairs, uses lazy initialization
PxU32* mValueReorderBuffer;
public:
/**
\brief Empty constructor which allows creating uninitialized objects
*/
PxGpuRadixSort() : mTempBlockSumsGpuPtr(NULL), mTempBlockSumScanGpuPtr(NULL), mTotalSum(NULL), mValueReorderBuffer(NULL) {}
/**
\brief Constructor that initializes and allocates all internal data
\param[in] cudaContextManager The cuda context manager
\param[in] numElements The maximum number of elements that can be processed by this gpu sort instance
\param[in] numThreadsPerBlock The number of threads applied per block when scheduling the gpu work
*/
PxGpuRadixSort(PxgKernelLauncher* cudaContextManager, PxU32 numElements, PxU32 numThreadsPerBlock = 512);
/**
\brief Initializes and allocates all internal data
\param[in] cudaContextManager The cuda context manager
\param[in] numElements The maximum number of elements that can be processed by this gpu sort instance
\param[in] numThreadsPerBlock The number of threads applied per block when scheduling the gpu work
*/
virtual bool initialize(PxgKernelLauncher* cudaContextManager, PxU32 numElements, PxU32 numThreadsPerBlock = 512);
/**
\brief Sorts the integer array in place
\param[in,out] inAndOutBuffer Gpu array with the integer data which gets sorted
\param[in] numBitsToSort The number of bits to sort. For 32bit integers where it is known that only 24 bits are used at most, it is sufficient to sort 24 bits only.
\param[in] stream Gpu stream on which the calculation is scheduled. To be sure that the sort finished, a synchronize call must be executed on that stream.
\param[in] outReorderTrackingBuffer Optional: Gpu tracking buffer that contains the original location in the unsorted array for every element after the sorting completed.
\param[in] numElementsToSort Optional: The number of elements that should get sorted. By default all elements are processed. The maximal number of elements is specified in the constructor.
*/
virtual void sort(T* inAndOutBuffer, PxU32 numBitsToSort, const CUstream& stream, PxU32* outReorderTrackingBuffer = NULL, PxU32 numElementsToSort = 0xFFFFFFFF);
/**
\brief Releases all internal data
*/
virtual bool release();
virtual ~PxGpuRadixSort() { }
};
/**
\brief Performs a scan operation (exclusive or inclusive cumulative sum) on the GPU
*/
class PxGpuScan
{
private:
PxU32 mTempBufferSize;
PxU32* mTempBlockSumsGpuPtr;
PxU32* mTempBlockSumScanGpuPtr;
PxU32* mTotalSum;
PxU32 mNumThreadsPerBlock = 0;
PxU32 mNumElements = 0;
PxgKernelLauncher* mKernelLauncher;
void scan(PxU32* inAndOutBuf, PxU32 exclusiveScan, const CUstream& stream, PxU32 numElementsToScan);
void sumOnly(PxU32* inBuf, const CUstream& stream, PxU32 numElementsToScan);
public:
/**
\brief Empty constructor which allows creating uninitialized objects
*/
PxGpuScan() : mTempBlockSumsGpuPtr(NULL), mTempBlockSumScanGpuPtr(NULL), mTotalSum(NULL) {}
/**
\brief Constructor that initializes and allocates all internal data
\param[in] cudaContextManager The cuda context manager
\param[in] numElements The maximum number of elements that can be processed by this gpu scan instance
\param[in] numThreadsPerBlock The number of threads applied per block when scheduling the gpu work
*/
PxGpuScan(PxgKernelLauncher* cudaContextManager, PxU32 numElements, PxU32 numThreadsPerBlock = 512);
/**
\brief Initializes and allocates all internal data
\param[in] cudaContextManager The cuda context manager
\param[in] numElements The maximum number of elements that can be processed by this gpu scan instance
\param[in] numThreadsPerBlock The number of threads applied per block when scheduling the gpu work
*/
bool initialize(PxgKernelLauncher* cudaContextManager, PxU32 numElements, PxU32 numThreadsPerBlock = 512);
/**
\brief Allows to access to total sum of all elements that took part in the scan operation
\return A gpu pointer to the total sum. Only contains valid data after a scan operation finished.
*/
PX_FORCE_INLINE PxU32* getSumPointer()
{
return mTotalSum;
}
/**
\brief Performs an exclusive scan in place on the given array
\param[in,out] inAndOutBuf Gpu array with the integer data which gets transformed into its exclusive cumulative sum
\param[in] stream Gpu stream on which the calculation is scheduled. To be sure that the scan finished, a synchronize call must be executed on that stream.
\param[in] numElementsToScan Optional: The number of elements that should get scanned. By default all elements are processed. The maximal number of elements is specified in the constructor.
*/
PX_FORCE_INLINE void exclusiveScan(PxU32* inAndOutBuf, const CUstream& stream, PxU32 numElementsToScan = 0xFFFFFFFF)
{
const PxU32 exclusiveScan = 1;
scan(inAndOutBuf, exclusiveScan, stream, numElementsToScan);
}
/**
\brief Performs an inclusive scan in place on the given array
\param[in,out] inAndOutBuf Gpu array with the integer data which gets transformed into its inclusive cumulative sum
\param[in] stream Gpu stream on which the calculation is scheduled. To be sure that the scan finished, a synchronize call must be executed on that stream.
\param[in] numElementsToScan The number of elements that should get scanned. By default all elements are processed. The maximal number of elements is specified in the constructor.
*/
PX_FORCE_INLINE void inclusiveScan(PxU32* inAndOutBuf, const CUstream& stream, PxU32 numElementsToScan = 0xFFFFFFFF)
{
const PxU32 exclusiveScan = 0;
scan(inAndOutBuf, exclusiveScan, stream, numElementsToScan);
}
/**
\brief Releases all internal data
*/
bool release();
~PxGpuScan() { }
};
#if !PX_DOXYGEN
} // namespace physx
#endif
#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_ALGORITHMS_DATA_H
#define PXG_ALGORITHMS_DATA_H
#include "foundation/PxSimpleTypes.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
/**
\brief An integer vector with 4 components
*/
PX_ALIGN_PREFIX(16) struct PxInt4
{
PxI32 x;
PxI32 y;
PxI32 z;
PxI32 w;
/**
\brief Comparison operator to check if two instances are equal
*/
bool operator==(const PxInt4& rhs) const
{
return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w;
}
}PX_ALIGN_SUFFIX(16);
/**
\brief An bundle of four integer vectors with 4 components each
*/
PX_ALIGN_PREFIX(16) struct PxInt4x4
{
PxInt4 data[4];
}PX_ALIGN_SUFFIX(16);
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,135 @@
// 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_ANISOTROPY_H
#define PXG_ANISOTROPY_H
#include "PxAnisotropy.h"
#include "PxgAnisotropyData.h"
#include "foundation/PxUserAllocated.h"
#include "PxgKernelLauncher.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
#if PX_SUPPORT_GPU_PHYSX
class PxgAnisotropyGenerator : public PxAnisotropyGenerator, public PxUserAllocated
{
PxgKernelLauncher mKernelLauncher;
PxAnisotropyData mAnisotropyDataHost;
PxAnisotropyData* mAnisotropyDataPerParticleSystemDevice;
PxU32 mNumParticles;
bool mDirty;
bool mOwnsAnisotropyGPUBuffers;
PxVec4* mAnisotropy1;
PxVec4* mAnisotropy2;
PxVec4* mAnisotropy3;
bool mEnabled;
void releaseGPUAnisotropyBuffers();
void allocateGPUAnisotropyBuffers();
public:
PxgAnisotropyGenerator(PxgKernelLauncher& cudaContextManager, PxU32 maxNumParticles, PxReal anisotropyScale, PxReal minAnisotropy, PxReal maxAnisotropy);
virtual ~PxgAnisotropyGenerator() { }
virtual void setAnisotropyMax(float maxAnisotropy)
{
mAnisotropyDataHost.mAnisotropyMax = maxAnisotropy;
mDirty = true;
}
virtual void setAnisotropyMin(float minAnisotropy)
{
mAnisotropyDataHost.mAnisotropyMin = minAnisotropy;
mDirty = true;
}
virtual void setAnisotropyScale(float anisotropyScale)
{
mAnisotropyDataHost.mAnisotropy = anisotropyScale;
mDirty = true;
}
virtual void release();
virtual void setResultBufferHost(PxVec4* anisotropy1, PxVec4* anisotropy2, PxVec4* anisotropy3);
virtual void setResultBufferDevice(PxVec4* anisotropy1, PxVec4* anisotropy2, PxVec4* anisotropy3);
virtual void generateAnisotropy(PxGpuParticleSystem* gpuParticleSystem, PxU32 numParticles, CUstream stream);
virtual void generateAnisotropy(PxVec4* particlePositionsGpu, PxParticleNeighborhoodProvider& neighborhoodProvider, PxU32 numParticles, PxReal particleContactOffset, CUstream stream);
virtual PxU32 getMaxParticles() const
{
return mNumParticles;
}
virtual void setMaxParticles(PxU32 maxParticles);
virtual PxVec4* getAnisotropy1DevicePointer() const
{
return mAnisotropyDataHost.mAnisotropy_q1;
}
virtual PxVec4* getAnisotropy2DevicePointer() const
{
return mAnisotropyDataHost.mAnisotropy_q2;
}
virtual PxVec4* getAnisotropy3DevicePointer() const
{
return mAnisotropyDataHost.mAnisotropy_q3;
}
virtual void setEnabled(bool enabled)
{
mEnabled = enabled;
}
virtual bool isEnabled() const
{
return mEnabled;
}
};
#endif
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,68 @@
// 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 PX_ANISOTROPY_DATA_H
#define PX_ANISOTROPY_DATA_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec4.h"
#if !PX_DOXYGEN
namespace physx
{
/**
\brief Data and settings to apply smoothing to an array of particle positions
*/
struct PxSmoothedPositionData
{
PxVec4* mPositions; //!< The gpu array with the positions
PxReal mSmoothing; //!< The strength of the smoothing
};
/**
\brief Data and settings to compute anisotropy information for an array of particle positions
*/
struct PxAnisotropyData
{
PxVec4* mAnisotropy_q1; //!< Gpu array containing the first direction (x, y, z) and magnitude (w) of the anisotropy
PxVec4* mAnisotropy_q2; //!< Gpu array containing the second direction (x, y, z) and magnitude (w) of the anisotropy
PxVec4* mAnisotropy_q3; //!< Gpu array containing the third direction (x, y, z) and magnitude (w) of the anisotropy
PxReal mAnisotropy; //!< Anisotropy scaling factor
PxReal mAnisotropyMin; //!< Lower anisotropy bound
PxReal mAnisotropyMax; //!< Upper anisotropy bound
PxU32 mPadding;
};
#endif
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,65 @@
// 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_ARRAY_CONVERTER_H
#define PXG_ARRAY_CONVERTER_H
#include "PxArrayConverter.h"
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec4.h"
#include "PxgKernelLauncher.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
#if PX_SUPPORT_GPU_PHYSX
class PxgArrayConverter : public PxArrayConverter, public PxUserAllocated
{
private:
PxgKernelLauncher mKernelLauncher;
public:
PxgArrayConverter(PxgKernelLauncher& kernelLauncher);
virtual ~PxgArrayConverter() { }
virtual void interleaveGpuBuffers(const PxVec4* vertices, const PxVec4* normals, PxU32 length, PxVec3* interleavedResultBuffer, CUstream stream) PX_OVERRIDE;
};
#endif
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,976 @@
// 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_ARTICULATION_H
#define PXG_ARTICULATION_H
#include "foundation/PxSimpleTypes.h"
#include "PxArticulationReducedCoordinate.h"
#include "PxgArticulationLink.h"
#include "PxgArticulationTendon.h"
#include "PxgCudaBuffer.h"
#include "PxSpatialMatrix.h"
#include "DyFeatherstoneArticulation.h"
#include "foundation/PxUserAllocated.h"
#include "vector_types.h"
namespace physx
{
class PxGpuSpatialTendonData;
class PxGpuFixedTendonData;
namespace Dy
{
struct ArticulationJointCore;
class ArticulationJointCoreData;
struct ArticulationInternalConstraint;
struct SpatialSubspaceMatrix;
}
//We load/store to Cm::SpatialMatrix rather than PxSpatialMatrix.
//This exploits the symmetry of the spatial matrix to avoid storing/loading the bottom-right,
//which is the transpose of the top-left
struct PxgSpatialMatrixBlock
{
float4 columns[7][32];
};
//We load/store to a PxSpatialMatrix. This has a full 6x6 matrix as there is no
//symmetry as described in the above struct
struct PxgSpatialMatrix6x6Block
{
float4 columns[9][32];
};
struct PxgMat33Block
{
float4 mCol0[32];
float4 mCol1[32];
float mCol2[32];
};
struct PxgSpatialVectorBlock
{
float4 mTopxyz_bx[32];
float2 mbyz[32];
};
struct PxgSpatialTransformBlock
{
float4 q[32];
float4 p[32];
};
PX_FORCE_INLINE PX_CUDA_CALLABLE void loadSpatialMatrix(const PxgSpatialMatrixBlock& block, const PxU32 threadIndexInWarp, Dy::SpatialMatrix& mat)
{
float4 val = block.columns[0][threadIndexInWarp];
mat.topLeft[0][0] = val.x; mat.topLeft[0][1] = val.y; mat.topLeft[0][2] = val.z; mat.topLeft[1][0] = val.w;
val = block.columns[1][threadIndexInWarp];
mat.topLeft[1][1] = val.x; mat.topLeft[1][2] = val.y; mat.topLeft[2][0] = val.z; mat.topLeft[2][1] = val.w;
val = block.columns[2][threadIndexInWarp];
mat.topLeft[2][2] = val.x; mat.topRight[0][0] = val.y; mat.topRight[0][1] = val.z; mat.topRight[0][2] = val.w;
val = block.columns[3][threadIndexInWarp];
mat.topRight[1][0] = val.x; mat.topRight[1][1] = val.y; mat.topRight[1][2] = val.z; mat.topRight[2][0] = val.w;
val = block.columns[4][threadIndexInWarp];
mat.topRight[2][1] = val.x; mat.topRight[2][2] = val.y; mat.bottomLeft[0][0] = val.z; mat.bottomLeft[0][1] = val.w;
val = block.columns[5][threadIndexInWarp];
mat.bottomLeft[0][2] = val.x; mat.bottomLeft[1][0] = val.y; mat.bottomLeft[1][1] = val.z; mat.bottomLeft[1][2] = val.w;
val = block.columns[6][threadIndexInWarp];
mat.bottomLeft[2][0] = val.x; mat.bottomLeft[2][1] = val.y; mat.bottomLeft[2][2] = val.z;
}
//This loads a 7-vec matrix in which the bottomRight is equal to the transpose of the top left
PX_FORCE_INLINE PX_CUDA_CALLABLE void loadSpatialMatrix(const PxgSpatialMatrixBlock& block, const PxU32 threadIndexInWarp, PxSpatialMatrix& mat)
{
float4 val = block.columns[0][threadIndexInWarp];
mat.column[0][0] = val.x; mat.column[0][1] = val.y; mat.column[0][2] = val.z; mat.column[1][0] = val.w;
mat.column[3][3] = val.x; mat.column[4][3] = val.y; mat.column[5][3] = val.z; mat.column[3][4] = val.w;
val = block.columns[1][threadIndexInWarp];
mat.column[1][1] = val.x; mat.column[1][2] = val.y; mat.column[2][0] = val.z; mat.column[2][1] = val.w;
mat.column[4][4] = val.x; mat.column[5][4] = val.y; mat.column[3][5] = val.z; mat.column[4][5] = val.w;
val = block.columns[2][threadIndexInWarp];
mat.column[2][2] = val.x; mat.column[0][3] = val.y; mat.column[0][4] = val.z; mat.column[0][5] = val.w;
mat.column[5][5] = val.x;
val = block.columns[3][threadIndexInWarp];
mat.column[1][3] = val.x; mat.column[1][4] = val.y; mat.column[1][5] = val.z; mat.column[2][3] = val.w;
val = block.columns[4][threadIndexInWarp];
mat.column[2][4] = val.x; mat.column[2][5] = val.y; mat.column[3][0] = val.z; mat.column[3][1] = val.w;
val = block.columns[5][threadIndexInWarp];
mat.column[3][2] = val.x; mat.column[4][0] = val.y; mat.column[4][1] = val.z; mat.column[4][2] = val.w;
val = block.columns[6][threadIndexInWarp];
mat.column[5][0] = val.x; mat.column[5][1] = val.y; mat.column[5][2] = val.z;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE void storeSpatialMatrix(PxgSpatialMatrixBlock& block, const PxU32 threadIndexInWarp, const Dy::SpatialMatrix& mat)
{
block.columns[0][threadIndexInWarp] = make_float4(mat.topLeft[0][0], mat.topLeft[0][1], mat.topLeft[0][2], mat.topLeft[1][0]);
block.columns[1][threadIndexInWarp] = make_float4(mat.topLeft[1][1], mat.topLeft[1][2], mat.topLeft[2][0], mat.topLeft[2][1]);
block.columns[2][threadIndexInWarp] = make_float4(mat.topLeft[2][2], mat.topRight[0][0], mat.topRight[0][1], mat.topRight[0][2]);
block.columns[3][threadIndexInWarp] = make_float4(mat.topRight[1][0], mat.topRight[1][1], mat.topRight[1][2], mat.topRight[2][0]);
block.columns[4][threadIndexInWarp] = make_float4(mat.topRight[2][1], mat.topRight[2][2], mat.bottomLeft[0][0], mat.bottomLeft[0][1]);
block.columns[5][threadIndexInWarp] = make_float4(mat.bottomLeft[0][2], mat.bottomLeft[1][0], mat.bottomLeft[1][1], mat.bottomLeft[1][2]);
block.columns[6][threadIndexInWarp] = make_float4(mat.bottomLeft[2][0], mat.bottomLeft[2][1], mat.bottomLeft[2][2], 0.f);
}
PX_FORCE_INLINE PX_CUDA_CALLABLE void loadSpatialMatrix(const PxgSpatialMatrix6x6Block& block, const PxU32 threadIndexInWarp, PxSpatialMatrix& mat)
{
float4 val = block.columns[0][threadIndexInWarp];
mat.column[0][0] = val.x; mat.column[0][1] = val.y; mat.column[0][2] = val.z; mat.column[0][3] = val.w;
val = block.columns[1][threadIndexInWarp];
mat.column[0][4] = val.x; mat.column[0][5] = val.y; mat.column[1][0] = val.z; mat.column[1][1] = val.w;
val = block.columns[2][threadIndexInWarp];
mat.column[1][2] = val.x; mat.column[1][3] = val.y; mat.column[1][4] = val.z; mat.column[1][5] = val.w;
val = block.columns[3][threadIndexInWarp];
mat.column[2][0] = val.x; mat.column[2][1] = val.y; mat.column[2][2] = val.z; mat.column[2][3] = val.w;
val = block.columns[4][threadIndexInWarp];
mat.column[2][4] = val.x; mat.column[2][5] = val.y; mat.column[3][0] = val.z; mat.column[3][1] = val.w;
val = block.columns[5][threadIndexInWarp];
mat.column[3][2] = val.x; mat.column[3][3] = val.y; mat.column[3][4] = val.z; mat.column[3][5] = val.w;
val = block.columns[6][threadIndexInWarp];
mat.column[4][0] = val.x; mat.column[4][1] = val.y; mat.column[4][2] = val.z; mat.column[4][3] = val.w;
val = block.columns[7][threadIndexInWarp];
mat.column[4][4] = val.x; mat.column[4][5] = val.y; mat.column[5][0] = val.z; mat.column[5][1] = val.w;
val = block.columns[8][threadIndexInWarp];
mat.column[5][2] = val.x; mat.column[5][3] = val.y; mat.column[5][4] = val.z; mat.column[5][5] = val.w;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE void storeSpatialMatrix(PxgSpatialMatrix6x6Block& block, const PxU32 threadIndexInWarp, const PxSpatialMatrix& mat)
{
block.columns[0][threadIndexInWarp] = make_float4(mat.column[0][0], mat.column[0][1], mat.column[0][2], mat.column[0][3]);
block.columns[1][threadIndexInWarp] = make_float4(mat.column[0][4], mat.column[0][5], mat.column[1][0], mat.column[1][1]);
block.columns[2][threadIndexInWarp] = make_float4(mat.column[1][2], mat.column[1][3], mat.column[1][4], mat.column[1][5]);
block.columns[3][threadIndexInWarp] = make_float4(mat.column[2][0], mat.column[2][1], mat.column[2][2], mat.column[2][3]);
block.columns[4][threadIndexInWarp] = make_float4(mat.column[2][4], mat.column[2][5], mat.column[3][0], mat.column[3][1]);
block.columns[5][threadIndexInWarp] = make_float4(mat.column[3][2], mat.column[3][3], mat.column[3][4], mat.column[3][5]);
block.columns[6][threadIndexInWarp] = make_float4(mat.column[4][0], mat.column[4][1], mat.column[4][2], mat.column[4][3]);
block.columns[7][threadIndexInWarp] = make_float4(mat.column[4][4], mat.column[4][5], mat.column[5][0], mat.column[5][1]);
block.columns[8][threadIndexInWarp] = make_float4(mat.column[5][2], mat.column[5][3], mat.column[5][4], mat.column[5][5]);
}
PX_FORCE_INLINE PX_CUDA_CALLABLE void zeroSpatialMatrix(PxgSpatialMatrix6x6Block& block, const PxU32 threadIndexInWarp)
{
block.columns[0][threadIndexInWarp] = make_float4(0.f, 0.f, 0.f, 0.f);
block.columns[1][threadIndexInWarp] = make_float4(0.f, 0.f, 0.f, 0.f);
block.columns[2][threadIndexInWarp] = make_float4(0.f, 0.f, 0.f, 0.f);
block.columns[3][threadIndexInWarp] = make_float4(0.f, 0.f, 0.f, 0.f);
block.columns[4][threadIndexInWarp] = make_float4(0.f, 0.f, 0.f, 0.f);
block.columns[5][threadIndexInWarp] = make_float4(0.f, 0.f, 0.f, 0.f);
block.columns[6][threadIndexInWarp] = make_float4(0.f, 0.f, 0.f, 0.f);
block.columns[7][threadIndexInWarp] = make_float4(0.f, 0.f, 0.f, 0.f);
block.columns[8][threadIndexInWarp] = make_float4(0.f, 0.f, 0.f, 0.f);
}
PX_FORCE_INLINE PX_CUDA_CALLABLE Cm::SpatialVectorF loadSpatialVectorF(const PxgSpatialVectorBlock& block, const PxU32 threadIndexInWarp)
{
float4 top = block.mTopxyz_bx[threadIndexInWarp];
float2 bottom = block.mbyz[threadIndexInWarp];
return Cm::SpatialVectorF(PxVec3(top.x, top.y, top.z), PxVec3(top.w, bottom.x, bottom.y));
}
PX_FORCE_INLINE PX_CUDA_CALLABLE Cm::UnAlignedSpatialVector loadSpatialVector(const PxgSpatialVectorBlock& block, const PxU32 threadIndexInWarp)
{
float4 top = block.mTopxyz_bx[threadIndexInWarp];
float2 bottom = block.mbyz[threadIndexInWarp];
return Cm::UnAlignedSpatialVector(PxVec3(top.x, top.y, top.z), PxVec3(top.w, bottom.x, bottom.y));
}
PX_FORCE_INLINE PX_CUDA_CALLABLE void storeSpatialVector(PxgSpatialVectorBlock& block, const Cm::UnAlignedSpatialVector& v, const PxU32 threadIndexInWarp)
{
block.mTopxyz_bx[threadIndexInWarp] = make_float4(v.top.x, v.top.y, v.top.z, v.bottom.x);
block.mbyz[threadIndexInWarp] = make_float2(v.bottom.y, v.bottom.z);
/*Pxstcg(&block.mTopxyz_bx[threadIndexInWarp], make_float4(v.top.x, v.top.y, v.top.z, v.bottom.x));
Pxstcg(&block.mbyz[threadIndexInWarp], make_float2(v.bottom.y, v.bottom.z));*/
}
PX_FORCE_INLINE PX_CUDA_CALLABLE void addSpatialVector(PxgSpatialVectorBlock& block, const Cm::UnAlignedSpatialVector& v, const PxU32 threadIndexInWarp)
{
block.mTopxyz_bx[threadIndexInWarp] += make_float4(v.top.x, v.top.y, v.top.z, v.bottom.x);
block.mbyz[threadIndexInWarp] += make_float2(v.bottom.y, v.bottom.z);
/*Pxstcg(&block.mTopxyz_bx[threadIndexInWarp], make_float4(v.top.x, v.top.y, v.top.z, v.bottom.x));
Pxstcg(&block.mbyz[threadIndexInWarp], make_float2(v.bottom.y, v.bottom.z));*/
}
#if PX_CUDA_COMPILER
PX_FORCE_INLINE __device__ void atomicAddSpatialVector(PxgSpatialVectorBlock& block, const Cm::UnAlignedSpatialVector& v, const PxU32 threadIndexInWarp)
{
#if __CUDA_ARCH__ >= 200
atomicAdd(&block.mTopxyz_bx[threadIndexInWarp].x, v.top.x);
atomicAdd(&block.mTopxyz_bx[threadIndexInWarp].y, v.top.y);
atomicAdd(&block.mTopxyz_bx[threadIndexInWarp].z, v.top.z);
atomicAdd(&block.mTopxyz_bx[threadIndexInWarp].w, v.bottom.x);
atomicAdd(&block.mbyz[threadIndexInWarp].x, v.bottom.y);
atomicAdd(&block.mbyz[threadIndexInWarp].y, v.bottom.z);
#else
PX_UNUSED(block);
PX_UNUSED(v);
PX_UNUSED(threadIndexInWarp);
#endif
/*Pxstcg(&block.mTopxyz_bx[threadIndexInWarp], make_float4(v.top.x, v.top.y, v.top.z, v.bottom.x));
Pxstcg(&block.mbyz[threadIndexInWarp], make_float2(v.bottom.y, v.bottom.z));*/
}
#endif
PX_FORCE_INLINE PX_CUDA_CALLABLE PxTransform loadSpatialTransform(const PxgSpatialTransformBlock& block, const PxU32 threadIndexInWarp)
{
const float4 q = block.q[threadIndexInWarp];
const float4 p = block.p[threadIndexInWarp];
return PxTransform(PxVec3(p.x, p.y, p.z), PxQuat(q.x, q.y, q.z, q.w));
}
PX_FORCE_INLINE PX_CUDA_CALLABLE void storeSpatialTransform(PxgSpatialTransformBlock& block, const PxU32 threadIndexInWarp, const PxTransform& transform)
{
block.q[threadIndexInWarp] = make_float4(transform.q.x, transform.q.y, transform.q.z, transform.q.w);
block.p[threadIndexInWarp] = make_float4(transform.p.x, transform.p.y, transform.p.z, 0.f);
}
PX_FORCE_INLINE PX_CUDA_CALLABLE PxQuat loadQuat(const float4* f, const PxU32 threadIndexInWarp)
{
float4 q = f[threadIndexInWarp];
return PxQuat(q.x, q.y, q.z, q.w);
}
PX_FORCE_INLINE PX_CUDA_CALLABLE PxVec3 loadPxVec3(const float4* f, const PxU32 threadIndexInWarp)
{
float4 v = f[threadIndexInWarp];
return PxVec3(v.x, v.y, v.z);
}
PX_FORCE_INLINE PX_CUDA_CALLABLE void loadPxMat33(const PxgMat33Block& block, const PxU32 threadIndexInWarp, PxMat33& mat)
{
float4 v0 = block.mCol0[threadIndexInWarp];
float4 v1 = block.mCol1[threadIndexInWarp];
float v2 = block.mCol2[threadIndexInWarp];
mat.column0.x = v0.x; mat.column0.y = v0.y; mat.column0.z = v0.z;
mat.column1.x = v0.w; mat.column1.y = v1.x; mat.column1.z = v1.y;
mat.column2.x = v1.z; mat.column2.y = v1.w; mat.column2.z = v2;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE void storePxMat33(PxgMat33Block& block, const PxU32 threadIndexInWarp, const PxMat33& mat)
{
block.mCol0[threadIndexInWarp] = make_float4(mat.column0.x, mat.column0.y, mat.column0.z, mat.column1.x);
block.mCol1[threadIndexInWarp] = make_float4(mat.column1.y, mat.column1.z, mat.column2.x, mat.column2.y);
block.mCol2[threadIndexInWarp] = mat.column2.z;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE Cm::UnAlignedSpatialVector loadSpatialVector(const Cm::UnAlignedSpatialVector* PX_RESTRICT vector)
{
size_t ptr = size_t(vector);
if (ptr & 0xf)
{
float2* top = reinterpret_cast<float2*>(ptr);
float2 val = *top;
float4 val2 = *(reinterpret_cast<float4*>(top+1));
return Cm::UnAlignedSpatialVector(PxVec3(val.x, val.y, val2.x), PxVec3(val2.y, val2.z, val2.w));
}
else
{
float4* top = reinterpret_cast<float4*>(ptr);
float4 val = *top;
float2 val2 = *(reinterpret_cast<float2*>(top + 1));
return Cm::UnAlignedSpatialVector(PxVec3(val.x, val.y, val.z), PxVec3(val.w, val2.x, val2.y));
}
}
PX_FORCE_INLINE PX_CUDA_CALLABLE void storeSpatialVector(Cm::UnAlignedSpatialVector* PX_RESTRICT vector,
const Cm::UnAlignedSpatialVector& src)
{
size_t ptr = size_t(vector);
if (ptr & 0xf)
{
float2* top = reinterpret_cast<float2*>(ptr);
float4* bottom = (reinterpret_cast<float4*>(top + 1));
*top = make_float2(src.top.x, src.top.y);
*bottom = make_float4(src.top.z, src.bottom.x, src.bottom.y, src.bottom.z);
}
else
{
float4* top = reinterpret_cast<float4*>(ptr);
float2* bottom = (reinterpret_cast<float2*>(top + 1));
*top = make_float4(src.top.x, src.top.y, src.top.z, src.bottom.x);
*bottom = make_float2(src.bottom.y, src.bottom.z);
}
}
struct PxgArticulationBitFieldStackData
{
PxU64 bitField[32];
};
typedef PxgArticulationBitFieldStackData PxgArticulationBitFieldData;
struct PxgArticulationTraversalStackData
{
PxU32 indices[32];
PxgSpatialVectorBlock impulseStack;
PxgSpatialVectorBlock deltaVStack;
};
struct PxgArticulationBlockLinkData
{
PxgSpatialMatrixBlock mSpatialArticulatedInertia;
PxgSpatialMatrix6x6Block mSpatialResponseMatrix;
PxgMat33Block mIsolatedInertia;
PxReal mMass[32];
//KS - these are questionable - we might want to store velocity/deltaVelocity etc. in a non-SOA format
//for the constraint solver. To be revisited later!!!!
PxgSpatialVectorBlock mMotionVelocity;
PxgSpatialVectorBlock mPosMotionVelocity;
PxgSpatialVectorBlock mDeltaMotion;
PxgSpatialVectorBlock mScratchImpulse; // These are non-propagated impulses. They may persist between kernels and are properly processed and then reset in averageLinkImpulsesAndPropagate. Should be reset to zero after propagation.
PxgSpatialVectorBlock mScratchDeltaV; // Temp! Used only for propagating velocities around the tree structure within a kernel! Left in an undefined state after use.
PxgSpatialVectorBlock mSolverSpatialDeltaVel;
PxgSpatialVectorBlock mSolverSpatialImpulse;
PxgSpatialVectorBlock mSolverSpatialInternalConstraintImpulse;
PxgSpatialVectorBlock mZAVector;
PxgSpatialVectorBlock mZAIntVector;
PxgSpatialVectorBlock mCoriolis;
PxgSpatialVectorBlock mConstraintForces;
PxgSpatialVectorBlock mMotionAcceleration;
PxgSpatialVectorBlock mMotionAccelerationInternal;
PxgSpatialVectorBlock mBiasForce;
PxReal mDeltaScale[32];
float mRw_x[32];
float mRw_y[32];
float mRw_z[32];
float4 mRelativeQuat[32];
PxU32 mNbStaticContacts[32];
PxU32 mStaticContactStartIndex[32];
PxU32 mNbStaticJoints[32];
PxU32 mStaticJointStartIndex[32];
PxgSpatialTransformBlock mPreTransform;
PxgSpatialTransformBlock mAccumulatedPose;
PxgSpatialTransformBlock mChildPose;
PxgSpatialTransformBlock mParentPose;
float4 mDeltaQ[32];
float4 mLinDampingX_AngDampingY_maxLinVelSqZ_maxAngVelSqW[32];
float4 mInvInertiaXYZ_invMassW[32];
PxReal mCfm[32];
PxU32 mChildrenOffset[32];
PxU32 mNumChildren[32];
PxU32 mJointOffset[32];
PxU32 mParents[32];
PxU8 mDofs[32];
PxU8 mJointType[32];
PxU8 mInvDofIds[6][32]; //mapping from axis to joint offset
PxU8 mDisableGravity[32];
PxU8 mRetainsAcceleration[32];
// PT: padded to 128 for coalesced loads
PxU32 pad[16];
};
PX_COMPILE_TIME_ASSERT((sizeof(PxgArticulationBlockLinkData) & 127)==0);
struct PxgArticulationBlockSpatialTendonData
{
public:
PxU32 mNumAttachments[32];
PxU32 mNumConstraints[32];
PxReal mStiffness[32];
PxReal mDamping[32];
PxReal mLimitStiffness[32];
PxReal mOffset[32];
};
struct PxgArticulationBlockFixedTendonData
{
public:
PxU32 mNumTendonJoints[32];
PxU32 mNumConstraints[32];
PxReal mStiffness[32];
PxReal mDamping[32];
PxReal mLimitStiffness[32];
PxReal mOffset[32];
PxReal mLowLimit[32];
PxReal mHighLimit[32];
PxReal mRestLength[32];
};
struct PxgArtiStateDirtyFlag
{
enum
{
eVEL_DIRTY = 1 << 0,
eHAS_IMPULSES = 1 << 1
};
};
//This class stores a block of data corresponding to 32 articulations.
//It is filled in at runtime.
struct PxgArticulationBlockData
{
PxgSpatialMatrixBlock mInvSpatialArticulatedInertia;
PxU32 mFlags[32]; // PT: seems to be mainly for PxArticulationFlag::eFIX_BASE so only 1 bit is needed? Merge with mNumLinks?
PxU32 mNumLinks[32];
PxU32 mNumSpatialTendons[32];
PxU32 mNumFixedTendons[32];
PxU32 mNumMimicJoints[32];
PxU32 mTotalDofs[32];
PxU32 mArticulationIndex[32];
PxReal mSleepThreshold[32];
//This one is a bit of a hack - it's the common link velocity.
PxgSpatialVectorBlock mCommonLinkDeltaVelocity;
PxU32 mLinkWithDeferredImpulse[32];
Cm::UnAlignedSpatialVector* mMotionVelocitiesPtr[32];
PxgSpatialVectorBlock mRootDeferredZ;
float4 mCOM_TotalInvMassW[32];
PxU8 mStateDirty[32]; //32 bytes
PxU32 mTotalSelfConstraintCount; //4 bytes
PxU32 mSelfConstraintOffset; //4 bytes
// PT: padded to 128 for coalesced loads
PxU32 pad[22]; //88 bytes padding, bringing this all up to 128 bytes
};
PX_COMPILE_TIME_ASSERT((sizeof(PxgArticulationBlockData) & 127)==0);
struct PxgArticulationInternalConstraintData
{
PxgSpatialVectorBlock mRow0;
PxgSpatialVectorBlock mRow1;
PxgSpatialVectorBlock mDeltaVA;
PxgSpatialVectorBlock mDeltaVB;
PxReal mRecipResponse[32];
PxReal mResponse[32];
float2 mLimits_LowLimitX_highLimitY[32];
float2 mLimitError_LowX_highY[32];
PxReal mHighImpulse[32];
PxReal mLowImpulse[32];
PxReal mMaxJointVelocity[32];
// drive
PxReal mDriveImpulse[32];
PxReal mConstraintMaxImpulse[32];
PxReal mMaxForce[32];
PxU32 mDriveType[32];
PxReal mMaxEffort[32];
PxReal mMaxActuatorVelocity[32];
PxReal mVelocityDependentResistance[32];
PxReal mSpeedEffortGradient[32];
PxReal mDriveTargetPos[32];
PxReal mArmature[32];
float4 mTargetVelPlusInitialBiasX_DriveBiasCoefficientY_VelMultiplierZ_ImpulseMultiplierW[32];
float mDriveStiffness[32];
float mDamping[32];
float mDriveTargetVel[32];
float mTargetPosBias[32];
PxReal mAccumulatedFrictionImpulse[32];
//old friction
PxReal mMaxFrictionForce[32];
PxReal mFrictionCoefficient[32];
//new friction
PxReal mStaticFrictionEffort[32];
PxReal mDynamicFrictionEffort[32];
PxReal mViscousFrictionCoefficient[32];
PX_FORCE_INLINE void PX_CUDA_CALLABLE setImplicitDriveDesc
(const PxU32 threadIndexInWarp,const Dy::ArticulationImplicitDriveDesc& driveDesc)
{
mTargetVelPlusInitialBiasX_DriveBiasCoefficientY_VelMultiplierZ_ImpulseMultiplierW[threadIndexInWarp] =
make_float4(driveDesc.driveTargetVelPlusInitialBias, driveDesc.driveBiasCoefficient, driveDesc.driveVelMultiplier, driveDesc.driveImpulseMultiplier);
mTargetPosBias[threadIndexInWarp] = driveDesc.driveTargetPosBias;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE Dy::ArticulationImplicitDriveDesc getImplicitDriveDesc(const PxU32 threadIndexInWarp) const
{
const Dy::ArticulationImplicitDriveDesc driveDesc
(
mTargetVelPlusInitialBiasX_DriveBiasCoefficientY_VelMultiplierZ_ImpulseMultiplierW[threadIndexInWarp].x,
mTargetVelPlusInitialBiasX_DriveBiasCoefficientY_VelMultiplierZ_ImpulseMultiplierW[threadIndexInWarp].y,
mTargetVelPlusInitialBiasX_DriveBiasCoefficientY_VelMultiplierZ_ImpulseMultiplierW[threadIndexInWarp].z,
mTargetVelPlusInitialBiasX_DriveBiasCoefficientY_VelMultiplierZ_ImpulseMultiplierW[threadIndexInWarp].w,
mTargetPosBias[threadIndexInWarp]
);
return driveDesc;
}
};
PX_COMPILE_TIME_ASSERT((sizeof(PxgArticulationInternalConstraintData) & 127)==0);
struct PxgArticulationInternalTendonConstraintData
{
PxgSpatialVectorBlock mRow0;
PxgSpatialVectorBlock mRow1;
PxgSpatialVectorBlock mDeltaVB;
PxReal mRecipResponse[32];
PxReal mAccumulatedLength[32];
PxReal mBiasCoefficient[32];
PxReal mVelMultiplier[32];
PxReal mImpulseMultiplier[32];
PxReal mAppliedForce[32];
PxReal mLimitBiasCoefficient[32];
PxReal mLimitImpulseMultiplier[32];
PxReal mLimitAppliedForce[32];
PxU32 mLink0[32];
PxU32 mLink1[32];
PxReal mDeltaVA[32];
PxReal mRestDistance[32];
PxReal mLowLimit[32];
PxReal mHighLimit[32];
};
struct PxgArticulationBlockDofData
{
PxReal mJointPositions[32];
PxReal mJointVelocities[32];
PxReal mJointUnconstrainedVelocities[32];
PxReal mPosJointVelocities[32];
PxReal mJointAccel[32];
PxReal mQstZ[32];
PxReal mQstZIcInternal[32];
PxReal mDeferredQstZ[32];
PxReal mTmpQstZ[32];
PxgSpatialVectorBlock mWorldMotionMatrix;
PxgSpatialVectorBlock mLocalMotionMatrix;
PxgSpatialVectorBlock mIsInvDW;
PxgSpatialVectorBlock mIsW;
PxgSpatialVectorBlock mJointAxis;
float mInvStIsT_x[32];
float mInvStIsT_y[32];
float mInvStIsT_z[32];
PxU8 mDofIds[32]; //mapping from joint offset to axis
PxU8 mMotion[32];
PxgArticulationInternalConstraintData mConstraintData;
// PT: padded to 128 for coalesced loads
PxU32 pad[16];
};
PX_COMPILE_TIME_ASSERT((sizeof(PxgArticulationBlockDofData) & 127)==0);
struct PxgArticulationBlockAttachmentData
{
public:
PxVec3 mRelativeOffset[32];
PxReal mRestDistance[32];
PxReal mCoefficient[32];
PxU64 mChildrens[32];
PxU16 mLinkIndex[32];
PxU32 mParents[32];
PxReal mLowLimit[32];
PxReal mHighLimit[32];
};
struct PxgArticulationBlockTendonJointData
{
public:
PxU32 mAxis[32];
PxReal mCoefficient[32];
PxReal mRecipCoefficient[32];
PxU64 mChildrens[32];
PxU16 mLinkIndex[32];
PxU32 mParents[32];
PxU32 mConstraintId[32];
};
struct PxgArticulationBlockInternallMimicJointData
{
PxU32 mDofA[32];
PxU32 mDofB[32];
//Cache recip effectiveInertia = [J * M^-1 * J^T] = [rAA + gearRatio*(rAB + rBA) + gearRatio*gearRatio*rBB]
//Impulse = [1, gearRatio]^T * [-b + J*v] /[J * M^-1 * J^T + cfm]
//Impulse = [1, gearRatio]^T * [-b + J*v] / [recipEffectiveInertia + cfm];
PxReal recipEffectiveInertia[32];
};
struct PxgArticulationBlockMimicJointData
{
PxU32 mLinkA[32];
PxU32 mAxisA[32];
PxU32 mLinkB[32];
PxU32 mAxisB[32];
PxReal mGearRatio[32];
PxReal mOffset[32];
PxReal mNaturalFrequency[32];
PxReal mDampingRatio[32];
PxgArticulationBlockInternallMimicJointData mInternalData;
};
struct PxgArticulationData
{
// index in the articulation buffer. This is the same as articulationRemapId in the PxgBodySim
PxU32 index;
PxU32 bodySimIndex;
PxU32 gpuDirtyFlag;
PxU32 updateDirty;
PxU16 numLinks;
PxU16 numJointDofs;
PxU16 numSpatialTendons;
PxU16 numFixedTendons;
PxU16 numMimicJoints;
PxU8 flags;
bool confiDirty;
PxU32 numPathToRoots;
};
#if PX_VC
#pragma warning(push)
#pragma warning(disable:4324)
#endif
PX_ALIGN_PREFIX(16)
class PxgArticulation
{
public:
PxgArticulationData data;
PxgArticulationLink* links;
Dy::ArticulationJointCore* joints;
Dy::ArticulationJointCoreData* jointData;
Cm::UnAlignedSpatialVector* motionVelocities;
Cm::UnAlignedSpatialVector* motionAccelerations;
Cm::UnAlignedSpatialVector* linkIncomingJointForces;
Cm::UnAlignedSpatialVector* corioliseVectors;
Cm::UnAlignedSpatialVector* zAForces; // used as temporary propagation buffer in inverseDynamics and to store TGS per substep isolated forces while the solver runs. Not cleared after use.
Cm::UnAlignedSpatialVector* externalAccelerations;
Cm::UnAlignedSpatialVector* rootPreMotionVelocity;
PxReal* jointPositions;
PxReal* jointVelocities;
PxReal* jointAccelerations;
PxReal* jointForce;
PxReal* jointTargetPositions;
PxReal* jointTargetVelocities;
PxU32* jointOffsets;
PxSpatialMatrix* worldSpatialArticulatedInertia;
PxSpatialMatrix* spatialResponseMatrixW;
PxTransform* linkBody2Worlds;
PxU8* linkJointRootStateDataBuffer;
PxTransform* linkBody2Actors;
PxU32* parents;
//Local space motion matrix - constant unless properties are changed
Dy::SpatialSubspaceMatrix* motionMatrix;
//World space motion matrix - computed from local matrix each frame
Dy::SpatialSubspaceMatrix* worldMotionMatrix; // AD: only inverse dynamics now.
Cm::UnAlignedSpatialVector* jointAxis;
PxReal* linkWakeCounters;
PxgArticulationLinkSleepData* linkSleepData;
PxgArticulationLinkProp* linkProps;
ArticulationBitField* children;
PxU32* pathToRoot;
PxQuat* relativeQuat;
PxQuat* tempParentToChilds;
PxVec3* tempRs;
PxGpuSpatialTendonData* spatialTendonParams;
PxgArticulationTendon* spatialTendons;
PxGpuFixedTendonData* fixedTendonParams;
PxgArticulationTendon* fixedTendons;
PxReal* cfms;
PxReal* cfmScale;
Dy::ArticulationMimicJointCore* mimicJointCores;
PX_ALIGN(16, PxSpatialMatrix) invSpatialArticulatedInertiaW;
Dy::ErrorAccumulator internalResidualAccumulator; //Internal residual means no errors introduces by contacts or non-articulation joints connected to this instance will be included
Dy::ErrorAccumulator contactResidualAccumulator;
}
PX_ALIGN_SUFFIX(16);
#if PX_VC
#pragma warning(pop)
#endif
/*
\brief We aggregate link, joint, and root link state data into a single char buffer.
We do this in two ways:
a) a single buffer for each articulation
b) a single buffer for all articulations
The typical pattern of data flow is as follows:
a) we store state data in a unique device buffer for each articulation.
b) we copy from the individual device buffers per articulation to the single device buffer for all articulations.
c) we copy the single buffer for all articulations from device to host
d) we distribute state data from the single host buffer on the host to the individual articulation instances on the host.
The state data that we store is as follows:
a) link body2Worlds array, link velocities array, link accelerations array, link incoming joint forces array
b) joint positions array, joint velocities array, joint accelerations array
d) root link pre-sim velocity
The struct PxgLinkJointRootStateData contains helper functions for allocating and querying
state data buffers.
*/
struct PxgArticulationLinkJointRootStateData
{/**
\brief Compute the number of bytes required for an articulation with known
maximum link count and known maximum dof count.
\param[in] maxNbLinks is the maximum number of links of any articulation in the ensemble of articulations.
\param[in] maxNbDofs is the maximum number of dofs of any articulation in the ensemble of articulations.
\note This does not return an aligned size, use computeStateDataBufferByteSizeAligned16 for that purpose
\return The number of bytes required to store the state data for an articulation.
*/
static PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 computeSingleArticulationStateDataBufferByteSizeRaw
(const PxU32 maxNbLinks, const PxU32 maxNbDofs)
{
PxU32 byteSizePerArt =
(sizeof(PxTransform) + 3 * sizeof(Cm::UnAlignedSpatialVector)) * maxNbLinks; //link pose + link velocity + link acceleration + link incoming joint force
byteSizePerArt += sizeof(PxReal) * maxNbDofs; //joint pos
byteSizePerArt += sizeof(PxReal) * maxNbDofs; //joint vel
byteSizePerArt += sizeof(PxReal) * maxNbDofs; //joint accel
byteSizePerArt += sizeof(Cm::UnAlignedSpatialVector); //root pre-sim vel
return byteSizePerArt;
}
/**
\brief Compute the number of bytes required for an ensemble of articulations with known
maximum link count and known maximum dof count.
\param[in] maxNbLinks is the maximum number of links of any articulation in the ensemble of articulations.
\param[in] maxNbDofs is the maximum number of dofs of any articulation in the ensemble of articulations.
\param[in] nbArticulations is the number of articulations in the ensemble.
\note This may be used to compute the number of bytes required for a single articulation by setting
nbArticulations to 1 and setting maxNbLinks etc to be the link and dof count of that articulation.
\return The number of bytes required to store the state data for an ensemble of articulations.
*/
static PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 computeStateDataBufferByteSizeAligned16
(const PxU32 maxNbLinks, const PxU32 maxNbDofs, const PxU32 nbArticulations)
{
const PxU32 byteSizePerArt = computeSingleArticulationStateDataBufferByteSizeRaw(maxNbLinks, maxNbDofs);
const PxU32 byteSize16PerArt = ((byteSizePerArt + 15) & ~15); //align the size upwards to the next 16-byte boundary
return (byteSize16PerArt * nbArticulations);
}
/**
\brief Return the pointer to a single articulation's state data buffer.
\param[in] inputBufferForAllArticulations is a pointer to the memory containing the state
data for the entire ensemble of articulations.
\param[in] maxNbLinks is the maximum number of links of any articulation in the ensemble of articulations.
\param[in] maxNbDofs is the maximum number of dofs of any articulation in the ensemble of articulations.
\param[in] articulationId is the index of a single articulation within the ensemble.
\return The pointer to a single articulation's state data buffer.
*/
static PX_CUDA_CALLABLE PX_FORCE_INLINE PxU8* getArticulationStateDataBuffer
(PxU8* inputBufferForAllArticulations,
const PxU32 maxNbLinks, const PxU32 maxNbDofs,
const PxU32 articulationId)
{
PxU8* singleArticulationStateBuffer =
inputBufferForAllArticulations +
computeStateDataBufferByteSizeAligned16(maxNbLinks, maxNbDofs, articulationId);
return singleArticulationStateBuffer;
}
/**
\brief Decompose the state data buffer of a single articulation into pointers to arrays of
poses, velocities etc.
\param[in] singleArticulationStateBuffer is the state data buffer for a single articulation.
\param[in] nbLinks is the number of links for the single articulation.
\param[in] nbDofs is the number of dofs for the single articulation.
\param[out] linkBody2Worlds is an array of link poses with one element per link.
\param[out] linkVels is a pointer to an array of link spatial velocities with one element per link.
\param[out] linkIncomingJointForces is a pointer to an array of link incoming joint forces with one element per link.
\param[out] jointPositions is a pointer to an array of joint positions with one element per dof.
\param[out] jointVelocities is a pointer to an array of joint velocities with one element per link.
\param[out] jointAccelerations is a pointer to an array of joint accelerations with one element per dof.
\param[out] rootPreVel is a pointer to the pre-sim velocity of the single articulation's root link.
*/
static PX_CUDA_CALLABLE PX_FORCE_INLINE void decomposeArticulationStateDataBuffer
(PxU8* singleArticulationStateBuffer,
const PxU32 nbLinks, const PxU32 nbDofs,
PxTransform*& linkBody2Worlds, Cm::UnAlignedSpatialVector*& linkVels, Cm::UnAlignedSpatialVector*& linkAccels, Cm::UnAlignedSpatialVector*& linkIncomingJointForces,
PxReal*& jointPositions, PxReal*& jointVelocities, PxReal*& jointAccelerations,
Cm::UnAlignedSpatialVector*& rootPreVel)
{
PxU8* buffer = singleArticulationStateBuffer;
linkBody2Worlds = reinterpret_cast<PxTransform*>(buffer);
buffer += sizeof(PxTransform) * nbLinks;
linkVels = reinterpret_cast<Cm::UnAlignedSpatialVector*>(buffer);
buffer += sizeof(Cm::UnAlignedSpatialVector) * nbLinks;
linkAccels = reinterpret_cast<Cm::UnAlignedSpatialVector*>(buffer);
buffer += sizeof(Cm::UnAlignedSpatialVector) * nbLinks;
linkIncomingJointForces = reinterpret_cast<Cm::UnAlignedSpatialVector*>(buffer);
buffer += sizeof(Cm::UnAlignedSpatialVector) * nbLinks;
jointPositions = reinterpret_cast<PxReal*>(buffer);
buffer += sizeof(PxReal) * nbDofs;
jointVelocities = reinterpret_cast<PxReal*>(buffer);
buffer += sizeof(PxReal) * nbDofs;
jointAccelerations = reinterpret_cast<PxReal*>(buffer);
buffer += sizeof(PxReal) * nbDofs;
rootPreVel = reinterpret_cast<Cm::UnAlignedSpatialVector*>(buffer);
PX_ASSERT(
singleArticulationStateBuffer + computeStateDataBufferByteSizeAligned16(nbLinks, nbDofs, 1) ==
reinterpret_cast<PxU8*>(((reinterpret_cast<size_t>(buffer) + sizeof(Cm::UnAlignedSpatialVector) + 15) & ~15)));
}
/**
\brief Compute the pointer to the array of link poses for a single articulation.
\param[in] singleArticulationStateBuffer is the state data buffer for a single articulation.
\param[in] nbLinks is the number of links for the single articulation.
\param[in] nbDofs is the number of dofs for the single articulation.
\return The pointer to the array of link poses for a single articulation.
*/
//Get the body2World array from the state data buffer of a single articulation.
static PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform* getArticulationBody2Worlds
(PxU8* singleArticulationStateBuffer,
const PxU32 nbLinks, const PxU32 nbDofs)
{
PxTransform* linkBody2Worlds;
Cm::UnAlignedSpatialVector* linkVels;
Cm::UnAlignedSpatialVector* linkAccels;
Cm::UnAlignedSpatialVector* linkIncomingJointForces;
PxReal* jointPositions;
PxReal* jointVelocities;
PxReal* jointAccelerations;
Cm::UnAlignedSpatialVector* rootPreVel;
decomposeArticulationStateDataBuffer(
singleArticulationStateBuffer,
nbLinks, nbDofs,
linkBody2Worlds, linkVels, linkAccels, linkIncomingJointForces,
jointPositions, jointVelocities, jointAccelerations,
rootPreVel);
return linkBody2Worlds;
}
};
class PxgArticulationBuffer : public PxUserAllocated
{
public:
PxgArticulationBuffer(PxgHeapMemoryAllocatorManager* heapMemoryManager);
~PxgArticulationBuffer();
PxgTypedCudaBuffer<PxgArticulationLink> links;
PxgTypedCudaBuffer<PxReal> linkWakeCounters; //original set to the same as articulation wakeCounter
PxgTypedCudaBuffer<PxgArticulationLinkSleepData> linkSleepData;
PxgTypedCudaBuffer<PxgArticulationLinkProp> linkProps;
PxgTypedCudaBuffer<Dy::ArticulationJointCore> joints;
PxgTypedCudaBuffer<Dy::ArticulationJointCoreData> jointData;
PxgTypedCudaBuffer<Cm::UnAlignedSpatialVector> corioliseVectors; //link coriolise vector
PxgTypedCudaBuffer<Cm::UnAlignedSpatialVector> zAForces; //link spatial zero acceleration force/ spatical articulate
PxgTypedCudaBuffer<PxU32> pathToRoots; //global array store path to root for each link in continuous. Each link should have a start index and numberOfElems
PxgTypedCudaBuffer<PxGpuSpatialTendonData> spatialTendonParams;
PxgTypedCudaBuffer<PxgArticulationTendon> spatialTendons;
PxArray<PxgCudaBuffer*> attachmentFixedData;
PxArray<PxgCudaBuffer*> attachmentModData;
PxgTypedCudaBuffer<PxGpuFixedTendonData> fixedTendonParams;
PxgTypedCudaBuffer<PxgArticulationTendon> fixedTendons;
PxArray<PxgCudaBuffer*> tendonJointFixData;
PxArray<PxgCudaBuffer*> tendonJointCoefficientData;
PxgTypedCudaBuffer<Dy::ArticulationMimicJointCore> mimicJoints;
PxgTypedCudaBuffer<Cm::UnAlignedSpatialVector> externalAccelerations;
PxgTypedCudaBuffer<PxReal> jointForce;
PxgTypedCudaBuffer<PxReal> jointTargetPositions;
PxgTypedCudaBuffer<PxReal> jointTargetVelocities;
PxgTypedCudaBuffer<PxU32> jointOffsets;
PxgTypedCudaBuffer<PxU32> parents;
PxgTypedCudaBuffer<Dy::SpatialSubspaceMatrix> motionMatrix;
PxgTypedCudaBuffer<Dy::SpatialSubspaceMatrix> motionMatrixW;
PxgTypedCudaBuffer<Cm::UnAlignedSpatialVector> jointAxis;
PxgTypedCudaBuffer<PxSpatialMatrix> spatialArticulatedInertiaW;
PxgTypedCudaBuffer<PxSpatialMatrix> spatialImpulseResponseW;
//see PxgArticulationLinkJointRootStateData
PxgCudaBuffer linkAndJointAndRootStates;
PxgTypedCudaBuffer<PxTransform> linkBody2Actors;
PxgTypedCudaBuffer<ArticulationBitField> children;
PxgTypedCudaBuffer<PxQuat> relativeQuats;
PxgTypedCudaBuffer<PxReal> cfms;
PxgTypedCudaBuffer<PxReal> cfmScale;
PxgTypedCudaBuffer<PxQuat> tempParentToChilds;
PxgTypedCudaBuffer<PxVec3> tempRs;
PxU32 linkCount;
PxgHeapMemoryAllocatorManager* mHeapMemoryManager;
};
//Helper function to compute the index of a particular link's deltaV value in the deltaV buffer.
//We store this in a particular order to try and minimize cache misses
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU32 computeDeltaVIndex(const PxU32 maxArticulations, const PxU32 maxLinks,
const PxU32 articulationID, const PxU32 linkID, const PxU32 slabID)
{
return articulationID + linkID * maxArticulations + slabID*maxArticulations*maxLinks;
}
}
#endif

View File

@@ -0,0 +1,109 @@
// 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_ARTICULATION_LINK_H
#define PXG_ARTICULATION_LINK_H
#include "foundation/PxSimpleTypes.h"
#include "PxgSolverBody.h"
#include "DyFeatherstoneArticulationUtils.h"
namespace physx
{
typedef PxU64 ArticulationBitField;
struct PxgArticulationLinkData
{
public:
Cm::UnAlignedSpatialVector IsW[3];//stI is the transpose of Is
Cm::UnAlignedSpatialVector IsInvDW[3];
//PxVec3 r; //vector from parent com to child com
//PxVec3 rw; //world space r
PxReal qstZIc[3];//jointForce - stZIc
PxReal invStIs[3][3];
};
struct PxgArticulationLink
{
#if !PX_CUDA_COMPILER
PX_ALIGN(16, PxVec3 initialAngVel); // 12 12 initial ang vel
PxReal penBiasClamp; // 4 16 the penetration bias clamp
PxVec3 initialLinVel; // 12 28 initial lin vel
PxReal invMass; // 4 32 inverse mass
#else
float4 initialAngVelXYZ_penBiasClamp;
float4 initialLinVelXYZ_invMassW;
#endif
PxReal maxAngularVelocitySq; // 4 36
PxReal maxLinearVelocitySq; // 4 40
PxReal linearDamping; // 4 44
PxReal angularDamping; // 4 48
PxU32 pathToRootOffset; // 4 52
PxU32 childrenOffset; // 4 56
PxU16 numPathToRoot; // 2 58
PxU16 numChildren; // 2 60
PxReal offsetSlop; // 4 64
ArticulationBitField pathToRoot; // 8 72 path to root, including link and root
PxReal cfmScale; // 4 76
bool disableGravity; // 1 77
bool retainsAccelerations; // 1 78
bool padding[2]; // 1 80
};
struct PxgArticulationLinkSleepData
{
#if !PX_CUDA_COMPILER
PX_ALIGN(16, PxVec3 sleepLinVelAcc); //12 12
PxReal padding0; //4 16
PX_ALIGN(16, PxVec3 sleepAngVelAcc); //12 28
PxReal padding1; //4 32
#else
float4 sleepLinVelAccXYZ;
float4 sleepAngVelAccXYZ;
#endif
};
struct PxgArticulationLinkProp
{
#if !PX_CUDA_COMPILER
PX_ALIGN(16, PxVec3 invInertia); //12 12
PxReal invMass; //4 16
#else
float4 invInertiaXYZ_invMass;
#endif
};
}
#endif

View File

@@ -0,0 +1,57 @@
// 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_ARTICULATION_TENDON_H
#define PXG_ARTICULATION_TENDON_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec3.h"
namespace physx
{
class PxgArticulationTendonElementFixedData
{
public:
PxU64 children; //my children index //8 8
PxU32 parent; //parent index //4 12
PxU32 linkInd; //articulation link index //4 16
};
class PxgArticulationTendon
{
public:
void* mFixedElements; //element fix in the initialization
void* mModElements; //element can be modified in run time
PxU32 mNbElements;
};
}//namespace physx
#endif

View File

@@ -0,0 +1,122 @@
// 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_BVH_H
#define PXG_BVH_H
#include "foundation/PxVec3.h"
#include "GuSDF.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
#if PX_SUPPORT_GPU_PHYSX
PX_ALIGN_PREFIX(16)
struct PxgPackedNodeHalf
{
PxReal x;
PxReal y;
PxReal z;
PxU32 i : 31;
PxU32 b : 1;
PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 getXYZ()
{
return PxVec3(x, y, z);
}
}
PX_ALIGN_SUFFIX(16);
PX_ALIGN_PREFIX(16)
struct PxgBVH
{
// for bottom up tree construction the root node does not appear in slot 0
// this is a single int CUDA alloc that holds the index of the root
PxU32* mRootNode;
PxgPackedNodeHalf* mNodeLowers; // stores the lower spatial bound of the node's children, left child stored in i, leaf flag stored in b
PxgPackedNodeHalf* mNodeUppers; // stores the upper spatial bound of the node's children, right child stored in i, flag is unused
PxU32 mNumNodes;
PxU32 mMaxNodes;
PxgBVH() : mRootNode(NULL), mNodeLowers(NULL), mNodeUppers(NULL), mNumNodes(0), mMaxNodes(0)
{}
}
PX_ALIGN_SUFFIX(16);
PX_ALIGN_PREFIX(16)
struct PxgBvhTriangleMesh
{
PxgBVH mBvh;
PxVec3* mVertices;
PxU32* mTriangles;
PxU32 mNumTriangles;
PxU32 mNumVertices;
PxU32 mPad[2];
PxgBvhTriangleMesh() : mBvh(), mVertices(NULL), mTriangles(NULL), mNumTriangles(0), mNumVertices(0)
{}
}
PX_ALIGN_SUFFIX(16);
PX_ALIGN_PREFIX(16)
struct PxgWindingClusterApproximation
{
public:
PxVec3 mCentroidTimesArea;
PxReal mRadius;
PxVec3 mWeightedNormalSum;
PxReal mAreaSum;
PX_CUDA_CALLABLE PxgWindingClusterApproximation() : mCentroidTimesArea(PxVec3(0.0f)), mRadius(0.0f), mWeightedNormalSum(PxVec3(0.0f)), mAreaSum(0.0f)
{}
}
PX_ALIGN_SUFFIX(16);
struct PxgBVHKernelBlockDim
{
enum
{
BUILD_HIERARCHY = 256,
BUILD_SDF = 256,
SDF_FIX_HOLES = 256
};
};
#endif
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,78 @@
// 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_BODYSIM_H
#define PXG_BODYSIM_H
#include "AlignedTransform.h"
namespace physx
{
struct PxgBodySim
{
float4 linearVelocityXYZ_inverseMassW; //16 16
float4 angularVelocityXYZ_maxPenBiasW; //32 16
float4 maxLinearVelocitySqX_maxAngularVelocitySqY_linearDampingZ_angularDampingW; //48 16
float4 inverseInertiaXYZ_contactReportThresholdW; //64 16
float4 sleepLinVelAccXYZ_freezeCountW; //80 16
float4 sleepAngVelAccXYZ_accelScaleW; //96 16
float4 freezeThresholdX_wakeCounterY_sleepThresholdZ_bodySimIndex; //112 16
PxAlignedTransform body2World; //144 32
PxAlignedTransform body2Actor_maxImpulseW; //176 32
PxU32 articulationRemapId; //180 4
PxU32 internalFlags; //184 4
PxU16 lockFlags; //186 2
PxU16 disableGravity; //188 2
PxReal offsetSlop; //192 4
float4 externalLinearAcceleration; //208 16
float4 externalAngularAcceleration; //224 16
};
struct PxgBodySimVelocities
{
float4 linearVelocity;
float4 angularVelocity;
};
struct PxgBodySimVelocityUpdate
{
float4 linearVelocityXYZ_bodySimIndexW;
float4 angularVelocityXYZ_maxPenBiasW;
float4 externalLinearAccelerationXYZ;
float4 externalAngularAccelerationXYZ;
};
}//physx
#endif

View File

@@ -0,0 +1,270 @@
// 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_BODYSIM_MANAGER_H
#define PXG_BODYSIM_MANAGER_H
#include "foundation/PxBitMap.h"
#include "foundation/PxPinnedArray.h"
#include "PxgCudaMemoryAllocator.h"
#include "PxNodeIndex.h"
#include "PxgBodySim.h"
#include "CmIDPool.h"
#include "CmBlockArray.h"
#include "foundation/PxHashMap.h"
namespace physx
{
class PxsRigidBody;
struct PxsExternalAccelerationProvider;
namespace IG
{
class NodeIndex;
}
namespace Dy
{
class FeatherstoneArticulation;
class DeformableSurface;
class DeformableVolume;
class ParticleSystem;
}
struct PxgRemapIndices
{
public:
PxU32 nodeIndex; //this is the index to PxgBodySim in GPU
PxU32 remapIndex; //this is the index map between PxgBodySim and the PxgArticulation in GPU
};
struct PxgArticulationUpdate
{
PxU32 articulationIndex; //Which articulation on GPU
Dy::FeatherstoneArticulation* articulation; //Which articulation on CPU
};
struct PxgArticulationIndices : public PxgRemapIndices {};
struct PxgSoftBodyIndices : public PxgRemapIndices {};
struct PxgFEMClothIndices : public PxgRemapIndices {};
struct PxgParticleSystemIndices : public PxgRemapIndices {};
struct PxgStaticConstraint
{
PxU32 uniqueId;
PxU32 linkID;
};
struct PxgSelfConstraint
{
PxU32 uniqueId;
PxU32 linkID0;
PxU32 linkID1;
};
struct PxgStaticConstraints
{
static const PxU32 MaxConstraints = 16;
PxArray<PxgStaticConstraint> mStaticContacts;
PxArray<PxgStaticConstraint> mStaticJoints;
};
struct PxgArticulationSelfConstraints
{
static const PxU32 MaxConstraints = 32;
PxArray<PxgSelfConstraint> mSelfContacts;
PxArray<PxgSelfConstraint> mSelfJoints;
};
class PxgBodySimManager
{
PX_NOCOPY(PxgBodySimManager)
public:
PxgBodySimManager(const PxVirtualAllocator& allocator) : mNewUpdatedBodies(allocator),
mTotalNumBodies(0), mNbUpdatedBodies(0),
mTotalNumArticulations(0), mTotalNumSoftBodies(0), mTotalNumFEMCloths(0),
mTotalNumPBDParticleSystems(0),
mActivePBDParticleSystems(allocator),
mActivePBDParticleSystemsDirty(false),
mActiveSoftbodies(allocator),
mActiveSelfCollisionSoftbodies(allocator),
mActiveSoftbodiesDirty(false),
mActiveFEMCloths(allocator),
mActiveFEMClothsDirty(false),
mTotalStaticArticContacts(0),
mTotalStaticArticJoints(0),
mTotalSelfArticContacts(0),
mTotalSelfArticJoints(0),
mMaxStaticArticContacts(0),
mMaxStaticArticJoints(0),
mMaxSelfArticContacts(0),
mMaxSelfArticJoints(0),
mTotalStaticRBContacts(0),
mTotalStaticRBJoints(0),
mMaxStaticRBContacts(0),
mMaxStaticRBJoints(0),
mExternalAccelerations(NULL)
{
}
~PxgBodySimManager();
void addBody(PxsRigidBody* bodyCore, const PxU32 nodeIndex);
void addArticulation(Dy::FeatherstoneArticulation* articulation, const PxU32 nodeIndex, bool OmniPVDRecordDirectGPUAPI);
void releaseArticulation(Dy::FeatherstoneArticulation* articulation, const PxU32 nodeIndex);
void releaseDeferredArticulationIds();
void addSoftBody(Dy::DeformableVolume* deformableVolume, const PxU32 nodeIndex);
void releaseSoftBody(Dy::DeformableVolume* deformableVolume);
void releaseDeferredSoftBodyIds();
bool activateSoftbody(Dy::DeformableVolume* deformableVolume);
bool deactivateSoftbody(Dy::DeformableVolume* deformableVolume);
bool activateSoftbodySelfCollision(Dy::DeformableVolume* deformableVolume);
bool deactivateSoftbodySelfCollision(Dy::DeformableVolume* deformableVolume);
void addFEMCloth(Dy::DeformableSurface*, const PxU32 nodeIndex);
void releaseFEMCloth(Dy::DeformableSurface*);
void releaseDeferredFEMClothIds();
bool activateCloth(Dy::DeformableSurface*);
bool deactivateCloth(Dy::DeformableSurface*);
void addPBDParticleSystem(Dy::ParticleSystem* particleSystem, const PxU32 nodeIndex);
void releasePBDParticleSystem(Dy::ParticleSystem* particleSystem);
void releaseDeferredPBDParticleSystemIds();
void updateBodies(PxsRigidBody** rigidBodies, PxU32* nodeIndices, const PxU32 nbBodies, PxsExternalAccelerationProvider* externalAccelerations);
void updateBody(const PxNodeIndex&);
void destroy();
void updateArticulation(Dy::FeatherstoneArticulation* articulation, const PxU32 nodeIndex);
void reset();
void reserve(const PxU32 nbBodies);
bool addStaticArticulationContactManager(PxU32 uniqueIndex, const PxNodeIndex nodeIndex);
bool removeStaticArticulationContactManager(PxU32 uniqueIndex, const PxNodeIndex nodeIndex);
bool addStaticArticulationJoint(PxU32 uniqueIndex, const PxNodeIndex nodeIndex);
bool removeStaticArticulationJoint(PxU32 uniqueIndex, const PxNodeIndex nodeIndex);
bool addSelfArticulationContactManager(PxU32 uniqueIndex, const PxNodeIndex nodeIndex0, const PxNodeIndex nodeIndex1);
bool removeSelfArticulationContactManager(PxU32 uniqueIndex, const PxNodeIndex nodeIndex0, const PxNodeIndex nodeIndex1);
bool addSelfArticulationJoint(PxU32 uniqueIndex, const PxNodeIndex nodeIndex0, const PxNodeIndex nodeIndex1);
bool removeSelfArticulationJoint(PxU32 uniqueIndex, const PxNodeIndex nodeIndex0, const PxNodeIndex nodeIndex1);
bool addStaticRBContactManager(PxU32 uniqueIndex, const PxNodeIndex nodeIndex);
bool removeStaticRBContactManager(PxU32 uniqueIndex, const PxNodeIndex nodeIndex);
bool addStaticRBJoint(PxU32 uniqueIndex, const PxNodeIndex nodeIndex);
bool removeStaticRBJoint(PxU32 uniqueIndex, const PxNodeIndex nodeIndex);
PX_INLINE PxU32 getArticulationRemapIndex(PxU32 nodeIndex) { return mNodeToRemapMap.find(nodeIndex)->second;}
PX_INLINE PxU32 getNumActiveParticleSystem()
{
return mActivePBDParticleSystems.size();
}
PxArray<PxgArticulationUpdate> mUpdatedArticulations;
PxArray<void*> mBodies; //rigid bodies, articulations, soft bodies and particle systems
PxArray<PxU32> mNewOrUpdatedBodySims;
PxArray<PxgArticulationIndices> mNewArticulationSims;
PxArray<PxgSoftBodyIndices> mNewSoftBodySims;
PxArray<PxgFEMClothIndices> mNewFEMClothSims;
PxArray<Dy::DeformableSurface*> mDeformableSurfaces;
PxArray<Dy::DeformableVolume*> mDeformableVolumes;
PxArray<PxgParticleSystemIndices> mNewPBDParticleSystemSims;
Cm::DeferredIDPool mArticulationIdPool; //generate the remap id between pxgbodysim and pxgarticulation
Cm::DeferredIDPool mSoftBodyIdPool; //generate the remap id between pxgbodysim and pxgsoftbody
Cm::DeferredIDPool mFEMClothIdPool; //generate the remap id between pxgbodysim and pxgfemcloth
Cm::DeferredIDPool mPBDParticleSystemIdPool; //generate the remap id between pxgbodysim and pxgparticlesystem
PxPinnedArray<PxgBodySimVelocityUpdate> mNewUpdatedBodies;
PxU32 mTotalNumBodies; //include rigid body and articulation
PxU32 mNbUpdatedBodies; //this is used for multiply threads in the ScBeforeSolverTask to update body information
PxBitMap mUpdatedMap;
PxU32 mTotalNumArticulations;
PxU32 mTotalNumSoftBodies;
PxU32 mTotalNumFEMCloths;
PxU32 mTotalNumPBDParticleSystems;
PxArray<PxU32> mActiveFEMClothIndex;
PxArray<PxU32> mActiveSoftbodyIndex;
PxArray<PxU32> mActiveSelfCollisionSoftbodyIndex;
PxInt32ArrayPinned mActivePBDParticleSystems;
bool mActivePBDParticleSystemsDirty;
PxInt32ArrayPinned mActiveSoftbodies;
PxInt32ArrayPinned mActiveSelfCollisionSoftbodies;
PxArray<PxU32> mActiveSoftbodiesStaging;
PxArray<PxU32> mActiveSelfCollisionSoftBodiesStaging;
bool mActiveSoftbodiesDirty;
PxInt32ArrayPinned mActiveFEMCloths;
PxArray<PxU32> mActiveFEMClothStaging;
bool mActiveFEMClothsDirty;
PxHashMap<PxU32, PxU32> mNodeToRemapMap;
#if PX_SUPPORT_OMNI_PVD
PxHashMap<PxU32, PxU32> mRemapToNodeMap;
#endif
PxArray<PxU32> mDeferredFreeNodeIDs;
Cm::BlockArray<PxgStaticConstraints, 1024> mStaticConstraints;
Cm::BlockArray<PxgArticulationSelfConstraints, 1024> mArticulationSelfConstraints;
PxU32 mTotalStaticArticContacts;
PxU32 mTotalStaticArticJoints;
PxU32 mTotalSelfArticContacts;
PxU32 mTotalSelfArticJoints;
PxU32 mMaxStaticArticContacts;
PxU32 mMaxStaticArticJoints;
PxU32 mMaxSelfArticContacts;
PxU32 mMaxSelfArticJoints;
PxU32 mTotalStaticRBContacts;
PxU32 mTotalStaticRBJoints;
PxU32 mMaxStaticRBContacts;
PxU32 mMaxStaticRBJoints;
PxsExternalAccelerationProvider* mExternalAccelerations;
};
}
#endif

View File

@@ -0,0 +1,84 @@
// 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_CONSTRAINT_ID_MAP_H
#define PXG_CONSTRAINT_ID_MAP_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxAssert.h"
#if PX_CUDA_COMPILER
#include "assert.h"
#endif
namespace physx
{
// maps the constraint/joint ID to the internal joint data ID. This is used for direct GPU API
// operations to use the same constraint/joint ID on the public interface level as long as the
// constraint/joint stays in the same scene. In particular, changing actors of a constraint/joint
// should be transparent to users and can be achieved using this map.
class PxgConstraintIdMapEntry
{
public:
static const PxU32 eINVALID_ID = 0xffffFFFF;
PX_CUDA_CALLABLE PX_FORCE_INLINE PxgConstraintIdMapEntry()
: mJointDataId(eINVALID_ID)
{
}
PX_CUDA_CALLABLE PX_FORCE_INLINE void invalidate()
{
mJointDataId = eINVALID_ID;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE void setJointDataId(PxU32 jointDataId)
{
#if PX_CUDA_COMPILER
assert(jointDataId < eINVALID_ID); // until PX_ASSERT works on GPU (see PX-4133)
#else
PX_ASSERT(jointDataId < eINVALID_ID);
#endif
mJointDataId = jointDataId;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getJointDataId() const
{
return mJointDataId;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE bool isJointDataIdValid() const { return (mJointDataId != eINVALID_ID); }
private:
// maps the constraint/joint ID to the internal GPU joint data ID. eINVALID_ID is used if the
// joint/constraint is unmapped/removed or inactive.
PxU32 mJointDataId;
};
}
#endif // PXG_CONSTRAINT_ID_MAP_H

View File

@@ -0,0 +1,75 @@
// 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_DEFORMABLE_SKINNING_H
#define PXG_DEFORMABLE_SKINNING_H
#include "PxDeformableSkinning.h"
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec4.h"
#include "PxgKernelLauncher.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
#if PX_SUPPORT_GPU_PHYSX
class PxgDeformableSkinning : public PxDeformableSkinning, public PxUserAllocated
{
private:
PxgKernelLauncher mKernelLauncher;
public:
PxgDeformableSkinning(PxgKernelLauncher& kernelLauncher);
virtual ~PxgDeformableSkinning() { }
virtual void computeNormalVectors(
PxTrimeshSkinningGpuData* skinningDataArrayD, PxU32 arrayLength,
CUstream stream, PxU32 numGpuThreads) PX_OVERRIDE;
virtual void evaluateVerticesEmbeddedIntoSurface(
PxTrimeshSkinningGpuData* skinningDataArrayD, PxU32 arrayLength,
CUstream stream, PxU32 numGpuThreads) PX_OVERRIDE;
virtual void evaluateVerticesEmbeddedIntoVolume(
PxTetmeshSkinningGpuData* skinningDataArrayD, PxU32 arrayLength,
CUstream stream, PxU32 numGpuThreads) PX_OVERRIDE;
};
#endif
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,64 @@
// 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_DENSE_GRID_DATA_H
#define PXG_DENSE_GRID_DATA_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec4.h"
#include "PxSparseGridParams.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
struct PxgDenseGridData
{
PxVec3 mOrigin;
PxReal mGridSpacing;
PxU32 mNumCellsX;
PxU32 mNumCellsY;
PxU32 mNumCellsZ;
PX_FORCE_INLINE PX_CUDA_CALLABLE PxReal getGridSpacing() const { return mGridSpacing; }
PX_FORCE_INLINE PX_CUDA_CALLABLE PxI32 getHaloSize() const { return 0; }
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU32 maxNumCells()
{
return mNumCellsX * mNumCellsY * mNumCellsZ;
}
};
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,93 @@
// 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 PX_DENSE_GRID_DATA_H
#define PX_DENSE_GRID_DATA_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec4.h"
#include "PxSparseGridParams.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
/**
\brief Descriptor for axis aligned dense grids
*/
struct PxDenseGridParams
{
PxVec3 origin; //!< The origin of the dense grid which is the corner with smallest x/y/z coordinates
PxU32 numCellsX; //!< The number of cells in x direction
PxU32 numCellsY; //!< The number of cells in y direction
PxU32 numCellsZ; //!< The number of cells in z direction
PxReal gridSpacing; //!< The cell size
PxDenseGridParams() : origin(PxVec3(0.0f)), numCellsX(0), numCellsY(0), numCellsZ(0), gridSpacing(0) {}
PxDenseGridParams(const PxVec3& origin_, PxU32 numCellsX_, PxU32 numCellsY_, PxU32 numCellsZ_, PxReal gridSpacing_)
: origin(origin_), numCellsX(numCellsX_), numCellsY(numCellsY_), numCellsZ(numCellsZ_), gridSpacing(gridSpacing_) {}
};
/**
\brief Minimal set of data to access cells in a dense grid
*/
struct PxDenseGridData
{
PxDenseGridParams mGridParams; //!< The grid descriptor
PxDenseGridData() : mGridParams() {}
/**
\brief The number of cells in the dense grid
\return The number of cells
*/
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU32 maxNumCells()
{
return mGridParams.numCellsX * mGridParams.numCellsY * mGridParams.numCellsZ;
}
/**
\brief The dense grid's cell size
\return The cell size
*/
PX_FORCE_INLINE PX_CUDA_CALLABLE PxReal getCellSize()
{
return mGridParams.gridSpacing;
}
};
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,70 @@
// 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_ESSENTIAL_COMMON_H
#define PXG_ESSENTIAL_COMMON_H
#include "foundation/PxVec3.h"
#include "foundation/PxVec4.h"
#include "cudamanager/PxCudaTypes.h"
namespace physx
{
class PxgCudaKernelWranglerManager;
class PxCudaContextManager;
class PxCudaContext;
class PxgHeapMemoryAllocatorManager;
struct PxGpuDynamicsMemoryConfig;
class PxgSimulationController;
class PxgCudaBroadPhaseSap;
class PxgGpuNarrowphaseCore;
class PxgGpuContext;
class PxgEssentialCore
{
public:
PxgEssentialCore(PxgCudaKernelWranglerManager* gpuKernelWrangler, PxCudaContextManager* cudaContextManager,
PxgHeapMemoryAllocatorManager* heapMemoryManager, PxgSimulationController* simController,
PxgGpuContext* context);
PxgCudaKernelWranglerManager* mGpuKernelWranglerManager;
PxCudaContextManager* mCudaContextManager;
PxCudaContext* mCudaContext;
PxgHeapMemoryAllocatorManager* mHeapMemoryManager;
PxgSimulationController* mSimController;
PxgGpuContext* mGpuContext;
CUstream mStream;
};
}
#endif

View File

@@ -0,0 +1,336 @@
// 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_FEMCLOTH_H
#define PXG_FEMCLOTH_H
#include "PxDeformableSurface.h"
#include "PxgCudaBuffer.h"
#include "PxsHeapMemoryAllocator.h"
#include "cutil_math.h"
#include "foundation/PxUserAllocated.h"
#include "foundation/PxVec2.h"
#include "foundation/PxVec4.h"
namespace physx
{
namespace Gu
{
class TriangleMesh;
};
struct PxgFemRigidConstraintBlock;
struct PxsDeformableSurfaceMaterialData;
#if PX_VC
#pragma warning(push)
#pragma warning(disable : 4324) // padding was added at the end of a structure because of a __declspec(align) value.
#endif
struct PxgFEMClothData
{
public:
PxU32 mMaxNbNonSharedTrisPerPartition;
PxU32 mSharedTriPairRemapOutputSize;
PxU32 mNonSharedTriPairRemapOutputSize;
PxU32 mMaxNbSharedTriPairsPerPartition;
PxU32 mMaxNbNonSharedTriPairsPerPartition;
PxU32 mNbPackedNodes;
};
PX_ALIGN_PREFIX(16)
class PxgFEMCloth
{
public:
// to deallocate the host mirror. Make sure you pass in the right allocator!
void deallocate(PxsHeapMemoryAllocator* allocator);
void* mTriMeshData;
float4* mVelocity_InvMass;
float4* mPosition_InvMass;
float4* mRestPosition;
float4* mPrevPositionInContactOffset; // After contact pairs are updated, cloth vertices have moved by mPosition_InvMass -
// mPrevPositionInContactOffset.
float4* mPrevPositionInRestOffset; // After previous "step()", cloth vertices moved from mPosition_InvMass to mPrevPositionInRestOffset.
float* mDynamicFrictions; // dynamic friction per vertex
PxU16* mMaterialIndices;
PxU32* mTrianglesWithActiveEdges;
uint4* mTriangleVertexIndices;
uint4* mOrderedNonSharedTriangleVertexIndices_triIndex;
float2* mOrderedSharedTriangleLambdas; // Two lambdas per triangle: ARAP, area
float2* mOrderedNonSharedTriangleLambdas; // Two lambdas per triangle: ARAP, area
float4* mOrderedNonSharedTriangleRestPoseInv; // Four components of restPoseInv: m00, m10, m01, m11
// Shared triangle pair: A pair of triangles where both in-plane and bending constraints are applied together.
// Non-shared triangle pair: A pair of triangles where only bending constraints are applied.
uint4* mOrderedSharedTrianglePairVertexIndices;
uint4* mOrderedNonSharedTrianglePairVertexIndices;
float4* mOrderedSharedRestBendingAngle_flexuralStiffness_damping;
float4* mOrderedNonSharedRestBendingAngle_flexuralStiffness_damping;
float* mSharedBendingLambdas;
float* mNonSharedBendingLambdas;
bool mNonSharedTriPair_hasActiveBending;
// To solve in-plane energies for shared triangle pairs, the rest pose of the two triangles is also stored.
// Since the two triangles share an edge, only one additional edge needs to be stored for each triangle, which are edge0 and edge1.
// By choosing the shared edge to be in the direction of (1, 0) in 2D, only the magnitude of the shared edge needs to be stored.
// Consequently:
// Rest edges for triangle 0: (RestEdgeLength, 0), (Edge0.x, Edge0.y)
// Rest edges for triangle 1: (RestEdgeLength, 0), (Edge1.x, Edge1.y)
// This approach saves significant memory compared to storing restPoseInv matrices for each triangle.
float4* mOrderedSharedRestEdge0_edge1;
float4* mOrderedSharedRestEdgeLength_material0_material1;
float4* mPosition_InvMassCP;
PxU32* mNonSharedTriAccumulatedPartitionsCP;
PxU32* mSharedTriPairRemapOutputCP;
PxU32* mNonSharedTriPairRemapOutputCP;
PxU32* mSharedTriPairAccumulatedCopiesCP;
PxU32* mNonSharedTriPairAccumulatedCopiesCP;
PxU32* mSharedTriPairAccumulatedPartitionsCP;
PxU32* mNonSharedTriPairAccumulatedPartitionsCP;
float4* mDeltaPos; // Initialize to zero and zero every time in the apply delta kernel
float4* mAccumulatedDeltaPos;
float4* mAccumulatedDeltaVel; // Used for damping
PxBounds3* mPackedNodeBounds;
// For cloth-rigid contact preparation.
PxgFemRigidConstraintBlock* mRigidConstraints; // ((numVerts + 31) / 32) * maxNumContactPerVertex *
// sizeof(PxgFemRigidConstraintBlock)
PxReal mLinearDamping;
PxReal mMaxLinearVelocity;
PxReal mPenBiasClamp;
PxReal mSettlingThreshold;
PxReal mSleepThreshold;
PxReal mSettlingDamping;
PxReal mSelfCollisionFilterDistance;
PxU32 mNbVerts;
PxU32 mNbTriangles;
PxU32 mNbNonSharedTriangles;
PxU32 mNbTrianglesWithActiveEdges;
PxU32 mNbTrianglePairs;
PxU32 mNbSharedTrianglePairs;
PxU32 mNbNonSharedTrianglePairs;
PxU32 mNbNonSharedTriPartitions;
PxU32 mNbSharedTriPairPartitions;
PxU32 mNbNonSharedTriPairPartitions;
// For partitions that contain only a small number of elements, run them in a single kernel call instead of launching multiple kernels
// one by one.
// clusterId stores the first partition that has fewer elements than PxgFEMClothKernelBlockDim::CLOTH_SOLVESHELL.
PxU32 mNonSharedTriClusterId;
PxU32 mSharedTriPairClusterId;
PxU32 mNonSharedTriPairClusterId;
PxU32 mElementIndex;
PxU32 mGpuRemapIndex;
PxU8 mActorFlags;
PxU8 mBodyFlags;
PxU16 mSurfaceFlags;
PxU32 mIsActive;
PxReal mRestDistance;
PxReal mOriginalContactOffset;
PxU32 mNbCollisionPairUpdatesPerTimestep;
PxU32 mNbCollisionSubsteps;
} PX_ALIGN_SUFFIX(16);
#if PX_VC
#pragma warning(pop)
#endif
class PxgFEMClothBuffer : public PxUserAllocated
{
public:
PxgFEMClothBuffer(PxgHeapMemoryAllocatorManager* heapMemoryManager);
PxgCudaBuffer triangleMeshData;
PxgTypedCudaBuffer<float4> deltaPos;
PxgTypedCudaBuffer<float4> accumulatedDeltaPos;
PxgTypedCudaBuffer<float4> accumulatedDeltaVel; // Used for damping
PxgTypedCudaBuffer<float4> prevPositionInContactOffset; // After contact pairs are updated, cloth vertices have moved by
// mPosition_InvMass - mPrevPositionInContactOffset.
PxgTypedCudaBuffer<float4> prevPositionInRestOffset; // After cloth-cloth distance is measured, cloth vertices have moved by
// mPosition_InvMass - mPrevPositionInRestOffset.
PxgTypedCudaBuffer<PxU16> materialIndices;
PxgTypedCudaBuffer<float> dynamicfrictions;
PxgTypedCudaBuffer<PxU32> trianglesWithActiveEdges;
PxgTypedCudaBuffer<uint4> triangleVertexIndices;
PxgTypedCudaBuffer<uint4> orderedNonSharedTriangleVertexIndices_triIndex;
PxgTypedCudaBuffer<float2> orderedSharedTriangleLambdas;
PxgTypedCudaBuffer<float2> orderedNonSharedTriangleLambdas;
PxgTypedCudaBuffer<float4> orderedNonSharedTriangleRestPoseInv;
PxgTypedCudaBuffer<uint4> orderedSharedTrianglePairVertexIndices;
PxgTypedCudaBuffer<uint4> orderedNonSharedTrianglePairVertexIndices;
PxgTypedCudaBuffer<float4> orderedSharedRestBendingAngle_flexuralStiffness_damping;
PxgTypedCudaBuffer<float4> orderedNonSharedRestBendingAngle_flexuralStiffness_damping;
PxgTypedCudaBuffer<float4> orderedSharedRestEdge0_edge1;
PxgTypedCudaBuffer<float4> orderedSharedRestEdgeLength_material0_material1;
PxgTypedCudaBuffer<float> sharedBendingLambdas;
PxgTypedCudaBuffer<float> nonSharedBendingLambdas;
PxgTypedCudaBuffer<float4> position_InvMassCP;
PxgTypedCudaBuffer<PxU32> nonSharedTriAccumulatedPartitionsCP;
PxgTypedCudaBuffer<PxU32> sharedTriPairRemapOutputCP;
PxgTypedCudaBuffer<PxU32> nonSharedTriPairRemapOutputCP;
PxgTypedCudaBuffer<PxU32> sharedTriPairAccumulatedCopiesCP;
PxgTypedCudaBuffer<PxU32> nonSharedTriPairAccumulatedCopiesCP;
PxgTypedCudaBuffer<PxU32> sharedTriPairAccumulatedPartitionsCP;
PxgTypedCudaBuffer<PxU32> nonSharedTriPairAccumulatedPartitionsCP;
PxgTypedCudaBuffer<PxBounds3> packedNodeBounds; // for refit
PxgTypedCudaBuffer<PxU32> numPenetratedTets;
};
struct EdgeEncoding
{
// TYPE0 layout (lower 16 bits)
static constexpr PxU32 TYPE0_EDGE_BASE_POS = 0; // Edge presence bits: 0-2
static constexpr PxU32 TYPE0_AUTH_COUNT_POS = 3; // bits 3-4
static constexpr PxU32 TYPE0_FIRST_EDGE_POS = 5; // bits 5-6
static constexpr PxU32 TYPE0_SECOND_EDGE_POS = 7; // bits 7-8
static constexpr PxU32 TYPE0_THIRD_EDGE_POS = 9; // bits 9-10
static constexpr PxU32 TYPE0_VERTEX0_ACTIVE_POS = 11;
static constexpr PxU32 TYPE0_VERTEX1_ACTIVE_POS = 12;
static constexpr PxU32 TYPE0_VERTEX2_ACTIVE_POS = 13;
// TYPE1 layout (upper 16 bits)
static constexpr PxU32 TYPE1_EDGE_BASE_POS = 16; // edge presence: bits 16-18
static constexpr PxU32 TYPE1_AUTH_COUNT_POS = 19; // bits 19-20
static constexpr PxU32 TYPE1_FIRST_EDGE_POS = 21; // bits 21-22
static constexpr PxU32 TYPE1_SECOND_EDGE_POS = 23; // bits 23-24
static constexpr PxU32 TYPE1_THIRD_EDGE_POS = 25; // bits 25-26
static constexpr PxU32 TYPE1_VERTEX0_ACTIVE_POS = 27;
static constexpr PxU32 TYPE1_VERTEX1_ACTIVE_POS = 28;
static constexpr PxU32 TYPE1_VERTEX2_ACTIVE_POS = 29;
};
struct EdgeEncodingMask
{
// Type0: minimal triangle set covering all edges and vertices (compact encoding)
static constexpr PxU32 TYPE0_AUTH_COUNT_MASK = 0x3 << EdgeEncoding::TYPE0_AUTH_COUNT_POS;
static constexpr PxU32 TYPE0_FIRST_EDGE_MASK = 0x3 << EdgeEncoding::TYPE0_FIRST_EDGE_POS;
static constexpr PxU32 TYPE0_SECOND_EDGE_MASK = 0x3 << EdgeEncoding::TYPE0_SECOND_EDGE_POS;
static constexpr PxU32 TYPE0_THIRD_EDGE_MASK = 0x3 << EdgeEncoding::TYPE0_THIRD_EDGE_POS;
static constexpr PxU32 TYPE0_VERTEX0_ACTIVE_MASK = 1U << EdgeEncoding::TYPE0_VERTEX0_ACTIVE_POS;
static constexpr PxU32 TYPE0_VERTEX1_ACTIVE_MASK = 1U << EdgeEncoding::TYPE0_VERTEX1_ACTIVE_POS;
static constexpr PxU32 TYPE0_VERTEX2_ACTIVE_MASK = 1U << EdgeEncoding::TYPE0_VERTEX2_ACTIVE_POS;
// Type1: more balanced distribution of edges and vertices across triangles (balanced encoding)
static constexpr PxU32 TYPE1_FIRST_EDGE_MASK = 0x3 << EdgeEncoding::TYPE1_FIRST_EDGE_POS;
static constexpr PxU32 TYPE1_SECOND_EDGE_MASK = 0x3 << EdgeEncoding::TYPE1_SECOND_EDGE_POS;
static constexpr PxU32 TYPE1_THIRD_EDGE_MASK = 0x3 << EdgeEncoding::TYPE1_THIRD_EDGE_POS;
static constexpr PxU32 TYPE1_VERTEX0_ACTIVE_MASK = 1U << EdgeEncoding::TYPE1_VERTEX0_ACTIVE_POS;
static constexpr PxU32 TYPE1_VERTEX1_ACTIVE_MASK = 1U << EdgeEncoding::TYPE1_VERTEX1_ACTIVE_POS;
static constexpr PxU32 TYPE1_VERTEX2_ACTIVE_MASK = 1U << EdgeEncoding::TYPE1_VERTEX2_ACTIVE_POS;
};
class PxgFEMClothUtil
{
public:
static PxU32 computeTriangleMeshByteSize(const Gu::TriangleMesh* triangleMesh);
static PxU32 loadOutTriangleMesh(void* mem, const Gu::TriangleMesh* triangleMesh);
static PxU32 initialTriangleData(PxgFEMCloth& femCloth, PxArray<uint2>& trianglePairTriangleIndices,
PxArray<uint4>& trianglePairVertexIndices, const Gu::TriangleMesh* triangleMesh,
const PxU16* materialHandles, PxsDeformableSurfaceMaterialData* materials, const PxU32 nbMaterials,
PxsHeapMemoryAllocator* alloc);
static void categorizeClothConstraints(PxArray<PxU32>& sharedTrianglePairs, PxArray<PxU32>& nonSharedTriangles,
PxArray<PxU32>& nonSharedTrianglePairs, PxgFEMCloth& femCloth,
const PxArray<uint2>& trianglePairTriangleIndices);
static void computeNonSharedTriangleConfiguration(PxgFEMCloth& femCloth, const PxArray<PxU32>& orderedNonSharedTriangles,
const PxArray<PxU32>& activeTriangleIndices,
const Gu::TriangleMesh* const triangleMesh);
static float updateFlexuralStiffnessPerTrianglePair(float t0Area, float t1Area, float hingeLength, float thickness, float inputStiffness);
static bool updateRestConfiguration(float4* orderedRestAngleAndStiffness_damping, uint4* orderedTrianglePairVertexIndices,
PxgFEMCloth& femCloth, PxU32 it, PxU32 index, PxArray<uint2>& trianglePairTriangleIndices,
const PxArray<uint4>& trianglePairVertexIndices, const PxsDeformableSurfaceMaterialData* materials,
const PxVec3* positions, bool zeroRestBendingAngle, float4* orderedRestEdge0_edge1 = NULL,
float4* orderedRestEdgeLength_material0_material1 = NULL);
static void computeTrianglePairConfiguration(PxgFEMCloth& femCloth, PxArray<uint2>& trianglePairTriangleIndices,
const PxArray<uint4>& trianglePairVertexIndices, const PxArray<PxU32>& orderedTrianglePairs,
const PxArray<PxU32>& activeTrianglePairIndices, const Gu::TriangleMesh* const triangleMesh,
const PxsDeformableSurfaceMaterialData* materials, bool zeroRestBendingAngle,
bool isSharedPartition);
};
} // namespace physx
#endif

View File

@@ -0,0 +1,217 @@
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef PXG_FEMCLOTH_CORE_H
#define PXG_FEMCLOTH_CORE_H
#include "PxgFEMCore.h"
namespace physx
{
#define FEMCLOTH_MAX_NUM_PARTITIONS 32
namespace Dy
{
struct DeformableSurfaceCore;
class DeformableSurface;
}
// this is needed to force PhysXSimulationControllerGpu linkage as Static Library!
void createPxgFEMCloth();
struct PxGpuDynamicsMemoryConfig;
class PxgCudaBroadPhaseSap;
class PxgGpuNarrowphaseCore;
class PxgFEMCloth;
struct PxgFEMClothData;
class PxRenderBuffer;
class PxRenderOutput;
struct PxgSolverCoreDesc;
struct PxgArticulationCoreDesc;
class PxPostSolveCallback;
struct PxgPrePrepDesc;
struct PxgConstraintPrepareDesc;
struct PxgSolverSharedDescBase;
class PxgFEMClothCore : public PxgFEMCore
{
public:
PxgFEMClothCore(PxgCudaKernelWranglerManager* gpuKernelWrangler, PxCudaContextManager* cudaContextManager,
PxgHeapMemoryAllocatorManager* heapMemoryManager, PxgSimulationController* simController, PxgGpuContext* context,
PxU32 maxContacts, const PxU32 collisionStackSize, bool isTGS);
~PxgFEMClothCore();
void preIteration();
// Integrate verts position based on gravity
void preIntegrateSystems(PxU32 nbActiveFEMCloths, const PxVec3& gravity, PxReal dt);
// Calculate femCloth's world bound
void refitBound(PxU32 nbActiveFEMCloths, CUstream stream);
void resetClothVsNonclothContactCounts();
void checkBufferOverflows();
void updateClothContactPairValidity(bool forceUpdateClothContactPairs, bool adaptiveCollisionPairUpdate, PxReal dt);
void selfCollision(bool isVT);
void differentClothCollision(bool isVT);
void clampContactCounts();
void sortContacts(PxU32 nbActiveFemClothes);
void solve(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd,
PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd,
PxReal dt, CUstream solverStream, PxU32 iter, PxU32 maxIter, bool isVelocityIteration, const PxVec3& gravity);
void solve_position(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd,
PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd,
PxReal dt, CUstream solverStream, PxU32 iter, PxU32 maxIter, const PxVec3& gravity);
void solve_velocity(PxU32 iter, PxU32 maxIter, PxReal dt);
void step(PxReal dt, CUstream stream, PxU32 nbFEMCloths, const PxVec3& gravity, bool adaptiveCollisionPairUpdate, bool forceUpdateClothContactPairs);
void finalizeVelocities(PxReal dt);
void constraintPrep(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgConstraintPrepareDesc> prepDescd,
PxReal invDt, PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, CUstream solverStream,
PxU32 nbSolverBodies, PxU32 nbArticulations);
bool updateUserData(PxPinnedArray<PxgFEMCloth>& femClothPool, PxArray<PxU32>& femClothNodeIndexPool, const PxU32* activeFEMCloths,
PxU32 nbActiveFEMCloths, void** bodySimsLL);
CUstream getStream() { return mStream; }
void partitionTriangleSimData(PxgFEMCloth& femCloth, PxgFEMClothData& clothData, PxArray<PxU32>& orderedTriangles,
const PxArray<PxU32>& activeTriangles, PxsHeapMemoryAllocator* alloc);
void partitionTrianglePairSimData(PxgFEMCloth& femCloth, PxgFEMClothData& clothData, PxU32 maximumPartitions,
PxArray<PxU32>& orderedTrianglePairs, const PxArray<PxU32>& activeTrianglePairs,
const PxArray<uint4>& trianglePairVertexIndices, bool isSharedTrianglePair,
PxsHeapMemoryAllocator* alloc);
PxgCudaPagedLinearAllocator<PxgHeapMemoryAllocator>& getStackAllocator() { return mIntermStackAlloc; }
PX_FORCE_INLINE PxU32 getMaxContacts() { return mMaxContacts; }
void applyDamping(PxU32 nbActiveFemClothes, PxReal dt, CUstream stream);
// Apply position delta change original triangle mesh
void applyExternalDelta(PxU32 nbActiveFemClothes, PxReal dt, CUstream stream);
void drawContacts(PxRenderOutput& out);
void syncCloths();
void createActivatedDeactivatedLists();
private:
void preIntegrateSystem(PxgFEMCloth* femClothsd, PxU32* activeFemCloths, PxU32 nbActiveFemCloths, PxU32 maxVertices,
const PxVec3& gravity, PxReal dt, CUstream bpStream);
void prepRigidContactConstraint(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgConstraintPrepareDesc> prepDescd,
PxReal invDt, PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, CUstream solverStream,
PxU32 numSolverBodies, PxU32 numArticulations);
void prepRigidAttachmentConstraints(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd,
PxgDevicePointer<PxgConstraintPrepareDesc> prepDescd, PxReal /*invDt*/,
PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, CUstream stream);
void prepClothAttachmentConstraints(CUstream stream);
void prepClothParticleConstraint();
// These method are running at the cloth stream
void prepClothContactConstraint(bool isVT);
void solveShellEnergy(PxgFEMCloth* femClothsd, PxgDevicePointer<PxU32> activeFEMClothsd, PxU32 nbActiveFEMCloths, PxReal dt);
void solveNonSharedTriangles(PxgFEMCloth* femClothsd, PxgDevicePointer<PxU32> activeFEMClothsd, PxU32 nbActiveFEMCloths, PxReal dt);
void solveTrianglePairs(PxgFEMCloth* femClothsd, PxgDevicePointer<PxU32> activeFEMClothsd, PxU32 nbActiveFEMCloths, PxReal dt,
bool isSharedTrianglePair);
void queryRigidContactReferenceCount(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd,
PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd,
PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd,
PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd, CUstream solverStream, PxReal dt);
// Solve cloth vs rigid body contact
void solveClothRigidContacts(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd,
PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd,
PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd, CUstream solverStream, PxReal dt);
// Solve cloth vs rigid body attachment
void solveClothRigidAttachment(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd,
PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd,
PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd, CUstream solverStream, PxReal dt);
void solveClothAttachmentDelta();
void prepareClothClothCollision(bool forceUpdateClothContactPairs, bool adaptiveCollisionPairUpdate, PxReal dt);
void solveClothClothCollision(PxU32 nbActiveFEMCloths, PxReal dt);
// Solve cloth vs cloth contact and output to cloth delta buffer
void solveClothContactsOutputClothDelta(PxReal dt, bool isVT);
// Solve cloth vs particle contact and output to cloth delta buffer
void solveParticleContactsOutputClothDelta(CUstream particleStream);
// Solve cloth vs particle contact and output to particle delta buffer
void solveParticleContactsOutputParticleDelta(CUstream particleStream);
//--------------------------------------------------------------------------------------
PxgTypedCudaBuffer<PxU8> mUpdateClothContactPairs; // When set to 1, updates the cloth-cloth contact pairs.
CUevent mBoundUpdateEvent; // This event is used to synchronize the broad phase stream(updateBound is running on
// broad phase stream) and mStream
CUevent mSolveRigidEvent; // This event is recorded at the solver stream and the cloth stream need to wait for
// that event finish before it processes
CUevent mConstraintPrepParticleEvent; // This event is used to synchronize constraint prep(cloth stream) and
// solve cloth vs particle system contacts (particle stream)
CUevent mSolveParticleEvent; // This event is used to synchronize particle system contacts (particle stream)
// before we call applyExternalTetraDelta
public:
PxArray<Dy::DeformableSurface*> mActivatingDeformableSurfaces;
PxArray<Dy::DeformableSurface*> mDeactivatingDeformableSurfaces;
PxPostSolveCallback* mPostSolveCallback;
};
}
#endif

View File

@@ -0,0 +1,46 @@
// 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_FEMCLOTH_CORE_KERNEL_INDICES_H
#define PXG_FEMCLOTH_CORE_KERNEL_INDICES_H
namespace physx
{
struct PxgFEMClothKernelBlockDim
{
enum
{
CLOTH_PREINTEGRATION = 512,
CLOTH_STEP = 1024,
CLOTH_SOLVESHELL = 128
};
};
}
#endif

View File

@@ -0,0 +1,543 @@
// 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_FEM_CORE_H
#define PXG_FEM_CORE_H
#include "PxgNonRigidCoreCommon.h"
#include "PxgSimulationCoreDesc.h"
#include "PxNodeIndex.h"
#include "foundation/PxSimpleTypes.h"
#include <vector_types.h>
namespace physx
{
struct PxgPrePrepDesc;
struct PxgSolverCoreDesc;
struct PxgSolverSharedDescBase;
struct PxgArticulationCoreDesc;
//rigid vs soft body : pairInd0 is rigid , pairInd1 is soft body
//particle vs soft body : pairInd0 is particle, pairInd1 is soft body
//soft body vs soft body : pairInd0 is soft body, pairInd1 is soft body
//soft body vs fem cloth : pairInd0 is soft body, pairInd1 is fem cloth
//fem cloth vs fem cloth : pairInd0 is fem cloth, pairInd1 is fem cloth
struct PX_ALIGN_PREFIX(16) PxgFemFemContactInfo
{
PxU64 pairInd0;
PxU32 pairInd1;
PxU32 auxInd; // Packed 32-bit auxiliary data
// Bit layout of auxInd (32 bits total):
//
// | 31 | 30 | 29 | 28 - 14 | 13 - 0 |
// | Valid | PairType | InCollision| AuxInd1 (15 bits)| AuxInd0 (14b) |
//
// - Bits [0-13] : AuxInd0. First auxiliary index (14 bits, max value 16,383)
// - Bits [14-28] : AuxInd1. Second auxiliary index (15 bits, max value 32,767)
// - Bit [29] : isInCollision flag (0 = not in contact, 1 = in contact)
// - Bit [30] : Pair type flag (0 = Vertex-Triangle, 1 = Edge-Edge)
// - Bit [31] : Validity flag (0 = Invalid, 1 = Valid)
// Bit layout masks and shifts for auxInd
static constexpr PxU32 AUX_IND0_BITS = 14;
static constexpr PxU32 AUX_IND1_BITS = 15;
static constexpr PxU32 AUX_IND0_MASK = (1u << AUX_IND0_BITS) - 1; // 0x00003FFF
static constexpr PxU32 AUX_IND1_MASK = ((1u << AUX_IND1_BITS) - 1) << AUX_IND0_BITS; // 0x1FFFC000
static constexpr PxU32 AUX_IND1_SHIFT = AUX_IND0_BITS;
static constexpr PxU32 CONTACT_FLAG_SHIFT = 29;
static constexpr PxU32 PAIR_TYPE_FLAG_SHIFT = 30;
static constexpr PxU32 VALIDITY_FLAG_SHIFT = 31;
static constexpr PxU32 CONTACT_FLAG_MASK = 1u << CONTACT_FLAG_SHIFT;
static constexpr PxU32 PAIR_TYPE_FLAG_MASK = 1u << PAIR_TYPE_FLAG_SHIFT;
static constexpr PxU32 VALIDITY_FLAG_MASK = 1u << VALIDITY_FLAG_SHIFT;
// Set auxiliary indices
PX_FORCE_INLINE PX_CUDA_CALLABLE void setAuxInd0(PxU32 id) { auxInd = (auxInd & ~AUX_IND0_MASK) | (id & AUX_IND0_MASK); }
PX_FORCE_INLINE PX_CUDA_CALLABLE void setAuxInd1(PxU32 id)
{
auxInd = (auxInd & ~AUX_IND1_MASK) | ((id & ((1u << AUX_IND1_BITS) - 1)) << AUX_IND1_SHIFT);
}
// Get auxiliary indices
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU32 getAuxInd0() const { return auxInd & AUX_IND0_MASK; }
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU32 getAuxInd1() const { return (auxInd >> AUX_IND1_SHIFT) & ((1u << AUX_IND1_BITS) - 1); }
// Mark validity
PX_FORCE_INLINE PX_CUDA_CALLABLE void markInvalid() { auxInd &= ~VALIDITY_FLAG_MASK; }
PX_FORCE_INLINE PX_CUDA_CALLABLE void markValid() { auxInd |= VALIDITY_FLAG_MASK; }
PX_FORCE_INLINE PX_CUDA_CALLABLE void markValidity(bool isValid)
{
auxInd = (auxInd & ~VALIDITY_FLAG_MASK) | (static_cast<PxU32>(isValid) << VALIDITY_FLAG_SHIFT);
}
PX_FORCE_INLINE PX_CUDA_CALLABLE bool isValidPair() const { return (auxInd & VALIDITY_FLAG_MASK) != 0; }
// Mark pair type
PX_FORCE_INLINE PX_CUDA_CALLABLE void markVertexTrianglePair() { auxInd &= ~PAIR_TYPE_FLAG_MASK; }
PX_FORCE_INLINE PX_CUDA_CALLABLE void markEdgeEdgePair() { auxInd |= PAIR_TYPE_FLAG_MASK; }
PX_FORCE_INLINE PX_CUDA_CALLABLE bool isVertexTrianglePair() const { return (auxInd & PAIR_TYPE_FLAG_MASK) == 0; }
PX_FORCE_INLINE PX_CUDA_CALLABLE bool isEdgeEdgePair() const { return (auxInd & PAIR_TYPE_FLAG_MASK) != 0; }
// Mark collision status (bit 29)
PX_FORCE_INLINE PX_CUDA_CALLABLE void markInCollision(bool inContact)
{
auxInd = (auxInd & ~CONTACT_FLAG_MASK) | (static_cast<PxU32>(inContact) << CONTACT_FLAG_SHIFT);
}
PX_FORCE_INLINE PX_CUDA_CALLABLE bool isInCollision() const { return (auxInd & CONTACT_FLAG_MASK) != 0; }
} PX_ALIGN_SUFFIX(16);
struct PX_ALIGN_PREFIX(16) PxgFemOtherContactInfo
{
PxU64 pairInd0; // Rigid/Particle
PxU32 pairInd1; // Fem id
PxU32 rigidMatInd_isInCollision;
// rigidMatInd_isInCollision encodes both rigid material index and collision state
// Bit layout of rigidMatInd_isInCollision (32 bits total):
//
// | 31 | 30 - 0 |
// |-------------|---------------------|
// | isCollision | rigidMaterialIndex |
//
// - Bits [0-30] : rigidMaterialIndex (up to 2^31 materials)
// - Bit [31] : isInCollision flag (0 = not in contact, 1 = in contact)
static constexpr PxU32 COLLISION_FLAG_BIT = 31;
static constexpr PxU32 COLLISION_FLAG_MASK = 1u << COLLISION_FLAG_BIT;
static constexpr PxU32 RIGID_MAT_INDEX_MASK = ~COLLISION_FLAG_MASK;
PX_FORCE_INLINE PX_CUDA_CALLABLE void setRigidMaterialIndex(PxU32 matIndex)
{
rigidMatInd_isInCollision = (rigidMatInd_isInCollision & COLLISION_FLAG_MASK) | (matIndex & RIGID_MAT_INDEX_MASK);
}
PX_FORCE_INLINE PX_CUDA_CALLABLE void markInCollision(bool inContact)
{
if(inContact)
rigidMatInd_isInCollision |= COLLISION_FLAG_MASK;
else
rigidMatInd_isInCollision &= ~COLLISION_FLAG_MASK;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU32 getRigidMaterialIndex() const { return rigidMatInd_isInCollision & RIGID_MAT_INDEX_MASK; }
PX_FORCE_INLINE PX_CUDA_CALLABLE bool isInCollision() const { return (rigidMatInd_isInCollision & COLLISION_FLAG_MASK) != 0; }
}
PX_ALIGN_SUFFIX(16);
PX_COMPILE_TIME_ASSERT(sizeof(PxgFemFemContactInfo) == sizeof(PxgFemOtherContactInfo));
struct PxgFemRigidConstraintBlock
{
// resp represents the rigid-body term in the denominator of the impulse calculation (also referred to as the velocity multiplier
// internally). Also refer to PBD (Position-Based Dynamics) papers.
float4 raXn_resp[32];
float4 raXnF0_resp[32];
float4 raXnF1_resp[32];
float4 normal_errorW[32];
// Friction tangent + invMass of the rigid body (avoids needing to read the mass)
// Second tangent can be found by cross producting normal with fricTan0
float4 fricTan0_invMass0[32];
float4 barycentric[32];
PxReal maxPenBias[32];
};
struct PxgFEMParticleConstraintBlock
{
float4 normal_pen[32];
float4 barycentric[32];
PxReal velMultiplier[32];
};
struct PxgFEMRigidAttachmentConstraint
{
float4 baryOrType[32];
float4 raXn0_biasW[32];
float4 raXn1_biasW[32];
float4 raXn2_biasW[32];
float4 velMultiplierXYZ_invMassW[32];
float4 low_high_limits[32];
float4 axis_angle[32];
PxU32 elemId[32];
PxU64 rigidId[32]; //node index
};
struct PxgFEMFEMAttachmentConstraint
{
union
{
float4 low_high_limits[32];
float4 low_high_angles[32];
};
union
{
float4 axis_angle[32];
float4 attachmentBarycentric[32];
};
float4 barycentric0[32];
float4 barycentric1[32];
PxU64 elemId0[32]; //can be triangleId(cloth) or tetrahedron index
PxU64 elemId1[32];//can be triangleId(cloth) or tetrahedron index
float constraintOffset[32];
};
class PxgFEMCore : public PxgNonRigidCore
{
public:
PxgFEMCore(PxgCudaKernelWranglerManager* gpuKernelWrangler, PxCudaContextManager* cudaContextManager,
PxgHeapMemoryAllocatorManager* heapMemoryManager, PxgSimulationController* simController,
PxgGpuContext* context, const PxU32 maxContacts, const PxU32 collisionStackSize, bool isTGS, PxsHeapStats::Enum statType);
virtual ~PxgFEMCore();
PX_FORCE_INLINE PxgTypedCudaBuffer<float4>& getRigidContacts() { return mRigidContactPointBuf; }
PX_FORCE_INLINE PxgTypedCudaBuffer<float4>& getRigidNormalPens() { return mRigidContactNormalPenBuf; }
PX_FORCE_INLINE PxgTypedCudaBuffer<float4>& getRigidBarycentrics() { return mRigidContactBarycentricBuf; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgFemOtherContactInfo>& getRigidContactInfos() { return mRigidContactInfoBuf; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getRigidContactCount() { return mRigidTotalContactCountBuf; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getPrevRigidContactCount() { return mRigidPrevContactCountBuf; }
PX_FORCE_INLINE PxgTypedCudaBuffer<float4>& getFemContacts() { return mFemContactPointBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<float4>& getFemNormalPens() { return mFemContactNormalPenBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<float4>& getFemBarycentrics0() { return mFemContactBarycentric0Buffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<float4>& getFemBarycentrics1() { return mFemContactBarycentric1Buffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgFemFemContactInfo>& getVolumeContactOrVTContactInfos() { return mVolumeContactOrVTContactInfoBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgFemFemContactInfo>& getEEContactInfos() { return mEEContactInfoBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getVolumeContactOrVTContactCount() { return mVolumeContactOrVTContactCountBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getEEContactCount() { return mEEContactCountBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getPrevFemContactCount() { return mPrevFemContactCountBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<float4>& getParticleContacts() { return mParticleContactPointBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<float4>& getParticleNormalPens() { return mParticleContactNormalPenBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<float4>& getParticleBarycentrics() { return mParticleContactBarycentricBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgFemOtherContactInfo>& getParticleContactInfos() { return mParticleContactInfoBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getParticleContactCount() { return mParticleTotalContactCountBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getPrevParticleContactCount() { return mPrevParticleContactCountBuffer; }
PX_FORCE_INLINE PxgDevicePointer<PxReal> getSpeculativeCCDContactOffset() { return mSpeculativeCCDContactOffset.getTypedDevicePtr(); }
void reserveRigidDeltaVelBuf(PxU32 newCapacity);
void reorderRigidContacts();
void copyContactCountsToHost();
protected:
void accumulateRigidDeltas(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd,
PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd,
PxgDevicePointer<PxNodeIndex> rigidIdsd, PxgDevicePointer<PxU32> numIdsd, CUstream stream, bool isTGS);
//rigid body and fem contacts
PxgTypedCudaBuffer<float4> mRigidContactPointBuf; //float4
PxgTypedCudaBuffer<float4> mRigidContactNormalPenBuf; //float4
PxgTypedCudaBuffer<float4> mRigidContactBarycentricBuf; //float4
PxgTypedCudaBuffer<PxgFemOtherContactInfo> mRigidContactInfoBuf;
PxgTypedCudaBuffer<PxU32> mRigidTotalContactCountBuf; //PxU32
PxgTypedCudaBuffer<PxU32> mRigidPrevContactCountBuf; //PxU32
PxgTypedCudaBuffer<float4> mRigidSortedContactPointBuf;
PxgTypedCudaBuffer<float4> mRigidSortedContactNormalPenBuf;
PxgTypedCudaBuffer<float4> mRigidSortedContactBarycentricBuf; //float4
PxgTypedCudaBuffer<PxU64> mRigidSortedRigidIdBuf;
PxgTypedCudaBuffer<PxgFemOtherContactInfo> mRigidSortedContactInfoBuf;
// Reference count of each rigid body that interacts with deformable objects.
// A single rigid body can have multiple reference counts when it is in contact with multiple triangles, tetrahedra, vertices, etc.
// from deformable surfaces or deformable bodies. Currently, this is used only for contact constraints, but it can also be used for
// attachment constraints.
PxgTypedCudaBuffer<PxU32> mFemRigidReferenceCount;
//fem vs fem and fem self collision contacts
PxgTypedCudaBuffer<float4> mFemContactPointBuffer; //float4
PxgTypedCudaBuffer<float4> mFemContactNormalPenBuffer; //float4
PxgTypedCudaBuffer<float4> mFemContactBarycentric0Buffer; //float4
PxgTypedCudaBuffer<float4> mFemContactBarycentric1Buffer; //float4
PxgTypedCudaBuffer<PxgFemFemContactInfo> mVolumeContactOrVTContactInfoBuffer;
PxgTypedCudaBuffer<PxgFemFemContactInfo> mEEContactInfoBuffer;
PxgTypedCudaBuffer<PxU32> mVolumeContactOrVTContactCountBuffer;
PxgTypedCudaBuffer<PxU32> mEEContactCountBuffer;
PxgTypedCudaBuffer<PxU32> mPrevFemContactCountBuffer;
PxgTypedCudaBuffer<PxReal> mSpeculativeCCDContactOffset;
//fem body vs particle system collision contacts
PxgTypedCudaBuffer<float4> mParticleContactPointBuffer; //float4
PxgTypedCudaBuffer<float4> mParticleContactNormalPenBuffer; //float4
PxgTypedCudaBuffer<float4> mParticleContactBarycentricBuffer; //float4
PxgTypedCudaBuffer<PxgFemOtherContactInfo> mParticleContactInfoBuffer;
PxgTypedCudaBuffer<PxU32> mParticleTotalContactCountBuffer;
PxgTypedCudaBuffer<PxU32> mPrevParticleContactCountBuffer;
PxgTypedCudaBuffer<float4> mParticleSortedContactPointBuffer;
PxgTypedCudaBuffer<float4> mParticleSortedContactBarycentricBuffer; //float4
PxgTypedCudaBuffer<float4> mParticleSortedContactNormalPenBuffer;
PxgTypedCudaBuffer<PxgFemOtherContactInfo> mParticleSortedContactInfoBuffer;
//contact prep buffer
PxgTypedCudaBuffer<PxgFemRigidConstraintBlock> mRigidConstraintBuf; //constraint prep for rigid body vs fem
PxgCudaBuffer mFemConstraintBuf; //constraint prep for fem vs fem(including self collision)
PxgTypedCudaBuffer<PxgFEMParticleConstraintBlock> mParticleConstraintBuf; //constraint prep for particle vs fem
//To do: ideally, we want to use two separate stream to solve the rigid body collision
PxgTypedCudaBuffer<PxReal> mRigidFEMAppliedForcesBuf;
PxgTypedCudaBuffer<float4> mFemAppliedForcesBuf; //applied force for fem due to collision between fem and fem or self collision
PxgTypedCudaBuffer<float4> mParticleAppliedFEMForcesBuf; //applied force for fem due to collision between particle system and fem
PxgTypedCudaBuffer<float4> mParticleAppliedParticleForcesBuf; //applied force for particle system due to collision between particle system and fem
PxgTypedCudaBuffer<float4> mRigidDeltaVelBuf;
//Temp buffer to accumulate rigid delta velocity changes
PxgTypedCudaBuffer<PxVec4> mTempBlockDeltaVelBuf;
PxgTypedCudaBuffer<PxU64> mTempBlockRigidIdBuf;
//Temp buffer for sorted particle contacts
PxgCudaBuffer mTempCellsHistogramBuf;
PxgTypedCudaBuffer<PxU32> mTempBlockCellsHistogramBuf;
PxgTypedCudaBuffer<PxU32> mTempHistogramCountBuf;
bool mIsTGS;
PxU32* mRigidContactCountPrevTimestep; //Pinned memory
PxU32* mVolumeContactorVTContactCountPrevTimestep; //Pinned memory
PxU32* mEEContactCountPrevTimestep; //Pinned memory
PxU32* mParticleContactCountPrevTimestep; //Pinned memory
#if PX_ENABLE_SIM_STATS
PxU32 mContactCountStats; // for simStats.
#else
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
#endif
CUevent mFinalizeEvent;
};
struct PxgFEMContactWriter
{
float4* outPoint;
float4* outNormalPen;
float4* outBarycentric;
PxgFemOtherContactInfo* outContactInfo;
PxU32* totalContactCount;
//Buffers for sorting. X either stands for Rigid or Particle
PxU64* contactByX; //value
PxU32* tempContactByX; //the lower 32 bit o value
PxU32* contactIndexSortedByX; //rank
PxU32* contactSortedByX; // AD: I'm not sure what we use this for. We do use the underlying buffer as the output buffer of RS_COPY_VALUE, so either we're skipping the radix sort in some cases or we write some unnecessary stuff here.
PxU32 maxNumContacts;
PxgFEMContactWriter(PxgFEMCore* femCore, bool useParticleForSorting = false)
{
//Ensure a rigid index has the same size as an encoded particle index
PX_COMPILE_TIME_ASSERT(sizeof(PxNodeIndex) == sizeof(PxU64));
if (useParticleForSorting)
{
outPoint = femCore->getParticleContacts().getTypedPtr();
outNormalPen = femCore->getParticleNormalPens().getTypedPtr();
outBarycentric = femCore->getParticleBarycentrics().getTypedPtr();
outContactInfo = femCore->getParticleContactInfos().getTypedPtr();
totalContactCount = femCore->getParticleContactCount().getTypedPtr();
contactByX = femCore->getContactSortedByParticle().getTypedPtr();
tempContactByX = femCore->getTempContactByParticle().getTypedPtr();
contactIndexSortedByX = femCore->getContactRemapSortedByParticle().getTypedPtr();
contactSortedByX = NULL; //Does not exist for particles
}
else
{
outPoint = femCore->getRigidContacts().getTypedPtr();
outNormalPen = femCore->getRigidNormalPens().getTypedPtr();
outBarycentric = femCore->getRigidBarycentrics().getTypedPtr();
outContactInfo = femCore->getRigidContactInfos().getTypedPtr();
totalContactCount = femCore->getRigidContactCount().getTypedPtr();
contactByX = reinterpret_cast<PxU64*>(femCore->getContactByRigid().getTypedPtr());
tempContactByX = femCore->getTempContactByRigid().getTypedPtr();
contactIndexSortedByX = femCore->getContactRemapSortedByRigid().getTypedPtr();
contactSortedByX = reinterpret_cast<PxU32*>(femCore->getContactSortedByRigid().getTypedPtr()); //Cast from larger type to smaller type - no memory overflow
}
maxNumContacts = femCore->mMaxContacts;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE bool writeContactCore(PxU32 index, const float4& contact, const float4& normalPen, PxU64 rigidId)
{
if (index >= maxNumContacts)
return false;
contactByX[index] = rigidId;
tempContactByX[index] = PxU32(rigidId & 0xffffffff);
contactIndexSortedByX[index] = index;
outPoint[index] = contact;
outNormalPen[index] = normalPen;
/*outContactInfo[index].pairInd0 = pairInd0;
outContactInfo[index].pairInd1 = pairInd1;*/
return true;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE bool writeContactNoBarycentric(PxU32 index, const float4& contact, const float4& normalPen,
PxU64 pairInd0, PxU32 pairInd1, PxU64 rigidId)
{
if (index >= maxNumContacts)
return false;
contactByX[index] = rigidId;
tempContactByX[index] = PxU32(rigidId & 0xffffffff);
contactIndexSortedByX[index] = index;
outPoint[index] = contact;
outNormalPen[index] = normalPen;
outContactInfo[index].pairInd0 = pairInd0;
outContactInfo[index].pairInd1 = pairInd1;
return true;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE bool writeRigidVsDeformableContactNoBarycentric(PxU32 index, const float4& contact, const float4& normalPen,
PxU64 pairInd0, PxU32 pairInd1, PxU64 rigidId, PxU32 rigidBodyMaterialId)
{
if (index >= maxNumContacts)
return false;
contactByX[index] = rigidId;
tempContactByX[index] = PxU32(rigidId & 0xffffffff);
contactIndexSortedByX[index] = index;
outPoint[index] = contact;
outNormalPen[index] = normalPen;
PxgFemOtherContactInfo* ptr = reinterpret_cast<PxgFemOtherContactInfo*>(&outContactInfo[index]);
ptr->pairInd0 = pairInd0;
ptr->pairInd1 = pairInd1;
ptr->setRigidMaterialIndex(rigidBodyMaterialId);
ptr->markInCollision(false);
return true;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE bool writeContact(PxU32 index, const float4& contact, const float4& normalPen, const float4& barycentric,
PxU64 pairInd0, PxU32 pairInd1, PxU64 id)
{
if (index >= maxNumContacts)
return false;
writeContactNoBarycentric(index, contact, normalPen, pairInd0, pairInd1, id);
outBarycentric[index] = barycentric;
return true;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE bool writeContact(PxU32 index, const float4& contact, const float4& normalPen, const float4& barycentric,
PxU64 pairInd0, PxU32 pairInd1, PxNodeIndex rigidId)
{
return writeContact(index, contact, normalPen, barycentric, pairInd0, pairInd1, rigidId.getInd());
}
PX_FORCE_INLINE PX_CUDA_CALLABLE bool writeRigidVsDeformableContact(PxU32 index, const float4& contact, const float4& normalPen, const float4& barycentric,
PxU64 pairInd0, PxU32 pairInd1, PxU32 rigidMaterialIndex, PxNodeIndex rigidId)
{
bool result = writeContactCore(index, contact, normalPen, rigidId.getInd());
if (result)
{
outBarycentric[index] = barycentric;
PxgFemOtherContactInfo* femRigidInfo = reinterpret_cast<PxgFemOtherContactInfo*>(outContactInfo);
femRigidInfo[index].pairInd0 = pairInd0;
femRigidInfo[index].pairInd1 = pairInd1;
femRigidInfo[index].setRigidMaterialIndex(rigidMaterialIndex);
femRigidInfo[index].markInCollision(false);
}
return result;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE bool writeRigidVsDeformableContact32(PxU32 index, const float4& contact, const float4& normalPen, const float4& barycentric,
PxU64 pairInd0, PxU32 pairInd1, PxU32 rigidMaterialIndex, PxU32 contactSortedByRigid_)
{
if (index >= maxNumContacts)
return false;
outPoint[index] = contact;
outNormalPen[index] = normalPen;
outBarycentric[index] = barycentric;
PxgFemOtherContactInfo* femRigidInfo = reinterpret_cast<PxgFemOtherContactInfo*>(outContactInfo);
femRigidInfo[index].pairInd0 = pairInd0;
femRigidInfo[index].pairInd1 = pairInd1;
femRigidInfo[index].setRigidMaterialIndex(rigidMaterialIndex);
femRigidInfo[index].markInCollision(false);
contactSortedByX[index] = contactSortedByRigid_;
contactIndexSortedByX[index] = index;
return true;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE bool writeContact32(PxU32 index, const float4& contact, const float4& normalPen, const float4& barycentric,
PxU64 pairInd0, PxU32 pairInd1, PxU32 contactSortedByRigid_)
{
if (index >= maxNumContacts)
return false;
outPoint[index] = contact;
outNormalPen[index] = normalPen;
outBarycentric[index] = barycentric;
outContactInfo[index].pairInd0 = pairInd0;
outContactInfo[index].pairInd1 = pairInd1;
contactSortedByX[index] = contactSortedByRigid_;
contactIndexSortedByX[index] = index;
return true;
}
};
}
#endif

View File

@@ -0,0 +1,212 @@
// 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_INTERPOLATION_H
#define PXG_INTERPOLATION_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec3.h"
#include "foundation/PxVec4.h"
#include "foundation/PxMat44.h"
#include "foundation/PxMathUtils.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
PX_FORCE_INLINE PX_CUDA_CALLABLE PxQuat rotateAroundAxis(const PxQuat& q, PxVec3 rotationAxis, PxReal angle)
{
PxReal mag2 = rotationAxis.magnitudeSquared();
if (mag2 < 1e-8f || angle < 1e-3f)
return q;
rotationAxis *= 1.0f / PxSqrt(mag2);
const PxQuat rot(angle, rotationAxis);
return rot * q;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE PxReal getT(PxReal t, PxReal alpha, const PxVec3& p0, const PxVec3& p1)
{
PxVec3 d = p1 - p0;
PxReal a = d.magnitudeSquared();
PxReal b = PxPow(a, alpha * 0.5f);
return (b + t);
}
PX_FORCE_INLINE PX_CUDA_CALLABLE PxReal lerp(PxReal p0, PxReal p1, PxReal t)
{
return (1.0f - t) * p0 + t * p1;
}
//https://en.wikipedia.org/wiki/Centripetal_CatmullRom_spline
inline PX_CUDA_CALLABLE PxVec3 evaluateSpline(const PxVec3& p0, const PxVec3& p1, const PxVec3& p2,
const PxVec3& p3, PxReal t, PxReal alpha = 0.5f)
{
PxReal t0 = 0.0f;
PxReal t1 = getT(t0, alpha, p0, p1);
PxReal t2 = getT(t1, alpha, p1, p2);
PxReal t3 = getT(t2, alpha, p2, p3);
t = lerp(t1, t2, t);
PxVec3 A1 = ((t1 - t) * p0 + (t - t0) * p1) * (1.0f / PxMax(0.0001f, t1 - t0));
PxVec3 A2 = ((t2 - t) * p1 + (t - t1) * p2)* (1.0f / PxMax(0.0001f, t2 - t1));
PxVec3 A3 = ((t3 - t) * p2 + (t - t2) * p3)* (1.0f / PxMax(0.0001f, t3 - t2));
PxVec3 B1 = ((t2 - t) * A1 + (t - t0) * A2)* (1.0f / PxMax(0.0001f, t2 - t0));
PxVec3 B2 = ((t3 - t) * A2 + (t - t1) * A3)* (1.0f / PxMax(0.0001f, t3 - t1));
PxVec3 C = ((t2 - t) * B1 + (t - t1) * B2)* (1.0f / PxMax(0.0001f, t2 - t1));
return C;
}
inline PX_CUDA_CALLABLE PxVec3 evaluateSpline(const PxVec3 controlPoints[4], PxU32 numControlPoints, PxReal t, PxReal alpha = 0.5f)
{
if (numControlPoints == 1)
return controlPoints[0];
return evaluateSpline(controlPoints[0], controlPoints[1], controlPoints[2], controlPoints[3], t, alpha);
}
PX_FORCE_INLINE PX_CUDA_CALLABLE PxVec3 PxLoad3(const PxVec4& v)
{
PxVec4 tmp = v;
return PxVec3(tmp.x, tmp.y, tmp.z);
}
template<typename V4>
inline PX_CUDA_CALLABLE PxVec3 load3(const V4& val, const PxMat44& transf)
{
return transf.transform(PxLoad3(val));
}
//Handles boundary case and forwards to standard evaluateSpline
template<typename V4>
inline PX_CUDA_CALLABLE PxVec3 evaluateSpline(const V4* points, PxU32 nbPoints, PxU32 index, PxReal t, const PxMat44& transf, PxReal alpha = 0.5f)
{
if (nbPoints == 0)
return PxVec3(0.0f);
if (nbPoints < 2)
return load3(points[0], transf);
if (index > nbPoints - 2)
index = nbPoints - 2;
PxVec3 p0;
if (index == 0)
p0 = load3(points[0], transf) - (load3(points[1], transf) - load3(points[0], transf));
else
p0 = load3(points[index - 1], transf);
PxVec3 p3;
if (index == nbPoints - 2)
p3 = load3(points[nbPoints - 1], transf) + (load3(points[nbPoints - 1], transf) - load3(points[nbPoints - 2], transf));
else
p3 = load3(points[index + 2], transf);
return evaluateSpline(p0, load3(points[index], transf), load3(points[index + 1], transf), p3, t, alpha);
}
template<typename V4>
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU32 catmullRomFetchLastPoint(const V4* points, PxU32 nbPoints, PxU32 index, PxVec3& controlPoint, const PxMat44& transf)
{
if (nbPoints == 0)
{
controlPoint = PxVec3(0.0f);
return 1;
}
if (nbPoints < 2)
{
controlPoint = load3(points[0], transf);
return 1;
}
if (index >= nbPoints - 2)
{
PxVec3 p = load3(points[nbPoints - 1], transf);
controlPoint = p + (p - load3(points[nbPoints - 2], transf));
}
else
controlPoint = load3(points[index + 2], transf);
return 4;
}
inline PX_CUDA_CALLABLE void insertNextControlPoint(PxVec3 controlPoints[4], const PxVec3& nextControlPoint)
{
controlPoints[0] = controlPoints[1];
controlPoints[1] = controlPoints[2];
controlPoints[2] = controlPoints[3];
controlPoints[3] = nextControlPoint;
}
template<typename V4>
inline PX_CUDA_CALLABLE PxU32 catmullRomFetchControlPoints(const V4* points, PxU32 nbPoints, PxU32 index, PxVec3 controlPoints[4], const PxMat44& transf)
{
if (nbPoints == 0)
{
controlPoints[0] = PxVec3(0.0f);
return 1;
}
if (nbPoints < 2)
{
controlPoints[0] = load3(points[0], transf);
return 1;
}
if (index > nbPoints - 2)
index = nbPoints - 2;
if (index <= 0)
{
PxVec3 p = load3(points[0], transf);
controlPoints[0] = p - (load3(points[1], transf) - p);
}
else
controlPoints[0] = load3(points[index - 1], transf);
if (index >= nbPoints - 2)
{
PxVec3 p = load3(points[nbPoints - 1], transf);
controlPoints[3] = p + (p - load3(points[nbPoints - 2], transf));
}
else
controlPoints[3] = load3(points[index + 2], transf);
controlPoints[1] = load3(points[index], transf);
controlPoints[2] = load3(points[index + 1], transf);
return 4;
}
PX_FORCE_INLINE PX_CUDA_CALLABLE PxReal encodeStrandLocation(PxReal uniform, PxU32 segmentIndexInStrand, bool markAsLast)
{
PX_ASSERT(segmentIndexInStrand > 0);
uniform = PxClamp(uniform, 0.0f, 0.999f); //Avoid the uniform to be smaller 0 or exactly 1 because then fractional and integer part cannot be separated reliably
return (markAsLast ? -1.0f : 1.0f) * (uniform + segmentIndexInStrand);
}
PX_FORCE_INLINE PX_CUDA_CALLABLE PxReal decodeStrandLocation(PxReal strandValue, PxU32& segmentIndexInStrand, bool& isLast)
{
isLast = strandValue < 0.0f;
strandValue = PxAbs(strandValue);
segmentIndexInStrand = PxU32(strandValue);
return strandValue - segmentIndexInStrand;
}
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,191 @@
// 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 PX_ISOSURFACE_DATA_H
#define PX_ISOSURFACE_DATA_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec4.h"
#include "PxSparseGridParams.h"
#include "PxgSparseGridDataStandalone.h"
#include "PxgDenseGridDataStandalone.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
/**
\brief Bundles all data used to extract an isosurface on a dense grid
*/
struct PxIsosurfaceExtractionData
{
PxIsosurfaceExtractionData() : mGrid(), kernelSize(0.0f), restDensity(0), threshold(0), firstCellVert(NULL), swapState(0),
numVerticesNumIndices(NULL), maxVerts(0), maxTriIds(0), verts(NULL), normals(NULL), triIds(NULL)
{
}
PxDenseGridData mGrid;
PxReal kernelSize;
PxReal restDensity;
PxReal threshold;
// grid
PxReal* buffer[2];
PxU32* firstCellVert;
PxU32 swapState;
// mesh
PxU32* numVerticesNumIndices; //Pointer to a GPU buffer to allow for device to host copy
PxU32 maxVerts, maxTriIds;
PxVec4* verts;
PxVec4* normals;
PxU32* triIds;
PxVec4* smoothingBuffer;
/**
\brief Access to the density device array
\return The density devixe array
*/
PX_CUDA_CALLABLE PxReal* density()
{
return buffer[swapState];
}
/**
\brief Access to the start triangle id per cell device array
\return The start triangle id per cell device array
*/
PX_CUDA_CALLABLE PxU32* firstCellTriId()
{
return reinterpret_cast<PxU32*>(buffer[1 - swapState]);
}
/**
\brief The grid's cell size
\return The cell size
*/
PX_CUDA_CALLABLE PxReal getSpacing()
{
return mGrid.mGridParams.gridSpacing;
}
/**
\brief The number of cells in the dense grid
\return The number of cells
*/
PX_CUDA_CALLABLE PxU32 maxNumCells()
{
return mGrid.maxNumCells();
}
};
/**
\brief Bundles all data used to extract an isosurface on a sparse grid
*/
struct PxSparseIsosurfaceExtractionData
{
PxSparseIsosurfaceExtractionData() : mGrid(), kernelSize(0.0f), restDensity(0), threshold(0), firstCellVert(NULL), swapState(0),
numVerticesNumIndices(NULL), maxVerts(0), maxTriIds(0), verts(NULL), normals(NULL), triIds(NULL)
{
}
PxSparseGridData mGrid;
PxReal* buffer[2];
PxReal kernelSize;
PxReal restDensity;
PxReal threshold;
PxU32* firstCellVert;
PxU32 swapState;
// mesh
PxU32* numVerticesNumIndices; //Pointer to a GPU buffer to allow for device to host copy
PxU32 maxVerts, maxTriIds;
PxVec4* verts;
PxVec4* normals;
PxU32* triIds;
PxVec4* smoothingBuffer;
/**
\brief Access to the density device array
\return The density device array
*/
PX_CUDA_CALLABLE PxReal* density()
{
return buffer[swapState];
}
/**
\brief Access to the start triangle id per cell device array
\return The start triangle id per cell device array
*/
PX_CUDA_CALLABLE PxU32* firstCellTriId()
{
return reinterpret_cast<PxU32*>(buffer[1 - swapState]);
}
/**
\brief The grid's cell size
\return The cell size
*/
PX_CUDA_CALLABLE PxReal getSpacing()
{
return mGrid.mGridParams.gridSpacing;
}
/**
\brief The maximal number of cells in the sparse grid, not all of them are always in use
\return The number of cells
*/
PX_CUDA_CALLABLE PxU32 maxNumCells()
{
return mGrid.maxNumCells();
}
};
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,301 @@
// 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_ISOSURFACE_EXTRACTION_H
#define PXG_ISOSURFACE_EXTRACTION_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec4.h"
#include "PxSparseGridParams.h"
#include "foundation/PxArray.h"
#include "PxIsosurfaceExtraction.h"
#include "PxgSparseGridStandalone.h"
#include "PxgAlgorithms.h"
#include "PxgIsosurfaceData.h"
#include "PxgKernelLauncher.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
#if PX_SUPPORT_GPU_PHYSX
class PxgSharedIsosurfaceExtractor
{
public:
bool mEnabled;
PxIsosurfaceParams mIsosurfaceParams;
PxGpuScan mScan;
PxgKernelLauncher mKernelLauncher;
PxU32* mNumVerticesNumIndices;
bool mOwnsOutputGPUBuffers;
PxVec4* mVertices;
PxVec4* mNormals;
PxU32* mTriIndices;
//public:
PxgSharedIsosurfaceExtractor() : mEnabled(true), mKernelLauncher(), mNumVerticesNumIndices(NULL), mOwnsOutputGPUBuffers(false),
mVertices(NULL), mNormals(NULL), mTriIndices(NULL)
{}
virtual ~PxgSharedIsosurfaceExtractor() {}
template<typename DenseOrSparseGpuDataPackage>
void extractIso(DenseOrSparseGpuDataPackage& mData, PxVec4* deviceParticlePos, const PxU32 numParticles, CUstream stream, PxU32* phases, PxU32 validPhaseMask,
PxU32* activeIndices = NULL, PxVec4* anisotropy1 = NULL, PxVec4* anisotropy2 = NULL, PxVec4* anisotropy3 = NULL, PxReal anisotropyFactor = 1.0f);
template<typename DenseOrSparseGpuDataPackage>
void meshFromDensity(DenseOrSparseGpuDataPackage& mData, CUstream stream);
};
/**
\brief GPU based isosurface extractor operating on a sparse grid
*/
class PxgSparseGridIsosurfaceExtractor : public PxSparseGridIsosurfaceExtractor, public PxUserAllocated
{
protected:
PxgSharedIsosurfaceExtractor mShared;
PxSparseIsosurfaceExtractionData mData;
PxSparseGridBuilder mSparseGrid;
void paramsToMCData();
virtual void setMaxVerticesAndTriangles(PxU32 maxIsosurfaceVertices, PxU32 maxIsosurfaceTriangles);
virtual void releaseGPUBuffers();
virtual void allocateGPUBuffers();
public:
PxgSparseGridIsosurfaceExtractor() : mShared()
{}
PxgSparseGridIsosurfaceExtractor(PxgKernelLauncher& cudaContextManager, const PxSparseGridParams sparseGridParams,
const PxIsosurfaceParams& isosurfaceParams, PxU32 maxNumParticles, PxU32 maxNumVertices, PxU32 maxNumTriangles) : mShared()
{
initialize(cudaContextManager, sparseGridParams, isosurfaceParams, maxNumParticles, maxNumVertices, maxNumTriangles);
}
virtual void setResultBufferDevice(PxVec4* vertices, PxU32* triIndices, PxVec4* normals);
virtual ~PxgSparseGridIsosurfaceExtractor() { }
void initialize(PxgKernelLauncher& cudaContextManager, const PxSparseGridParams sparseGridParams,
const PxIsosurfaceParams& isosurfaceParams, PxU32 maxNumParticles, PxU32 maxNumVertices, PxU32 maxNumTriangles);
virtual void release();
virtual void setIsosurfaceParams(const PxIsosurfaceParams& params)
{
mShared.mIsosurfaceParams = params;
paramsToMCData();
}
virtual void clearDensity(CUstream stream);
virtual PxU32 getMaxParticles() const
{
return mSparseGrid.getMaxParticles();
}
virtual PxU32 getMaxVertices() const
{
return mData.maxVerts;
}
virtual PxU32 getMaxTriangles() const
{
return mData.maxTriIds / 3;
}
virtual void setMaxParticles(PxU32 maxParticles);
virtual void extractIsosurface(PxVec4* deviceParticlePos, const PxU32 numParticles, CUstream stream, PxU32* phases = NULL, PxU32 validPhaseMask = PxParticlePhaseFlag::eParticlePhaseFluid,
PxU32* activeIndices = NULL, PxVec4* anisotropy1 = NULL, PxVec4* anisotropy2 = NULL, PxVec4* anisotropy3 = NULL, PxReal anisotropyFactor = 1.0f);
virtual void setResultBufferHost(PxVec4* vertices, PxU32* triIndices, PxVec4* normals);
virtual PxIsosurfaceParams getIsosurfaceParams() const
{
return mShared.mIsosurfaceParams;
}
virtual PxU32 getNumVertices() const
{
if (!mShared.mNumVerticesNumIndices)
return 0;
return mShared.mNumVerticesNumIndices[0];
}
virtual PxU32 getNumTriangles() const
{
if (!mShared.mNumVerticesNumIndices)
return 0;
return mShared.mNumVerticesNumIndices[1] / 3;
}
virtual void setEnabled(bool enabled)
{
mShared.mEnabled = enabled;
}
virtual bool isEnabled() const
{
return mShared.mEnabled;
}
virtual PxSparseGridParams getSparseGridParams() const
{
return mSparseGrid.getGridParameters();
}
virtual void setSparseGridParams(const PxSparseGridParams& params)
{
mSparseGrid.setGridParameters(params);
}
};
/**
\brief GPU based isosurface extractor operating on a dense grid
*/
class PxgDenseGridIsosurfaceExtractor : public PxIsosurfaceExtractor, public PxUserAllocated
{
protected:
PxgSharedIsosurfaceExtractor mShared;
PxIsosurfaceExtractionData mData;
PxU32 mMaxParticles; //For compatibility with sparse grid isosurface extractor. There is no upper particle limit on the dense grid extractor.
void paramsToMCData();
virtual void setMaxVerticesAndTriangles(PxU32 maxIsosurfaceVertices, PxU32 maxIsosurfaceTriangles);
virtual void releaseGPUBuffers();
virtual void allocateGPUBuffers();
public:
PxgDenseGridIsosurfaceExtractor() : mShared()
{}
PxgDenseGridIsosurfaceExtractor(PxgKernelLauncher& cudaContextManager, const PxBounds3& worldBounds,
PxReal cellSize, const PxIsosurfaceParams& isosurfaceParams, PxU32 maxNumParticles, PxU32 maxNumVertices, PxU32 maxNumTriangles) : mShared()
{
initialize(cudaContextManager, worldBounds, cellSize, isosurfaceParams, maxNumParticles, maxNumVertices, maxNumTriangles);
}
virtual void setResultBufferDevice(PxVec4* vertices, PxU32* triIndices, PxVec4* normals);
virtual ~PxgDenseGridIsosurfaceExtractor() { }
void initialize(PxgKernelLauncher& cudaContextManager, const PxBounds3& worldBounds,
PxReal cellSize, const PxIsosurfaceParams& isosurfaceParams, PxU32 maxNumParticles, PxU32 maxNumVertices, PxU32 maxNumTriangles);
virtual void release();
virtual void setIsosurfaceParams(const PxIsosurfaceParams& params)
{
mShared.mIsosurfaceParams = params;
paramsToMCData();
}
virtual void clearDensity(CUstream stream);
virtual PxU32 getMaxParticles() const
{
return mMaxParticles;
}
virtual PxU32 getMaxVertices() const
{
return mData.maxVerts;
}
virtual PxU32 getMaxTriangles() const
{
return mData.maxTriIds / 3;
}
virtual void setMaxParticles(PxU32 maxParticles)
{
//No need to resize internal buffers on the dense grid isosurface;
mMaxParticles = maxParticles;
}
virtual void extractIsosurface(PxVec4* deviceParticlePos, const PxU32 numParticles, CUstream stream, PxU32* phases = NULL, PxU32 validPhaseMask = PxParticlePhaseFlag::eParticlePhaseFluid,
PxU32* activeIndices = NULL, PxVec4* anisotropy1 = NULL, PxVec4* anisotropy2 = NULL, PxVec4* anisotropy3 = NULL, PxReal anisotropyFactor = 1.0f);
virtual void setResultBufferHost(PxVec4* vertices, PxU32* triIndices, PxVec4* normals);
virtual PxIsosurfaceParams getIsosurfaceParams() const
{
return mShared.mIsosurfaceParams;
}
virtual PxU32 getNumVertices() const
{
if (!mShared.mNumVerticesNumIndices)
return 0;
return mShared.mNumVerticesNumIndices[0];
}
virtual PxU32 getNumTriangles() const
{
if (!mShared.mNumVerticesNumIndices)
return 0;
return mShared.mNumVerticesNumIndices[1] / 3;
}
virtual void setEnabled(bool enabled)
{
mShared.mEnabled = enabled;
}
virtual bool isEnabled() const
{
return mShared.mEnabled;
}
};
#endif
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,162 @@
// 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_JOINT_MANAGER_H
#define PXG_JOINT_MANAGER_H
#include "foundation/PxPinnedArray.h"
#include "foundation/PxHashMap.h"
#include "CmIDPool.h"
#include "PxgD6JointData.h"
#include "PxgConstraintPrep.h"
#include "PxgConstraintIdMap.h"
namespace physx
{
namespace IG
{
class IslandSim;
class CPUExternalData;
class GPUExternalData;
}
namespace Dy
{
struct Constraint;
}
struct PxgSolverConstraintManagerConstants;
//This manager should separate the joint types because we just support D6Joint in the constaint pre-prepare code
class PxgJointManager
{
public:
typedef PxPinnedArray<PxgConstraintIdMapEntry> ConstraintIdMap;
PxgJointManager(const PxVirtualAllocator& allocator, bool isDirectGpuApiEnabled);
~PxgJointManager();
void reserveMemory(PxU32 maxConstraintRows);
void reserveMemoryPreAddRemove(); // reserveMemory() above can not be used because it gets called after
// joints get added/removed during constraint partitioning
void registerJoint(const Dy::Constraint& constraint);
void removeJoint(PxU32 edgeIndex, PxArray<PxU32>& jointIndices, const IG::CPUExternalData& islandSimCpuData, const IG::GPUExternalData& islandSimGpuData);
void addJoint( PxU32 edgeIndex, const Dy::Constraint* constraint, IG::IslandSim& islandSim, PxArray<PxU32>& jointIndices,
PxPinnedArray<PxgSolverConstraintManagerConstants>& managerIter, PxU32 uniqueId);
void updateJoint(PxU32 edgeIndex, const Dy::Constraint* constraint);
void update(PxArray<PxU32>& jointOutputIndex);
void reset();
PxU32 getGpuNbRigidConstraints();
PxU32 getGpuNbArtiConstraints();
PxU32 getCpuNbRigidConstraints();
PxU32 getCpuNbArtiConstraints();
PxU32 getGpuNbActiveRigidConstraints();
PxU32 getGpuNbActiveArtiConstraints();
PX_FORCE_INLINE const PxArray<const Dy::Constraint*>& getCpuRigidConstraints() const { return mCpuRigidConstraints; }
PX_FORCE_INLINE const PxArray<const Dy::Constraint*>& getCpuArtiConstraints() const { return mCpuArtiConstraints; }
PX_FORCE_INLINE const PxInt32ArrayPinned& getDirtyGPURigidJointDataIndices() const { return mDirtyGPURigidJointDataIndices; }
PX_FORCE_INLINE const PxInt32ArrayPinned& getDirtyGPUArtiJointDataIndices() const { return mDirtyGPUArtiJointDataIndices; }
PX_FORCE_INLINE const PxPinnedArray<PxgD6JointData>& getGpuRigidJointData() const { return mGpuRigidJointData; }
PX_FORCE_INLINE const PxPinnedArray<PxgD6JointData>& getGpuArtiJointData() const { return mGpuArtiJointData; }
PX_FORCE_INLINE const PxPinnedArray<PxgConstraintPrePrep>& getGpuRigidJointPrePrep() const { return mGpuRigidJointPrePrep; }
PX_FORCE_INLINE const PxPinnedArray<PxgConstraintPrePrep>& getGpuArtiJointPrePrep() const { return mGpuArtiJointPrePrep; }
// PT: these ones are contained in this class but actually filled by external code, PxgJointManager doesn't touch them.(*)
PX_FORCE_INLINE PxPinnedArray<PxgConstraintData>& getCpuRigidConstraintData() { return mCpuRigidConstraintData; }
PX_FORCE_INLINE PxPinnedArray<PxgConstraintData>& getCpuArtiConstraintData() { return mCpuArtiConstraintData; }
PX_FORCE_INLINE PxPinnedArray<Px1DConstraint>& getCpuRigidConstraintRows() { return mCpuRigidConstraintRows; }
PX_FORCE_INLINE PxPinnedArray<Px1DConstraint>& getCpuArtiConstraintRows() { return mCpuArtiConstraintRows; }
PX_FORCE_INLINE const ConstraintIdMap& getGpuConstraintIdMapHost() const { return mGpuConstraintIdMapHost; }
PX_FORCE_INLINE bool getAndClearConstraintIdMapDirtyFlag()
{
const bool isDirty = mIsGpuConstraintIdMapDirty;
mIsGpuConstraintIdMapDirty = false;
return isDirty;
}
private:
PxHashMap<PxU32, PxU32> mGpuRigidConstraintIndices;
PxHashMap<PxU32, PxU32> mGpuArtiConstraintIndices;
PxHashMap<PxU32, PxU32> mCpuRigidConstraintIndices;
PxHashMap<PxU32, PxU32> mCpuArtiConstraintIndices;
PxArray<const Dy::Constraint*> mCpuRigidConstraints;
PxArray<const Dy::Constraint*> mCpuArtiConstraints;
PxArray<PxU32> mCpuRigidUniqueIndex;
PxArray<PxU32> mCpuArtiUniqueIndex;
PxArray<PxU32> mCpuRigidConstraintEdgeIndices;
PxArray<PxU32> mCpuArtiConstraintEdgeIndices;
PxPinnedArray<PxgD6JointData> mGpuRigidJointData; // this is the input (PxgD6JointData) for rigid body we need to DMA to GPU so that GPU can fill in PxgConstraintData
PxPinnedArray<PxgD6JointData> mGpuArtiJointData; // this is the input (PxgD6JointData) for articulation we need to DMA to GPU so that GPU can fill in PxgConstraintData
PxPinnedArray<PxgConstraintPrePrep> mGpuRigidJointPrePrep; // this is the input (PxgConstraintPrePrep) for rigid body we need to DMA to GPU so that GPU can fill in PxgConstraintData
PxPinnedArray<PxgConstraintPrePrep> mGpuArtiJointPrePrep; // this is the input (PxgConstraintPrePrep) for articulation we need to DMA to GPU so that GPU can fill in PxgConstraintData
PxPinnedArray<PxgConstraintData> mCpuRigidConstraintData; // (*) this need to append to the GPU result (PxgConstraintData) after the first past pre-prepare code
PxPinnedArray<Px1DConstraint> mCpuRigidConstraintRows; // (*) this need to append to the GPU result (Px1DConstraint) after the first past pre-prepare code
PxPinnedArray<PxgConstraintData> mCpuArtiConstraintData; // (*) this need to append to the GPU result (PxgConstraintData) after the first past pre-prepare code
PxPinnedArray<Px1DConstraint> mCpuArtiConstraintRows; // (*) this need to append to the GPU result (Px1DConstraint) after the first past pre-prepare code
PxInt32ArrayPinned mDirtyGPURigidJointDataIndices; // the dirty list indices of PxgD6JointData
PxInt32ArrayPinned mDirtyGPUArtiJointDataIndices; // the dirty list indices of PxgD6JointData
ConstraintIdMap mGpuConstraintIdMapHost; // See PxgConstraintIdMapEntry for details. Only used when direct GPU API is enabled and
// for joint/constraints that have the shader run on GPU.
PxHashMap<PxU32, PxU32> mEdgeIndexToGpuConstraintIdMap; // Get from edge index to constraint ID. Only used when direct GPU API is
// enabled and for joint/constraints that have the shader run on GPU.
Cm::IDPool mGpuRigidJointDataIDPool; //each PxgD6JointData has an unique id. We can recycle the id when a joint has been removed from the joint manager
Cm::IDPool mGpuArtiJointDataIDPool;
public:
// PT: not sure why these are here, it's computed by PxgGpuContext at the same time it fills the CPU constraint data (*)
PxI32 mNbCpuRigidConstraintRows;
PxI32 mNbCpuArtiConstraintRows;
private:
PxU32 mMaxConstraintId;
// Tracks all-time highest constraint ID to reserve sufficient space for mGpuConstraintIdMapHost.
bool mIsGpuConstraintIdMapDirty; // set to true when mGpuConstraintIdMapHost changed and needs to get sent to GPU
const bool mIsDirectGpuApiEnabled;
};
}
#endif

View File

@@ -0,0 +1,298 @@
// 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_KERNEL_LAUNCHER_H
#define PXG_KERNEL_LAUNCHER_H
#include "cudamanager/PxCudaContextManager.h"
#include "CudaKernelWrangler.h"
#include "PxgKernelWrangler.h"
#include "cudamanager/PxCudaContext.h"
#include "foundation/PxString.h"
#define KERNEL_LAUNCH_ERROR_CHECK 0
namespace physx
{
// PT: do not inline this
static PX_NOINLINE void outputKernelLaunchDebugInfo(KernelWrangler* kernelWrangler, PxU16 id, const char* file, PxU32 line)
{
char errorMsg[4096];
physx::Pxsnprintf(errorMsg, 4096, "Launching GPU kernel %s...\n", kernelWrangler->getCuFunctionName(id));
PxGetFoundation().error(PxErrorCode::eDEBUG_INFO, file, line, errorMsg);
}
// PT: do not inline this
static PX_NOINLINE void outputKernelLaunchError(KernelWrangler* kernelWrangler, PxU16 kernelId, PxCUresult result, const char* file, PxU32 line)
{
char errorMsg[4096];
physx::Pxsnprintf(errorMsg, 4096, "GPU kernel '%s' failed to launch with error %u!!\n",
kernelWrangler->getCuFunctionName(kernelId), result.value);
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, file, line, errorMsg);
}
//do not inline this
static PX_NOINLINE void outputKernelLaunchSyncError(KernelWrangler* kernelWrangler, PxU16 kernelId, PxCUresult result, const char* file, PxU32 line)
{
char buffer[4096];
physx::Pxsnprintf(buffer, 4096, "GPU kernel '%s' execution failed with error %u!\n",
kernelWrangler->getCuFunctionName(kernelId), result.value);
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, file, line, buffer);
}
template<const bool debugExecution>
static PX_FORCE_INLINE PxCUresult _testLaunch(PxCUresult resultR, KernelWrangler* kernelWrangler, PxCudaContext* ctx, PxU16 kernelId, CUstream hStream, const char* file, PxU32 line)
{
// PT: don't assert immediately, we want to print the failing kernel's name first
if(resultR != CUDA_SUCCESS)
outputKernelLaunchError(kernelWrangler, kernelId, resultR, file, line);
else if(debugExecution)
{
// PT: launching the kernel might have worked but executing the kernel is a different thing that can also fail.
// This is only for debugging so code bloat won't matter here, and we can inline the whole thing.
// This assumes the compiler removes all of it, which should work because we use a template for debugExecution.
const PxCUresult syncErr = ctx->streamSynchronize(hStream);
// PT: here again, don't assert immediately
if(syncErr != CUDA_SUCCESS)
{
outputKernelLaunchSyncError(kernelWrangler, kernelId, syncErr, file, line);
/*char buffer[4096];
physx::Pxsnprintf(buffer, 4096, "GPU kernel '%s' execution failed with error %u!\n",
kernelWrangler->getCuFunctionName(kernelId), syncErr.value);
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, file, line, buffer);*/
}
PX_ASSERT(syncErr == CUDA_SUCCESS);
}
PX_ASSERT(resultR == CUDA_SUCCESS);
return resultR;
}
// PT: this one is for the regular launchKernel function
template<const bool debugExecution>
static PX_FORCE_INLINE PxCUresult _launch(
KernelWrangler* kernelWrangler, PxCudaContext* ctx, PxU16 kernelId,
PxU32 gridDimX, PxU32 gridDimY, PxU32 gridDimZ,
PxU32 blockDimX, PxU32 blockDimY, PxU32 blockDimZ,
PxU32 sharedMemBytes, CUstream hStream,
PxCudaKernelParam* kernelParams, size_t kernelParamsSizeInBytes,
const char* file, PxU32 line)
{
if (0)
outputKernelLaunchDebugInfo(kernelWrangler, kernelId, file, line);
const PxCUresult resultR = ctx->launchKernel(kernelWrangler->getCuFunction(kernelId),
gridDimX, gridDimY, gridDimZ,
blockDimX, blockDimY, blockDimZ,
sharedMemBytes, hStream,
kernelParams, kernelParamsSizeInBytes,
NULL,
file, line);
return _testLaunch<debugExecution>(resultR, kernelWrangler, ctx, kernelId, hStream, file, line);
}
// PT: this one is for the new 'optimized' launchKernel function
template<const bool debugExecution>
static PX_FORCE_INLINE PxCUresult _launch(
KernelWrangler* kernelWrangler, PxCudaContext* ctx, PxU16 kernelId,
PxU32 gridDimX, PxU32 gridDimY, PxU32 gridDimZ,
PxU32 blockDimX, PxU32 blockDimY, PxU32 blockDimZ,
PxU32 sharedMemBytes, CUstream hStream,
void** kernelParams,
const char* file, PxU32 line)
{
if (0)
outputKernelLaunchDebugInfo(kernelWrangler, kernelId, file, line);
const PxCUresult resultR = ctx->launchKernel(kernelWrangler->getCuFunction(kernelId),
gridDimX, gridDimY, gridDimZ,
blockDimX, blockDimY, blockDimZ,
sharedMemBytes, hStream,
kernelParams,
NULL,
file, line);
return _testLaunch<debugExecution>(resultR, kernelWrangler, ctx, kernelId, hStream, file, line);
}
class PxgKernelLauncher
{
private:
static PX_FORCE_INLINE PxU32 divideRoundUp(PxU32 a, PxU32 b)
{
return (a + b - 1) / b;
}
//https://riptutorial.com/cplusplus/example/3208/iterating-over-a-parameter-pack
static void packArguments(PxCudaKernelParam* /*buffer*/, const PxU32 /*index*/)
{
// base case
}
template <class T, class... Ts>
static void packArguments(PxCudaKernelParam* buffer, const PxU32 index, T const* first, Ts const*... rest)
{
buffer[index].data = const_cast<void*>(static_cast<void const*>(first));
buffer[index].size = sizeof(*first);
packArguments(buffer, index + 1, rest...);
}
//https://riptutorial.com/cplusplus/example/3208/iterating-over-a-parameter-pack
static void packArgumentsPointerOnly(void** /*buffer*/, const PxU32 /*index*/)
{
// base case
}
template <class T, class... Ts>
static void packArgumentsPointerOnly(void** buffer, const PxU32 index, T const* first, Ts const*... rest)
{
buffer[index] = const_cast<void*>(static_cast<void const*>(first));
packArgumentsPointerOnly(buffer, index + 1, rest...);
}
public:
static PX_FORCE_INLINE PxCUresult launchKernel(PxCudaContext* cudaContext, PxgCudaKernelWranglerManager* gpuKernelWranglerManager,
PxU16 kernelFunctionId, PxU32 gridDimX, PxU32 gridDimY, PxU32 gridDimZ,
PxU32 blockDimX, PxU32 blockDimY, PxU32 blockDimZ, PxU32 sharedMemBytes, CUstream stream, PxCudaKernelParam* kernelParams, PxU32 kernelParamsSize)
{
return _launch<KERNEL_LAUNCH_ERROR_CHECK>(gpuKernelWranglerManager->mKernelWrangler, cudaContext, kernelFunctionId,
gridDimX, gridDimY, gridDimZ, blockDimX, blockDimY, blockDimZ,
sharedMemBytes, stream, kernelParams, kernelParamsSize, PX_FL);
}
static PX_FORCE_INLINE PxCUresult launchKernel(PxCudaContext* cudaContext, PxgCudaKernelWranglerManager* gpuKernelWranglerManager,
PxU16 kernelFunctionId, PxU32 gridDimX, PxU32 gridDimY, PxU32 gridDimZ,
PxU32 blockDimX, PxU32 blockDimY, PxU32 blockDimZ, PxU32 sharedMemBytes, CUstream stream, void** kernelParams)
{
return _launch<KERNEL_LAUNCH_ERROR_CHECK>(gpuKernelWranglerManager->mKernelWrangler, cudaContext, kernelFunctionId,
gridDimX, gridDimY, gridDimZ, blockDimX, blockDimY, blockDimZ,
sharedMemBytes, stream, kernelParams, PX_FL);
}
static PX_FORCE_INLINE PxCUresult launchKernelBlocks(PxCudaContext* cudaContext, PxgCudaKernelWranglerManager* gpuKernelWranglerManager,
PxU16 kernelFunctionId, PxU32 numBlocks, PxU32 numThreadsPerBlock, PxU32 sharedMemBytes, CUstream stream, PxCudaKernelParam* kernelParams, PxU32 kernelParamsSize)
{
return launchKernel(cudaContext, gpuKernelWranglerManager, kernelFunctionId, numBlocks, 1, 1, numThreadsPerBlock, 1, 1, sharedMemBytes, stream, kernelParams, kernelParamsSize);
}
template <class ...Args>
static PX_FORCE_INLINE PxCUresult launchKernelAutoPackParameters(PxCudaContext* cudaContext, PxgCudaKernelWranglerManager* gpuKernelWranglerManager,
PxU16 kernelFunctionId, PxU32 gridDimX, PxU32 gridDimY, PxU32 gridDimZ,
PxU32 blockDimX, PxU32 blockDimY, PxU32 blockDimZ, PxU32 sharedMemBytes, CUstream stream, const Args&... args)
{
PxCudaKernelParam p[sizeof...(args)];
packArguments(p, 0, &args...);
return launchKernel(cudaContext, gpuKernelWranglerManager, kernelFunctionId, gridDimX, gridDimY, gridDimZ,
blockDimX, blockDimY, blockDimZ, sharedMemBytes, stream, p, sizeof(p));
}
template <class ...Args>
static PX_FORCE_INLINE PxCUresult launchKernelBlocksAutoPackParameters(PxCudaContext* cudaContext, PxgCudaKernelWranglerManager* gpuKernelWranglerManager,
PxU16 kernelFunctionId, PxU32 numBlocks, PxU32 numThreadsPerBlock, PxU32 sharedMemBytes, CUstream stream, const Args&... args)
{
PxCudaKernelParam p[sizeof...(args)];
packArguments(p, 0, &args...);
return launchKernelBlocks(cudaContext, gpuKernelWranglerManager, kernelFunctionId, numBlocks,
numThreadsPerBlock, sharedMemBytes, stream, p, sizeof(p));
}
static PX_FORCE_INLINE PxCUresult launchKernelThreads(PxCudaContext* cudaContext, PxgCudaKernelWranglerManager* gpuKernelWranglerManager,
PxU16 kernelFunctionId, PxU32 totalNumThreads, PxU32 numThreadsPerBlock, PxU32 sharedMemBytes, CUstream stream, PxCudaKernelParam* kernelParams, PxU32 kernelParamsSize)
{
return launchKernelBlocks(cudaContext, gpuKernelWranglerManager, kernelFunctionId, divideRoundUp(totalNumThreads, numThreadsPerBlock),
numThreadsPerBlock, sharedMemBytes, stream, kernelParams, kernelParamsSize);
}
template <class ...Args>
static PX_FORCE_INLINE PxCUresult launchKernelThreadsAutoPackParameters(PxCudaContext* cudaContext, PxgCudaKernelWranglerManager* gpuKernelWranglerManager,
PxU16 kernelFunctionId, PxU32 totalNumThreads, PxU32 numThreadsPerBlock, PxU32 sharedMemBytes, CUstream stream, const Args&... args)
{
PxCudaKernelParam p[sizeof...(args)];
packArguments(p, 0, &args...);
return launchKernelThreads(cudaContext, gpuKernelWranglerManager, kernelFunctionId, totalNumThreads,
numThreadsPerBlock, sharedMemBytes, stream, p, sizeof(p));
}
PxgKernelLauncher()
: mCudaContextManager(NULL), mGpuKernelWranglerManager(NULL) {}
PxgKernelLauncher(PxCudaContextManager* cudaContextManager, PxgCudaKernelWranglerManager* gpuKernelWranglerManager)
: mCudaContextManager(cudaContextManager), mGpuKernelWranglerManager(gpuKernelWranglerManager) {}
PX_FORCE_INLINE PxCudaContextManager* getCudaContextManager() { return mCudaContextManager; }
PX_FORCE_INLINE const PxCudaContextManager* getCudaContextManager() const { return mCudaContextManager; }
PX_FORCE_INLINE PxgCudaKernelWranglerManager* getKernelWrangler() { return mGpuKernelWranglerManager; }
PX_FORCE_INLINE const PxgCudaKernelWranglerManager* getKernelWrangler() const { return mGpuKernelWranglerManager; }
template <class ...Args>
PxCUresult launchKernel(PxU16 kernelId, PxU32 numBlocks, PxU32 numThreadsPerBlock, PxU32 sharedMemorySize, CUstream stream, const Args&... args)
{
void* p[sizeof...(args)];
packArgumentsPointerOnly(p, 0, &args...);
return PxgKernelLauncher::launchKernel(getCudaContextManager()->getCudaContext(), getKernelWrangler(),
kernelId, numBlocks, 1, 1, numThreadsPerBlock, 1, 1, sharedMemorySize, stream, p);
}
template <class ...Args>
PxCUresult launchKernelXYZ(PxU16 kernelId, PxU32 numBlocksX, PxU32 numBlocksY, PxU32 numBlocksZ,
PxU32 numThreadsPerBlockX, PxU32 numThreadsPerBlockY, PxU32 numThreadsPerBlockZ, PxU32 sharedMemorySize, CUstream stream, const Args&... args)
{
void* p[sizeof...(args)];
packArgumentsPointerOnly(p, 0, &args...);
return PxgKernelLauncher::launchKernel(getCudaContextManager()->getCudaContext(), getKernelWrangler(),
kernelId, numBlocksX, numBlocksY, numBlocksZ, numThreadsPerBlockX, numThreadsPerBlockY, numThreadsPerBlockZ, sharedMemorySize, stream, p);
}
template <class ...Args>
PxCUresult launchKernelPtr(PxU16 kernelId, PxU32 numBlocks, PxU32 numThreadsPerBlock, PxU32 sharedMemorySize, CUstream stream, const Args*... args)
{
void* p[sizeof...(args)];
packArgumentsPointerOnly(p, 0, args...);
return PxgKernelLauncher::launchKernel(getCudaContextManager()->getCudaContext(), getKernelWrangler(),
kernelId, numBlocks, 1, 1, numThreadsPerBlock, 1, 1, sharedMemorySize, stream, p);
}
template <class ...Args>
PxCUresult launchKernelXYZPtr(PxU16 kernelId, PxU32 numBlocksX, PxU32 numBlocksY, PxU32 numBlocksZ,
PxU32 numThreadsPerBlockX, PxU32 numThreadsPerBlockY, PxU32 numThreadsPerBlockZ, PxU32 sharedMemorySize, CUstream stream, const Args*... args)
{
void* p[sizeof...(args)];
packArgumentsPointerOnly(p, 0, args...);
return PxgKernelLauncher::launchKernel(getCudaContextManager()->getCudaContext(), getKernelWrangler(),
kernelId, numBlocksX, numBlocksY, numBlocksZ, numThreadsPerBlockX, numThreadsPerBlockY, numThreadsPerBlockZ, sharedMemorySize, stream, p);
}
private:
PxCudaContextManager* mCudaContextManager;
PxgCudaKernelWranglerManager* mGpuKernelWranglerManager;
};
}
#endif

View File

@@ -0,0 +1,117 @@
// 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_NONRIGID_CORE_COMMON_H
#define PXG_NONRIGID_CORE_COMMON_H
#include "PxgCudaBuffer.h"
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec3.h"
#include "foundation/PxVec4.h"
#include "PxgCudaPagedLinearAllocator.h"
#include "PxgRadixSortDesc.h"
#include "foundation/PxPinnedArray.h"
#include "PxgEssentialCore.h"
#include "PxNodeIndex.h"
namespace physx
{
class PxgCudaKernelWranglerManager;
class PxCudaContextManager;
class PxgHeapMemoryAllocatorManager;
struct PxGpuDynamicsMemoryConfig;
class PxgSimulationController;
class PxgCudaBroadPhaseSap;
class PxgGpuNarrowphaseCore;
class PxgGpuContext;
class PxgNonRigidCore : public PxgEssentialCore
{
public:
PxgNonRigidCore(PxgCudaKernelWranglerManager* gpuKernelWrangler, PxCudaContextManager* cudaContextManager,
PxgHeapMemoryAllocatorManager* heapMemoryManager, PxgSimulationController* simController,
PxgGpuContext* context, const PxU32 maxContacts, const PxU32 collisionStackSize, PxsHeapStats::Enum statType);
virtual ~PxgNonRigidCore();
void updateGPURadixSortBlockDesc(CUstream stream, CUdeviceptr inputKeyd, CUdeviceptr inputRankd,
CUdeviceptr outputKeyd, CUdeviceptr outputRankd, CUdeviceptr radixCountd,
CUdeviceptr numKeysd, PxgRadixSortBlockDesc* rsDescs,
CUdeviceptr radixSortDescBuf0, CUdeviceptr radixSortDescBuf1);
PX_FORCE_INLINE PxgTypedCudaBuffer<PxNodeIndex>& getContactByRigid() { return mContactByRigidBuf; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxNodeIndex>& getContactSortedByRigid() { return mContactSortedByRigidBuf; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getTempContactByRigid() { return mTempContactByRigidBitBuf; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getContactRemapSortedByRigid() { return mContactRemapSortedByRigidBuf; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU64>& getContactSortedByParticle() { return mContactSortedByParticleBuf; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getTempContactByParticle() { return mTempContactByParticleBitBuf; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getContactRemapSortedByParticle() { return mContactRemapSortedByParticleBuf; }
PxgCudaPagedLinearAllocator<PxgHeapMemoryAllocator> mIntermStackAlloc;
PxgTypedCudaBuffer<PxU32> mStackSizeNeededOnDevice;
PxU32* mStackSizeNeededPinned;
PxU32 mMaxContacts;
PxU32 mCollisionStackSizeBytes;
//for sorting contacts
PxPinnedArray<PxgRadixSortBlockDesc> mRSDesc;
PxgCudaBufferN<2> mRadixSortDescBuf; //radix sort with rank
PxgCudaBuffer mRadixCountTotalBuf;
PxU32 mRadixCountSize;
//for radix sort
PxgTypedCudaBuffer<PxNodeIndex> mContactByRigidBuf; //rigidId is nodeIndex, which is 64 bit
PxgTypedCudaBuffer<PxNodeIndex> mContactSortedByRigidBuf; //rigidId is nodeIndex, which is 64 bit
PxgTypedCudaBuffer<PxU32> mTempContactByRigidBitBuf; //low/high 32 bit
PxgTypedCudaBuffer<PxU32> mContactRemapSortedByRigidBuf; //rank index
PxgTypedCudaBuffer<PxU64> mContactSortedByParticleBuf; //PxU64 particle system id and particle index
PxgTypedCudaBuffer<PxU32> mTempContactByParticleBitBuf; //low/high 32 bit
PxgTypedCudaBuffer<PxU32> mContactRemapSortedByParticleBuf; //rank index
PxgTypedCudaBuffer<PxU32> mTempContactBuf;
PxgTypedCudaBuffer<PxU32> mTempContactRemapBuf;
PxgTypedCudaBuffer<PxU32> mTempContactBuf2;
PxgTypedCudaBuffer<PxU32> mTempContactRemapBuf2;
#if PX_ENABLE_SIM_STATS
PxU32 mCollisionStackSizeBytesStats;
#else
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
#endif
};
}
#endif

View File

@@ -0,0 +1,162 @@
// 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_PBD_PARTICLE_SYSTEM_CORE_H
#define PXG_PBD_PARTICLE_SYSTEM_CORE_H
#include "foundation/PxVec3.h"
#include "foundation/PxSimpleTypes.h"
#include "cudamanager/PxCudaTypes.h"
#include "PxgParticleSystemCore.h"
namespace physx
{
class PxCudaContextManager;
class PxgBodySimManager;
class PxgCudaKernelWranglerManager;
class PxgGpuContext;
struct PxGpuParticleBufferIndexPair;
class PxgHeapMemoryAllocatorManager;
class PxgParticleAndDiffuseBuffer;
class PxgParticleClothBuffer;
class PxgParticleRigidBuffer;
class PxgParticleSystem;
class PxgParticleSystemBuffer;
class PxgParticleSystemDiffuseBuffer;
class PxgSimulationController;
namespace Dy
{
class ParticleSystemCore;
}
class PxgPBDParticleSystemCore : public PxgParticleSystemCore, public PxgDiffuseParticleCore
{
public:
PxgPBDParticleSystemCore(PxgCudaKernelWranglerManager* gpuKernelWrangler, PxCudaContextManager* cudaContextManager,
PxgHeapMemoryAllocatorManager* heapMemoryManager, PxgSimulationController* simController,
PxgGpuContext* gpuContext, PxU32 maxParticleContacts);
virtual ~PxgPBDParticleSystemCore();
// calculate AABB bound for each particle volumes
void updateVolumeBound(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd, const PxU32 numActiveParticleSystems,
CUstream bpStream);
virtual void preIntegrateSystems(const PxU32 nbActiveParticleSystems, const PxVec3 gravity, const PxReal dt);
//virtual void updateBounds(PxgParticleSystem* particleSystems, PxU32* activeParticleSystems, const PxU32 nbActiveParticleSystems);
virtual void updateGrid();
virtual void selfCollision();
//this is for solving selfCollsion and contacts between particles and primitives based on sorted by particle id
virtual void constraintPrep(CUdeviceptr prePrepDescd, CUdeviceptr prepDescd, CUdeviceptr solverCoreDescd, CUdeviceptr sharedDescd,
const PxReal dt, CUstream solverStream, bool isTGS, PxU32 numSolverBodies);
virtual void updateParticles(const PxReal dt);
virtual void solve(CUdeviceptr prePrepDescd, CUdeviceptr solverCoreDescd,
CUdeviceptr sharedDescd, CUdeviceptr artiCoreDescd, const PxReal dt, CUstream solverStream);
virtual void solveTGS(CUdeviceptr prePrepDescd, CUdeviceptr solverCoreDescd,
CUdeviceptr sharedDescd, CUdeviceptr artiCoreDescd, const PxReal dt, const PxReal totalInvDt, CUstream solverStream,
const bool isVelocityIteration, PxI32 iterationIndex, PxI32 numTGSIterations, PxReal coefficient);
virtual void prepParticleConstraint(CUdeviceptr prePrepDescd, CUdeviceptr prepDescd, CUdeviceptr sharedDescd, bool isTGS, const PxReal dt);
virtual void integrateSystems(const PxReal dt, const PxReal epsilonSq);
virtual void onPostSolve();
virtual void gpuMemDmaUpParticleSystem(PxgBodySimManager& bodySimManager, CUstream stream);
virtual void getMaxIterationCount(PxgBodySimManager& bodySimManager, PxI32& maxPosIters, PxI32& maxVelIters);
virtual void releaseParticleSystemDataBuffer();
void solveVelocities(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd, const PxU32 nbActiveParticleSystems, const PxReal dt);
void solveParticleCollision(const PxReal dt, bool isTGS, PxReal coefficient);
virtual void finalizeVelocities(const PxReal dt, const PxReal scale);
void solveSprings(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd,
const PxU32 nbActiveParticleSystems, const PxReal dt, bool isTGS);
void initializeSprings(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd,
const PxU32 nbActiveParticleSystems);
// Direct-GPU API
PX_DEPRECATED void applyParticleBufferDataDEPRECATED(const PxU32* indices, const PxGpuParticleBufferIndexPair* indexPairs, const PxParticleBufferFlags* flags, PxU32 nbUpdatedBuffers, CUevent waitEvent, CUevent signalEvent);
private:
void allocateParticleBuffer(const PxU32 nbTotalParticleSystems, CUstream stream);
void allocateParticleDataBuffer(void** bodySimsLL, CUstream stream);
void updateDirtyData(PxgBodySimManager& bodySimManager, CUstream stream);
void resizeParticleDataBuffer(PxgParticleSystem& particleSystem, PxgParticleSystemBuffer* buffer, const PxU32 maxParticles, const PxU32 maxNeighborhood, CUstream stream);
void resizeDiffuseParticleDiffuseBuffer(PxgParticleSystem& particleSystem, PxgParticleSystemDiffuseBuffer* diffuseBuffer, const PxU32 maxDiffuseParticles, CUstream stream);
bool createUserParticleData(PxgParticleSystem& particleSystem, Dy::ParticleSystemCore& dyParticleSystemCore, PxgParticleSystemBuffer* buffer, PxgParticleSystemDiffuseBuffer* diffuseBuffer,
CUstream stream);
PX_FORCE_INLINE PxU32 getMaxSpringsPerBuffer() { return mMaxSpringsPerBuffer; }
PX_FORCE_INLINE PxU32 getMaxSpringPartitionsPerBuffer() { return mMaxSpringPartitionsPerBuffer; }
PX_FORCE_INLINE PxU32 getMaxSpringsPerPartitionPerBuffer() { return mMaxSpringsPerPartitionPerBuffer; }
PX_FORCE_INLINE PxU32 getMaxRigidsPerBuffer() { return mMaxRigidsPerBuffer; }
void calculateHashForDiffuseParticles(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd, const PxU32 numActiveParticleSystems);
void solveDensities(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemd, const PxU32 nbActiveParticleSystems, const PxReal dt,
PxReal coefficient);
void solveInflatables(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemd, const PxU32 nbActiveParticleSystems, const PxReal coefficient, const PxReal dt);
void solveShapes(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemd, const PxU32 nbActiveParticleSystems, const PxReal dt, const PxReal biasCoefficient);
void solveAerodynamics(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemd, const PxU32 nbActiveParticleSystems, const PxReal dt);
void solveDiffuseParticles(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemd, const PxU32 nbActiveParticleSystems, const PxReal dt);
//-------------------------------------------------------------------------------
// Materials
void updateMaterials(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemd, const PxU32 nbActiveParticleSystems, CUstream bpStream, const PxReal invTotalDt);
PxU32 mMaxClothBuffersPerSystem;
PxU32 mMaxClothsPerBuffer;
PxU32 mMaxSpringsPerBuffer;
PxU32 mMaxSpringPartitionsPerBuffer;
PxU32 mMaxSpringsPerPartitionPerBuffer;
PxU32 mMaxTrianglesPerBuffer;
PxU32 mMaxVolumesPerBuffer;
PxU32 mMaxRigidBuffersPerSystem;
PxU32 mMaxRigidsPerBuffer;//compute the max rigids(shape matching) for each particle system
PxU32 mMaxNumPhaseToMaterials; //compute the max number of phase to materials for each particle system
bool mComputePotentials;
PxU32 mNumActiveParticleSystems;
};
}
#endif

View File

@@ -0,0 +1,112 @@
// 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_PARTICLE_NEIGHBORHOOD_PROVIDER_H
#define PXG_PARTICLE_NEIGHBORHOOD_PROVIDER_H
#include "PxParticleNeighborhoodProvider.h"
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec4.h"
#include "PxgSparseGridStandalone.h"
#include "PxgKernelLauncher.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
#if PX_SUPPORT_GPU_PHYSX
class PxgParticleNeighborhoodProvider : public PxParticleNeighborhoodProvider, public PxUserAllocated
{
private:
PxgKernelLauncher mKernelLauncher;
public:
PxSparseGridBuilder mSparseGridBuilder;
PxgParticleNeighborhoodProvider(PxgKernelLauncher& cudaContextManager, const PxU32 maxNumParticles, const PxReal particleContactOffset, const PxU32 maxNumSparseGridCells);
virtual void buildNeighborhood(PxVec4* deviceParticlePos, const PxU32 numParticles, CUstream stream, PxU32* devicePhases = NULL,
PxU32 validPhase = PxParticlePhaseFlag::eParticlePhaseFluid, const PxU32* deviceActiveIndices = NULL)
{
mSparseGridBuilder.updateSparseGrid(deviceParticlePos, numParticles, devicePhases, stream, validPhase, deviceActiveIndices);
mSparseGridBuilder.updateSubgridEndIndices(numParticles, stream);
}
PxU32* getSubgridEndIndicesBuffer()
{
return mSparseGridBuilder.getSubgridEndIndicesBuffer();
}
virtual PxU32 getMaxParticles() const
{
return mSparseGridBuilder.getMaxParticles();
}
virtual void setMaxParticles(PxU32 maxParticles)
{
mSparseGridBuilder.setMaxParticles(maxParticles);
}
virtual void release()
{
mSparseGridBuilder.release();
PX_DELETE_THIS;
}
virtual PxU32 getNumGridCellsInUse() const
{
return mSparseGridBuilder.getNumSubgridsInUse();
}
virtual PxU32 getMaxGridCells() const
{
return mSparseGridBuilder.getGridParameters().maxNumSubgrids;
}
virtual PxReal getCellSize() const
{
return mSparseGridBuilder.getGridParameters().gridSpacing;
}
virtual void setCellProperties(PxU32 maxGridCells, PxReal cellSize);
virtual ~PxgParticleNeighborhoodProvider() {}
};
#endif
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,638 @@
// 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_PARTICLE_SYSTEM_H
#define PXG_PARTICLE_SYSTEM_H
#include "foundation/PxPinnedArray.h"
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec3.h"
#include "foundation/PxVec4.h"
#include "foundation/PxUserAllocated.h"
#include "PxParticleBuffer.h"
#include "PxParticleGpu.h"
#include "PxgCudaBuffer.h"
#include "DyParticleSystemCore.h"
#include "PxsParticleBuffer.h"
#include <vector_types.h>
#include "PxNodeIndex.h"
#include "PxgSimulationCoreDesc.h"
namespace physx
{
#define EMPTY_CELL 0xffffffff
#define NUM_SPRING_PER_BLOCK 4
struct PxsParticleMaterialData;
struct PxParticleRigidFilterPair;
struct PxParticleRigidAttachment;
class PxCudaContextManager;
class PxsHeapMemoryAllocatorManager;
class PxNodeIndex;
class PxgPBDMaterialDerived;
template<typename MaterialType>
PX_CUDA_CALLABLE PX_FORCE_INLINE const MaterialType& getParticleMaterial(const PxsParticleMaterialData* PX_RESTRICT materials,
const PxU32 id, const PxU32 stride)
{
const PxU8* PX_RESTRICT data = reinterpret_cast<const PxU8*>(materials) + id * stride;
return *reinterpret_cast<const MaterialType*>(data);
}
struct PX_ALIGN_PREFIX(16) PxgPBDParticleMaterialDerived
{
PxReal surfaceTensionDerived;
PxReal cohesion;
PxReal cohesion1;
PxReal cohesion2;
__device__ PxgPBDParticleMaterialDerived() {}
__device__ PxgPBDParticleMaterialDerived(const PxReal surfaceTension_,
const PxReal cohesion_, const PxReal cohesion1_, const PxReal cohesion2_)
: surfaceTensionDerived(surfaceTension_), cohesion(cohesion_), cohesion1(cohesion1_), cohesion2(cohesion2_)
{
}
};
struct PxgParticleSystemData
{
public:
PxVec3 mBoundCenter;
PxU32 mElementIndex;
PxU32 mRemapIndex;
PxReal mRestOffset;
PxReal mSolidRestOffset;
PxReal mSpiky1;
PxReal mSpiky2;
PxReal mRestDensity;
PxReal mRestDensityBoundary;
PxReal mFluidSurfaceConstraintScale;
PxReal mLambdaScale;
PxReal mRelaxationFactor;
PxReal mFluidRestOffset;
PxReal mInvRestDensity;
PxU32 mFlags;
PxReal mMaxVelocity;
PxU16 mLockFlags;
PxU32 mNumPhaseToMaterials;
PxVec3 mWind;
};
//each particle has one collision header
struct PX_ALIGN_PREFIX(8) PxgParticleCollisionHeader
{
public:
PxU32 mPrimitiveCollisionStartIndex;
PxU32 mPrimitiveCounts; //how many primitives are colliding with this particle
} PX_ALIGN_SUFFIX(8);
PX_ALIGN_PREFIX(16)
struct PxgParticleContactInfo
{
static const PxU32 MaxStaticContactsPerParticle = 12;
static const PxU32 MaxStaticContactsPerMesh = 6;
float4 mNormal_PenW;
}PX_ALIGN_SUFFIX(16);
struct PxgParticleSimBuffer
{
float4* mPositionInvMasses;
float4* mVelocities;
float4* mRestPositions;
PxU32* mPhases;
PxParticleVolume* mVolumes;
PxParticleRigidFilterPair* mFilterPairs;
PxParticleRigidAttachment* mRigidAttachments;
PxU32 mNumActiveParticles;
PxU32 mNumVolumes;
PxU32 mNumFilterPairs;
PxU32 mNumRigidAttachments;
PxU32 mFlags;
PxU32 mDiffuseParticleBufferIndex;
PxU32 mUniqueId; //Remains unchanged over the whole lifetime of a buffer
};
struct PxgParticleClothSimBuffer
{
//Cloth
PxU32* mAccumulatedSpringsPerPartitions; //numPartitions;
PxU32* mAccumulatedCopiesPerParticles; //numSprings
PxU32* mRemapOutput; //numSprings * 2
PxParticleSpring* mOrderedSprings; //numSprings
PxU32* mTriangles; //numTriangles * 3
PxU32* mSortedClothStartIndices; //numCloths
PxParticleCloth* mCloths; //numCloths
float4* mRemapPositions;
float4* mRemapVelocities;
PxReal* mSpringLambda;
PxReal* mInflatableLambda;
PxU32 mParticleBufferIndex; //which particle buffer this cloth buffer associated with
PxU32 mNumSprings;
PxU32 mNumPartitions;
PxU32 mNumCloths;
PxU32 mNumTriangles;
};
struct PxgParticleRigidSimBuffer
{
PxReal* mRigidCoefficients; //mNumRigids;
float4* mRigidTranslations; //mNumRigids
float4* mRigidRotations; //mNumRigids
PxU32* mRigidOffsets; //mNumRigids + 1
float4* mRigidLocalPositions; //mNumActiveParticles
float4* mRigidLocalNormals; //mNumActiveParticles
PxU32 mNumRigids;
PxU32 mParticleBufferIndex;
};
struct PxgParticleDiffuseSimBuffer
{
PxDiffuseParticleParams mParams;
float4* mDiffusePositions_LifeTime;
float4* mDiffuseVelocities;
PxU32 mMaxNumParticles;
int* mNumDiffuseParticles; //device memory
int* mNumActiveDiffuseParticles; //pinned memory
PxU32 mStartIndex;
PxU32 mFlags;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class BufferClass>
class PxgParticleBufferBase : public BufferClass, public PxUserAllocated
{
public:
PxgParticleBufferBase(PxU32 maxNumParticles, PxU32 maxNumVolumes, PxCudaContextManager& contextManager);
virtual ~PxgParticleBufferBase();
//PxsParticleBuffer
virtual PxVec4* getPositionInvMassesD() const PX_OVERRIDE PX_FINAL { return mPositionInvMassesD; }
virtual PxVec4* getVelocitiesD() const PX_OVERRIDE PX_FINAL { return mVelocitiesD; }
virtual PxU32* getPhasesD() const PX_OVERRIDE PX_FINAL { return mPhasesD; }
virtual PxParticleVolume* getParticleVolumesD() const PX_OVERRIDE PX_FINAL { return mVolumesD; }
virtual PxVec4* getPositionInvMassesH() const PX_OVERRIDE PX_FINAL { return mPositionInvMassesH; }
virtual PxVec4* getVelocitiesH() const PX_OVERRIDE PX_FINAL { return mVelocitiesH; }
virtual PxU32* getPhasesH() const PX_OVERRIDE PX_FINAL { return mPhasesH; }
virtual PxParticleVolume* getParticleVolumesH() const PX_OVERRIDE PX_FINAL { return mVolumesH; }
virtual void setNbActiveParticles(PxU32 nbActiveParticles) PX_OVERRIDE;
virtual PxU32 getNbActiveParticles() const PX_OVERRIDE PX_FINAL { return mNumActiveParticles; }
virtual PxU32 getMaxParticles() const PX_OVERRIDE PX_FINAL { return mMaxNumParticles; }
virtual PxU32 getNbParticleVolumes() const PX_OVERRIDE PX_FINAL { return mNumParticleVolumes; }
virtual void setNbParticleVolumes(PxU32 nbParticleVolumes) PX_OVERRIDE PX_FINAL { mNumParticleVolumes = nbParticleVolumes; }
virtual PxU32 getMaxParticleVolumes() const PX_OVERRIDE PX_FINAL { return mMaxNumVolumes; }
virtual void setRigidFilters(PxParticleRigidFilterPair* filters, PxU32 nbFilters) PX_OVERRIDE PX_FINAL;
virtual void setRigidAttachments(PxParticleRigidAttachment* attachments, PxU32 nbAttachments) PX_OVERRIDE PX_FINAL;
virtual PxU32 getFlatListStartIndex() const PX_OVERRIDE PX_FINAL { return mFlatListStartIndex; }
virtual void raiseFlags(PxParticleBufferFlag::Enum flags) PX_OVERRIDE PX_FINAL { mBufferFlags |= flags; }
virtual PxU32 getUniqueId() const PX_OVERRIDE PX_FINAL { return mUniqueId; }
virtual void allocHostBuffers() PX_OVERRIDE PX_FINAL;
//~PxsParticleBuffer
void setFlatListStartIndex(PxU32 flatListStartIndex) { mFlatListStartIndex = flatListStartIndex; }
PxParticleRigidAttachment* getRigidAttachments() const { return mRigidAttachments; }
PxU32 getNbRigidAttachments() const { return mNumRigidAttachments; }
PxParticleRigidFilterPair* getRigidFilters() const { return mFilterPairs; }
PxU32 getNbRigidFilters() const { return mNumFilterPairs; }
void copyToHost(CUstream stream);
PxU32 mBufferFlags;
public:
PxCudaContextManager& mContextManager;
PxVec4* mPositionInvMassesD;
PxVec4* mVelocitiesD;
PxU32* mPhasesD;
PxParticleVolume* mVolumesD;
PxVec4* mPositionInvMassesH;
PxVec4* mVelocitiesH;
PxU32* mPhasesH;
PxParticleVolume* mVolumesH;
PxParticleRigidFilterPair* mFilterPairs;
PxParticleRigidAttachment* mRigidAttachments;
PxU32 mNumActiveParticles;
PxU32 mMaxNumParticles;
PxU32 mNumParticleVolumes;
PxU32 mMaxNumVolumes;
PxU32 mNumFilterPairs;
PxU32 mNumRigidAttachments;
PxU32 mFlatListStartIndex;
PxU32 mUniqueId;
};
class PxgParticleBuffer : public PxgParticleBufferBase<PxsParticleBuffer>
{
public:
PxgParticleBuffer(PxU32 maxNumParticles, PxU32 maxNumVolumes, PxCudaContextManager& contextManager);
virtual ~PxgParticleBuffer() {}
//PxsParticleBuffer
virtual void release() PX_OVERRIDE PX_FINAL { PX_DELETE_THIS; }
//~PxsParticleBuffer
void copyToHost(CUstream stream);
};
class PxgParticleAndDiffuseBuffer : public PxgParticleBufferBase<PxsParticleAndDiffuseBuffer>
{
public:
PxgParticleAndDiffuseBuffer(PxU32 maxNumParticles, PxU32 maxNumVolumes, PxU32 maxNumDiffuseParticles, PxCudaContextManager& contextManager);
virtual ~PxgParticleAndDiffuseBuffer();
//PxsParticleAndDiffuseBuffer
virtual void release() PX_OVERRIDE PX_FINAL { PX_DELETE_THIS; }
virtual PxVec4* getDiffusePositionLifeTimeD() const PX_OVERRIDE PX_FINAL { return mDiffusePositionsLifeTimeD; }
virtual PxVec4* getDiffuseVelocitiesD() const PX_OVERRIDE PX_FINAL { return mDiffuseVelocitiesD; }
virtual PxU32 getNbActiveDiffuseParticles() const PX_OVERRIDE PX_FINAL { return mNumActiveDiffuseParticlesH[0]; }
virtual void setMaxActiveDiffuseParticles(PxU32 maxActiveDiffuseParticles) PX_OVERRIDE PX_FINAL;
virtual PxU32 getMaxDiffuseParticles() const PX_OVERRIDE PX_FINAL { return mMaxNumDiffuseParticles; }
virtual void setDiffuseParticleParams(const PxDiffuseParticleParams& params) PX_OVERRIDE PX_FINAL;
virtual const PxDiffuseParticleParams& getDiffuseParticleParams() const PX_OVERRIDE PX_FINAL { return mParams; }
//~PxsParticleAndDiffuseBuffer
void copyToHost(CUstream stream);
public:
PxDiffuseParticleParams mParams;
PxVec4* mDiffusePositionsLifeTimeD;
PxVec4* mDiffuseVelocitiesD;
PxI32* mNumDiffuseParticlesD;
PxU32 mMaxNumDiffuseParticles;
PxU32 mMaxActiveDiffuseParticles;
PxI32* mNumActiveDiffuseParticlesH; //pinned memory
};
class PxgParticleClothBuffer : public PxgParticleBufferBase<PxsParticleClothBuffer>
{
public:
PxgParticleClothBuffer(PxU32 maxNumParticles, PxU32 maxNumVolumes, PxU32 maxNumCloths,
PxU32 maxNumTriangles, PxU32 maxNumSprings, PxCudaContextManager& contextManager);
virtual ~PxgParticleClothBuffer();
//PxsParticleClothBuffer
virtual void release() PX_OVERRIDE PX_FINAL { PX_DELETE_THIS; }
virtual PxVec4* getRestPositionsD() PX_OVERRIDE PX_FINAL { return mRestPositionsD; }
virtual PxU32* getTrianglesD() const PX_OVERRIDE PX_FINAL { return mTriangleIndicesD; }
virtual void setNbTriangles(PxU32 nbTriangles) PX_OVERRIDE PX_FINAL { mNumTriangles = nbTriangles; }
virtual PxU32 getNbTriangles() const PX_OVERRIDE PX_FINAL { return mNumTriangles; }
virtual PxU32 getNbSprings() const PX_OVERRIDE PX_FINAL { return mNumSprings; }
virtual PxParticleSpring* getSpringsD() PX_OVERRIDE PX_FINAL { return mOrderedSpringsD; }
virtual void setCloths(PxPartitionedParticleCloth& cloths) PX_OVERRIDE PX_FINAL;
virtual void setNbActiveParticles(PxU32 nbActiveParticles) PX_OVERRIDE PX_FINAL;
//~PxsParticleClothBuffer
void copyToHost(CUstream stream);
public:
PxVec4* mRestPositionsD;
PxU32* mTriangleIndicesD;
PxU32* mAccumulatedSpringsPerPartitionsD; //numPartitions;
PxU32* mAccumulatedCopiesPerParticlesD; //numSprings
PxU32* mRemapOutputD; //numSprings * 2
PxParticleSpring* mOrderedSpringsD; //numSprings
PxU32* mSortedClothStartIndicesD; //numCloths
PxParticleCloth* mClothsD; //numClothes
PxVec4* mRemapPositionsD;
PxVec4* mRemapVelocitiesD;
PxReal* mSpringLambdaD;
PxReal* mInflatableLambdaD;
PxU32 mMaxNumCloths;
PxU32 mMaxNumTriangles;
PxU32 mMaxNumSprings;
PxU32 mNumPartitions;
PxU32 mMaxSpringsPerPartition;
PxU32 mNumSprings;
PxU32 mNumCloths;
PxU32 mNumTriangles;
PxU32 mRemapOutputSize;
};
class PxgParticleRigidBuffer : public PxgParticleBufferBase<PxsParticleRigidBuffer>
{
public:
PxgParticleRigidBuffer(PxU32 maxNumParticles, PxU32 maxNumVolumes, PxU32 maxNumRigids, PxCudaContextManager& contextManager);
virtual ~PxgParticleRigidBuffer();
//PxsParticleRigidBuffer
virtual void release() PX_OVERRIDE PX_FINAL { PX_DELETE_THIS; }
PxU32* getRigidOffsetsD() const PX_OVERRIDE PX_FINAL { return mRigidOffsetsD; }
PxReal* getRigidCoefficientsD() const PX_OVERRIDE PX_FINAL { return mRigidCoefficientsD; }
PxVec4* getRigidLocalPositionsD() const PX_OVERRIDE PX_FINAL { return mRigidLocalPositionsD; }
PxVec4* getRigidLocalNormalsD() const PX_OVERRIDE PX_FINAL { return mRigidLocalNormalsD; }
PxVec4* getRigidTranslationsD() const PX_OVERRIDE PX_FINAL { return mRigidTranslationsD; }
PxVec4* getRigidRotationsD() const PX_OVERRIDE PX_FINAL { return mRigidRotationsD; }
void setNbRigids(const PxU32 nbRigids) PX_OVERRIDE PX_FINAL { mNumActiveRigids = nbRigids; }
PxU32 getNbRigids() const PX_OVERRIDE PX_FINAL { return mNumActiveRigids; }
//~PxsParticleRigidBuffer
void copyToHost(CUstream stream);
public:
PxU32* mRigidOffsetsD;
PxReal* mRigidCoefficientsD;
PxVec4* mRigidLocalPositionsD;
PxVec4* mRigidLocalNormalsD;
PxVec4* mRigidTranslationsD;
PxVec4* mRigidRotationsD;
PxU32 mNumActiveRigids;
PxU32 mMaxNumRigids;
};
#if PX_VC
#pragma warning(push)
#pragma warning( disable : 4324 ) // Padding was added at the end of a structure because of a __declspec(align) value.
#endif
PX_ALIGN_PREFIX(16)
class PxgParticleSystem : public PxGpuParticleSystem
{
public:
float4* mOriginPos_InvMass; //8 16
PxU32* mGridParticleHash; //16 32
float4* mAccumDeltaP; //32 80
//float4* mDeltaP; //32 80
float4* mSortedDeltaP; //32 80
PxU32* mCellStart; //36 88
PxU32* mCellEnd; //40 96
PxgParticleCollisionHeader* mCollisionHeaders; //44 104
float2* mDensityCollisionImpulses;
PxgParticleContactInfo* mOneWayContactInfos; //56 128
float2* mOneWayForces; //60
PxNodeIndex* mOneWayNodeIndex; //64 136
float4* mOneWaySurfaceVelocity; //68 144
PxU32* mOneWayContactCount; //72 152
float4* mRestArray; //84
PxgParticleSystemData mData;
PxReal* mDensity;
PxReal* mStaticDensity;
float4* mSurfaceNormal;
float4* mDelta;
float4* mCurl;
// Normals
float4* mNormalArray;
float4* mSortedOriginPos_InvMass;
PxgParticleSimBuffer* mParticleSimBuffers;
PxU32* mParticleBufferRunsum;
PxU32* mParticleBufferSortedUniqueIds;
PxU32* mParticleBufferSortedUniqueIdsOriginalIndex;
PxgParticleClothSimBuffer* mClothSimBuffers;
PxgParticleRigidSimBuffer* mRigidSimBuffers;
PxgParticleDiffuseSimBuffer* mDiffuseSimBuffers;
PxU32* mAttachmentRunsum;
PxU32 mNumClothBuffers;
PxU32 mNumRigidBuffers;
PxU32 mNumDiffuseBuffers;
PxU32 mNumRigidAttachments;
PxU32 mRigidAttachmentOffset;
// Diffuse particles
int* mNumDiffuseParticles;
float4* mDiffusePosition_LifeTime;
float4* mDiffuseVelocity;
float2* mDiffusePotentials;
PxU32* mDiffuseCellStart;
PxU32* mDiffuseCellEnd;
PxU32* mDiffuseGridParticleHash;
float4* mDiffuseOriginPos_LifeTime;
float4* mDiffuseSortedPos_LifeTime;
float4* mDiffuseSortedOriginPos_LifeTime;
float4* mDiffuseSortedVel;
//GPU pointer to the mapping from sorted particle ID to unsorted particle ID
PxU32* mDiffuseSortedToUnsortedMapping;
//GPU pointer to the mapping from unsortedParticle ID to sorted particle ID
PxU32* mDiffuseUnsortedToSortedMapping;
PxgParticleContactInfo* mDiffuseOneWayContactInfos;
float* mDiffuseOneWayForces;
PxNodeIndex* mDiffuseOneWayNodeIndex;
PxU32* mDiffuseOneWayContactCount;
PxgPBDParticleMaterialDerived* mDerivedPBDMaterialData;
PxU32 mParticleMaterialStride;
PxU16* mPhaseGroupToMaterialHandle;
}PX_ALIGN_SUFFIX(16);
#if PX_VC
#pragma warning(pop)
#endif
class PxgParticleSystemBuffer
{
public:
PxgParticleSystemBuffer(PxgHeapMemoryAllocatorManager* heapMemoryManager);
PxgTypedCudaBuffer<PxVec4> originalPosition_mass; //we should be able to get rid of this buffer
PxgTypedCudaBuffer<PxU32> grid_particle_hash;
PxgTypedCudaBuffer<PxU32> grid_particle_index;
PxgTypedCudaBuffer<PxVec4> sorted_position_mass;
PxgTypedCudaBuffer<PxVec4> sorted_velocity;
PxgTypedCudaBuffer<PxVec4> accumDeltaV;
PxgTypedCudaBuffer<PxVec4> sortedDeltaP;
PxgTypedCudaBuffer<PxU32> cell_start;
PxgTypedCudaBuffer<PxU32> cell_end;
PxgTypedCudaBuffer<PxgParticleCollisionHeader> collision_headers;
PxgTypedCudaBuffer<PxU32> collision_counts;
PxgTypedCudaBuffer<PxU32> collision_index;
PxgTypedCudaBuffer<float2> collision_impulses;
PxgTypedCudaBuffer<PxU32> phases;
PxgTypedCudaBuffer<float4> unsortedpositions;
PxgTypedCudaBuffer<float4> unsortedvelocities;
PxgTypedCudaBuffer<float4> restArray;
PxgTypedCudaBuffer<float4> normal;
PxgTypedCudaBuffer<PxReal> density;
PxgTypedCudaBuffer<PxReal> staticDensity;
PxgTypedCudaBuffer<PxVec4> surfaceNormal;
PxgTypedCudaBuffer<PxVec4> delta;
PxgTypedCudaBuffer<PxVec4> curl;
PxgTypedCudaBuffer<float4> sorted_originalPosition_mass;
PxgTypedCudaBuffer<PxU32> sortedPhaseArray;
PxgTypedCudaBuffer<PxgParticleContactInfo> particleOneWayContacts;
PxgTypedCudaBuffer<float2> particleOneWayForces;
PxgTypedCudaBuffer<PxNodeIndex> particleOneWayContactsNodeIndices;
PxgTypedCudaBuffer<float4> particleOneWayContactsSurfaceVelocities;
PxgTypedCudaBuffer<PxU32> particleOneWayContactCount;
PxgTypedCudaBuffer<PxU32> reverseLookup;
PxgTypedCudaBuffer<PxU16> phase_group_to_material_handle;
PxgTypedCudaBuffer<PxgPBDParticleMaterialDerived> derivedPBDMaterialProperties;
PxgTypedCudaBuffer<PxgParticleSimBuffer> user_particle_buffer; //PxgPBDParticleBuffer
PxgTypedCudaBuffer<PxU32> user_particle_buffer_runsum; //PxU32*
PxgTypedCudaBuffer<PxU32> user_particle_buffer_sorted_unique_ids; //PxU32*
PxgTypedCudaBuffer<PxU32> user_particle_buffer_runsum_sorted_unique_ids_original_index; //PxU32*
PxgTypedCudaBuffer<PxgParticleClothSimBuffer> user_cloth_buffer;
PxgTypedCudaBuffer<PxgParticleRigidSimBuffer> user_rigid_buffer;
PxgTypedCudaBuffer<PxgParticleDiffuseSimBuffer> user_diffuse_buffer;
PxgTypedCudaBuffer<PxU32> attachmentRunSum;
PxgTypedCudaBuffer<PxU32> referencedRigidsRunsum;
PxPinnedArray<PxgParticleSimBuffer> mHostParticleBuffers;
PxPinnedArray<PxgParticleClothSimBuffer> mHostClothBuffers;
PxPinnedArray<PxgParticleRigidSimBuffer> mHostRigidBuffers;
PxPinnedArray<PxgParticleDiffuseSimBuffer> mHostDiffuseBuffers;
PxInt32ArrayPinned mAttachmentRunSum;
PxInt32ArrayPinned mParticleBufferRunSum;
PxInt32ArrayPinned mReferencedRigidsRunsum;
PxInt32ArrayPinned mParticleBufferSortedUniqueIds;
PxInt32ArrayPinned mParticleBufferSortedUniqueIdsOriginalIndex;
PxFloatArrayPinned mRandomTable;
PxInt16ArrayPinned mHostPhaseGroupToMaterialHandle;
};
class PxgParticleSystemDiffuseBuffer
{
public:
PxgParticleSystemDiffuseBuffer(PxgHeapMemoryAllocatorManager* heapMemoryManager);
// Diffuse particle data
PxgTypedCudaBuffer<PxVec4> diffuse_positions;
PxgTypedCudaBuffer<PxVec4> diffuse_velocities;
PxgTypedCudaBuffer<PxVec4> diffuse_potentials;
PxgTypedCudaBuffer<PxU32> diffuse_cell_start;
PxgTypedCudaBuffer<PxU32> diffuse_cell_end;
PxgTypedCudaBuffer<PxU32> diffuse_grid_particle_hash;
PxgTypedCudaBuffer<PxU32> diffuse_sorted_to_unsorted_mapping;
PxgTypedCudaBuffer<PxU32> diffuse_unsorted_to_sorted_mapping;
PxgTypedCudaBuffer<PxVec4> diffuse_origin_pos_life_time;
PxgTypedCudaBuffer<PxVec4> diffuse_sorted_pos_life_time;
PxgTypedCudaBuffer<PxVec4> diffuse_sorted_origin_pos_life_time;
PxgTypedCudaBuffer<PxVec4> diffuse_sorted_vel;
PxgTypedCudaBuffer<PxgParticleContactInfo> diffuse_one_way_contacts;
PxgTypedCudaBuffer<PxReal> diffuse_one_way_forces;
PxgTypedCudaBuffer<PxNodeIndex> diffuse_one_way_contacts_node_indices;
PxgTypedCudaBuffer<PxU32> diffuse_one_way_contact_count;
PxgTypedCudaBuffer<PxU32> diffuse_particle_count;
};
PX_ALIGN_PREFIX(16)
struct PxgParticlePrimitiveContact
{
public:
PxVec4 normal_pen; //normal pen
PxU64 rigidId; //the corresponding rigid body node index
PxU64 particleId; //particle index
}PX_ALIGN_SUFFIX(16);
struct PxgParticleContactWriter
{
PxgParticlePrimitiveContact* PX_RESTRICT particleContacts;
PxU32* numTotalContacts;
PxU64* contactSortedByParticle;
PxU32* tempContactByParticle;
PxU32* contactIndexSortedByParticle;
PxNodeIndex* contactByRigid;
PxU32* tempContactByRigid;
PxU32* contactIndexSortedByRigid;
PxU32 maxContacts;
PX_FORCE_INLINE PX_CUDA_CALLABLE void writeContact(PxU32 index, const PxVec4& normalPen,
PxU64 compressedParticleIndex, PxNodeIndex rigidId)
{
if (index < maxContacts)
{
contactByRigid[index] = rigidId;
tempContactByRigid[index] = PxU32(rigidId.getInd() & 0xffffffff);
contactIndexSortedByRigid[index] = index;
contactSortedByParticle[index] = compressedParticleIndex;
tempContactByParticle[index] = PxGetParticleIndex(compressedParticleIndex);
contactIndexSortedByParticle[index] = index;
PxgParticlePrimitiveContact& contact = particleContacts[index];
contact.normal_pen = normalPen;
contact.rigidId = rigidId.getInd();
contact.particleId = compressedParticleIndex;
}
}
};
}
#endif

View File

@@ -0,0 +1,334 @@
// 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_PARTICLE_SYSTEM_CORE_H
#define PXG_PARTICLE_SYSTEM_CORE_H
#include "foundation/PxArray.h"
#include "foundation/PxPinnedArray.h"
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec3.h"
#include "PxSparseGridParams.h"
#include "cudamanager/PxCudaTypes.h"
#include "PxgCudaBuffer.h"
#include "PxgNarrowphaseCore.h"
#include "PxgNonRigidCoreCommon.h"
#include "PxgParticleSystem.h"
#include "PxgRadixSortDesc.h"
#include "PxgSimulationCoreDesc.h"
#include <vector_types.h>
namespace physx
{
//this is needed to force PhysXSimulationControllerGpu linkage as Static Library!
void createPxgParticleSystem();
class PxgBodySimManager;
class PxgEssentialCore;
class PxgCudaKernelWranglerManager;
class PxCudaContextManager;
class PxgHeapMemoryAllocatorManager;
class PxgSimulationController;
class PxgGpuContext;
class PxBounds3;
struct PxgShapeDescBuffer;
struct PxgParticlePrimitiveConstraintBlock
{
float4 raXn_velMultiplierW[32];
float4 normal_errorW[32];
//Friction tangent + invMass of the rigid body (avoids needing to read the mass)
//Second tangent can be found by cross producting normal with fricTan0
float4 fricTan0_invMass0[32];
float4 raXnF0_velMultiplierW[32];
float4 raXnF1_velMultiplierW[32];
PxU64 rigidId[32];
PxU64 particleId[32];
};
class PxgParticleSystemCore : public PxgNonRigidCore
{
public:
PxgParticleSystemCore(PxgCudaKernelWranglerManager* gpuKernelWrangler, PxCudaContextManager* cudaContextManager,
PxgHeapMemoryAllocatorManager* heapMemoryManager, PxgSimulationController* simController,
PxgGpuContext* gpuContext, PxU32 maxParticleContacts);
virtual ~PxgParticleSystemCore();
virtual void preIntegrateSystems(const PxU32 nbActiveParticleSystems, const PxVec3 gravity, const PxReal dt) = 0;
virtual void updateBounds(PxgParticleSystem* particleSystems, PxU32* activeParticleSystems, const PxU32 nbActiveParticleSystems);
virtual void updateGrid() = 0;
virtual void selfCollision() = 0;
void resetContactCounts();
void sortContacts(const PxU32 nbActiveParticleSystems);
virtual void gpuMemDmaUpParticleSystem(PxgBodySimManager& bodySimManager, CUstream stream) = 0;
virtual void constraintPrep(CUdeviceptr prePrepDescd, CUdeviceptr prepDescd, CUdeviceptr solverCoreDescd, CUdeviceptr sharedDescd,
const PxReal dt, CUstream solverStream, bool isTGS, PxU32 numSolverBodies) = 0;
virtual void solve(CUdeviceptr prePrepDescd, CUdeviceptr solverCoreDescd,
CUdeviceptr sharedDescd, CUdeviceptr artiCoreDescd, const PxReal dt, CUstream solverStream) = 0;
virtual void solveTGS(CUdeviceptr prePrepDescd, CUdeviceptr solverCoreDescd,
CUdeviceptr sharedDescd, CUdeviceptr artiCoreDescd, const PxReal dt, const PxReal totalInvDt, CUstream solverStream,
const bool isVelocityIteration, PxI32 iterationIndex, PxI32 numTGSIterations, PxReal coefficient) = 0;
virtual void integrateSystems(const PxReal dt, const PxReal epsilonSq) = 0;
virtual void onPostSolve() = 0;
virtual void getMaxIterationCount(PxgBodySimManager& bodySimManager, PxI32& maxPosIters, PxI32& maxVelIters) = 0;
void updateParticleSystemData(PxgParticleSystem& sys, Dy::ParticleSystemCore& dyParticleSystemCore);
//void updateSparseGridParams(PxSparseGridParams& params, Dy::ParticleSystemCore& dyParticleSystemCore);
PxgTypedCudaBuffer<PxgParticleSystem>& getParticleSystemBuffer() { return mParticleSystemBuffer; }
PxgTypedCudaBuffer<PxU32>& getActiveParticleSystemBuffer() { return mActiveParticleSystemBuffer; }
PxgCudaBuffer& getTempCellsHistogram() { return mTempCellsHistogramBuf; }
PxgTypedCudaBuffer<PxU32>& getTempBlockCellsHistogram() { return mTempBlockCellsHistogramBuf; }
PxgTypedCudaBuffer<PxU32>& getTempHistogramCount() { return mTempHistogramCountBuf; }
PxgTypedCudaBuffer<PxgParticlePrimitiveContact>& getParticleContacts() { return mPrimitiveContactsBuf; }
PxgTypedCudaBuffer<PxU32>& getParticleContactCount() { return mPrimitiveContactCountBuf; }
CUstream getStream() { return mStream; }
CUstream getFinalizeStream() { return mFinalizeStream; }
CUevent getBoundsUpdatedEvent() { return mBoundUpdateEvent;}
PxgDevicePointer<float4> getDeltaVelParticle() { return mDeltaVelParticleBuf.getTypedDevicePtr(); }
virtual void updateParticles(const PxReal dt) = 0;
virtual void finalizeVelocities(const PxReal dt, const PxReal scale) = 0;
virtual void releaseParticleSystemDataBuffer() = 0;
void gpuDMAActiveParticleIndices(const PxU32* activeParticleSystems, const PxU32 numActiveParticleSystems, CUstream stream);
PX_FORCE_INLINE PxU32 getMaxParticles() { return mMaxParticles; }
PxU32 getHostContactCount() { return *mHostContactCount; }
PxPinnedArray<PxgParticleSystem> mNewParticleSystemPool; //record the newly created particle system
PxPinnedArray<PxgParticleSystem> mParticleSystemPool; //persistent cpu mirror
PxArray<PxU32> mNewParticleSystemNodeIndexPool;
PxArray<PxU32> mParticleSystemNodeIndexPool;
PxInt32ArrayPinned mDirtyParamsParticleSystems;
protected:
void releaseInternalParticleSystemDataBuffer();
void getMaxIterationCount(PxgBodySimManager& bodySimManager, const PxU32 nbActiveParticles, const PxU32* activeParticles, PxI32& maxPosIters, PxI32& maxVelIters);
void updateGrid(PxgParticleSystem* particleSystems, const PxU32* activeParticleSystems, const PxU32 nbActiveParticles,
CUdeviceptr particleSystemsd);
void copyUserBufferToUnsortedArray(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd,
const PxU32 nbActiveParticle, CUstream bpStream);
void copyUnsortedArrayToUserBuffer(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd, const PxU32 nbActiveParticles);
void copyUserBufferDataToHost(PxgParticleSystem* particleSystems, PxU32* activeParticleSystems, PxU32 nbActiveParticleSystems);
void copyUserDiffuseBufferToUnsortedArray(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd,
const PxU32 nbActiveParticle, CUstream bpStream);
//integrate particle position based on gravity
void preIntegrateSystem(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd, const PxU32 nbActiveParticles, const PxVec3 gravity,
const PxReal dt, CUstream bpStream);
// calculate particle system's world bound
void updateBound(const PxgParticleSystem& sys, PxgParticleSystem* particleSystems,
PxBounds3* boundArray, PxReal* contactDists, CUstream bpStream);
// calculate grid hash
void calculateHash(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd, const PxU32 numActiveParticleSystems);
// reorder particle arrays into sorted order and
// find start and end of each cell
void reorderDataAndFindCellStart(PxgParticleSystem* particleSystems, CUdeviceptr particleSystemsd, const PxU32 id, const PxU32 numParticles);
void selfCollision(PxgParticleSystem& particleSystem, PxgParticleSystem* particleSystemsd, const PxU32 id, const PxU32 numParticles);
//----------------------------------------------------------------------------------------
//These method are using the particle stream
virtual void prepParticleConstraint(CUdeviceptr prePrepDescd, CUdeviceptr prepDescd, CUdeviceptr sharedDescd, bool isTGS, const PxReal dt);
//void solveSelfCollision(PxgParticleSystem& particleSystem, PxgParticleSystem* particleSystemsd, const PxU32 id, const PxU32 numParticles, PxReal dt);
void applyDeltas(CUdeviceptr particleSystemd, CUdeviceptr activeParticleSystemd, const PxU32 nbActivParticleSystem, const PxReal dt, CUstream stream);
/*void solveSprings(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd,
const PxU32 nbActiveParticleSystems, const PxReal dt, bool isTGS);
*/
void solveOneWayCollision(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd,
const PxU32 nbActiveParticleSystems, const PxReal dt, const PxReal biasCoefficient, const bool isVelocityIteration);
void updateSortedVelocity(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd,
const PxU32 nbActiveParticleSystems, const PxReal dt, const bool skipNewPositionAdjustment = false);
void stepParticleSystems(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd, const PxU32 nbActiveParticleSystems,
const PxReal dt, const PxReal totalInvDt, bool isParticleSystem);
//-------------------------------------------------------------------------------
//These method are using the solverStream
void prepPrimitiveConstraint(CUdeviceptr prePrepDescd, CUdeviceptr prepDescd, CUdeviceptr sharedDescd,
const PxReal dt, bool isTGS, CUstream solverStream);
//this is for solving contacts between particles and primitives based on sorted by rigid id
void solvePrimitiveCollisionForParticles(CUdeviceptr prePrepDescd, CUdeviceptr solverCoreDescd,
CUdeviceptr sharedDescd, CUdeviceptr artiCoreDescd, const PxReal dt, bool isTGS, const PxReal coefficient,
bool isVelIteration);
void solvePrimitiveCollisionForRigids(CUdeviceptr prePrepDescd, CUdeviceptr solverCoreDescd,
CUdeviceptr sharedDescd, CUdeviceptr artiCoreDescd, CUstream solverStream, const PxReal dt, bool isTGS, const PxReal coefficient,
bool isVelIteration);
void accumulateRigidDeltas(CUdeviceptr prePrepDescd, CUdeviceptr solverCoreDescd,
CUdeviceptr sharedDescd, CUdeviceptr artiCoreDescd, CUdeviceptr rigidIdsd, CUdeviceptr numIdsd, CUstream stream,
const bool isTGS);
void prepRigidAttachments(CUdeviceptr prePrepDescd, CUdeviceptr prepDescd, bool isTGS, const PxReal dt, CUstream stream,
const PxU32 nbActiveParticleSystems, CUdeviceptr activeParticleSystemsd, PxU32 numSolverBodies);
void solveRigidAttachments(CUdeviceptr prePrepDescd, CUdeviceptr solverCoreDescd,
CUdeviceptr sharedDescd, CUdeviceptr artiCoreDescd, CUstream solverStream, const PxReal dt,
const bool isTGS, const PxReal biasCoefficient, const bool isVelocityIteration, CUdeviceptr particleSystemd, CUdeviceptr activeParticleSystemd, const PxU32 nbActiveParticleSystems);
//integrate particle position and velocity based on contact constraints
void integrateSystem(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemd, const PxU32 nbActiveParticleSystems, const PxReal dt, const PxReal epsilonSq);
PxgTypedCudaBuffer<PxgParticleSystem> mParticleSystemBuffer; //persistent buffer for particle system
PxgTypedCudaBuffer<PxU32> mActiveParticleSystemBuffer;
PxgTypedCudaBuffer<PxU32> mTempGridParticleHashBuf;
PxgTypedCudaBuffer<PxU32> mTempGridParticleIndexBuf;
PxgTypedCudaBuffer<PxU32> mTempGridDiffuseParticleHashBuf;
PxgTypedCudaBuffer<PxU32> mTempGridDiffuseParticleIndexBuf;
PxgCudaBuffer mTempCellsHistogramBuf;
PxgTypedCudaBuffer<PxU32> mTempBlockCellsHistogramBuf;
PxgTypedCudaBuffer<PxU32> mTempHistogramCountBuf;
PxgTypedCudaBuffer<PxBounds3> mTempBoundsBuf;
//-----------------------buffer for primitive vs particles contacts
PxgTypedCudaBuffer<PxgParticlePrimitiveContact> mPrimitiveContactsBuf;
PxgTypedCudaBuffer<PxU32> mPrimitiveContactCountBuf;
PxgTypedCudaBuffer<PxgParticlePrimitiveContact> mPrimitiveContactSortedByParticleBuf;
PxgTypedCudaBuffer<PxgParticlePrimitiveContact> mPrimitiveContactSortedByRigidBuf;
PxgTypedCudaBuffer<PxgParticlePrimitiveConstraintBlock> mPrimitiveConstraintSortedByParticleBuf;
PxgTypedCudaBuffer<PxgParticlePrimitiveConstraintBlock> mPrimitiveConstraintSortedByRigidBuf;
PxgTypedCudaBuffer<float2> mPrimitiveConstraintAppliedParticleForces;
PxgTypedCudaBuffer<float2> mPrimitiveConstraintAppliedRigidForces;
PxgTypedCudaBuffer<float4> mDeltaVelParticleBuf;
PxgTypedCudaBuffer<float4> mDeltaVelRigidBuf;
PxgTypedCudaBuffer<PxVec4> mTempBlockDeltaVelBuf;
PxgTypedCudaBuffer<PxU64> mTempBlockRigidIdBuf;
PxgTypedCudaBuffer<PxgParticleRigidConstraint> mParticleRigidConstraints;
PxgTypedCudaBuffer<PxU64> mParticleRigidAttachmentIds;
PxgTypedCudaBuffer<PxU32> mParticleRigidConstraintCount;
PxgTypedCudaBuffer<PxReal> mParticleRigidAttachmentScaleBuffer;
//------------------------------------------------------------------------
CUstream mFinalizeStream;
CUevent mFinalizeStartEvent;
CUevent mBoundUpdateEvent;//this event is used to synchronize the broad phase stream(updateBound is running on broad phase stream) and mStream
CUevent mSolveParticleEvent; //this event is used to synchronize solve particle/particle, paricle/rigid and solver rigid/particle
CUevent mSelfCollisionEvent;
CUevent mSolveParticleRigidEvent;
CUevent mSolveRigidParticleEvent;
PxU32 mCurrentTMIndex; //current temp marker buffer index
PxgCudaBuffer mHasFlipPhase;
PxArray<PxgParticleSystemBuffer*> mParticleSystemDataBuffer; //persistent data, map with mParticleSystemBuffer
// Diffuse particles
PxPinnedArray<PxgRadixSortBlockDesc> mDiffuseParticlesRSDesc;
PxVec3 mGravity; //this get set in preIntegrateSystems
PxU32 mNbTotalParticleSystems;
PxU32 mMaxParticles;
bool mHasNonZeroFluidBoundaryScale;
PxU32 mMaxParticlesPerBuffer;
PxU32 mMaxBuffersPerSystem;
PxU32 mMaxDiffusePerBuffer;
PxU32 mMaxDiffuseBuffersPerSystem;
PxU32 mMaxRigidAttachmentsPerSystem;
PxU32 mTotalRigidAttachments;
PxU32* mHostContactCount;
friend class PxgSoftBodyCore;
};
class PxgDiffuseParticleCore
{
public:
PxgDiffuseParticleCore(PxgEssentialCore* core);
virtual ~PxgDiffuseParticleCore();
void releaseInternalDiffuseParticleDataBuffer();
void preDiffuseIntegrateSystem(CUdeviceptr particleSystemsd, CUdeviceptr activeParticleSystemsd, const PxU32 nbActiveParticles, const PxVec3 gravity,
const PxReal dt, CUstream bpStream);
PxgEssentialCore* mEssentialCore;
PxgCudaBuffer mDiffuseParticlesRandomTableBuf;
PxArray<PxgParticleSystemDiffuseBuffer*> mDiffuseParticleDataBuffer; //persistent data
PxU32 mRandomTableSize;
PxU32 mMaxDiffuseParticles; //the max number of diffuse particles
protected:
void resizeDiffuseParticleParticleBuffers(PxgParticleSystem& particleSystem, PxgParticleSystemDiffuseBuffer* buffer, const PxU32 numParticles);
};
}
#endif

View File

@@ -0,0 +1,68 @@
// 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_PARTICLE_SYSTEM_CORE_KERNEL_INDICES_H
#define PXG_PARTICLE_SYSTEM_CORE_KERNEL_INDICES_H
namespace physx
{
struct PxgParticleSystemKernelBlockDim
{
enum
{
UPDATEBOUND = 1024, //can't change this. updateBound kernel is relied on numOfWarpPerBlock = 32
UPDATEGRID = 1024,
BOUNDCELLUPDATE = 512,
PS_COLLISION = 256, //128,
PS_MESH_COLLISION = 512,
PS_HEIGHTFIELD_COLLISION = 64,
ACCUMULATE_DELTA = 512,
PS_SOLVE = 256,
PS_CELL_RECOMPUTE = 256,
PS_INFLATABLE = 256,
PS_SOLVE_SHAPE = 64,
SCAN = 512
};
};
struct PxgParticleSystemKernelGridDim
{
enum
{
BOUNDCELLUPDATE = 32,
PS_COLLISION = 1024,
PS_MESH_COLLISION = 16384,
PS_HEIGHTFIELD_COLLISION = 4096,
ACCUMULATE_DELTA = 32,
PS_CELL_RECOMPUTE = 32,
};
};
}
#endif

View File

@@ -0,0 +1,101 @@
// 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_RADIX_SORT_CORE_H
#define PXG_RADIX_SORT_CORE_H
#include "PxgCudaBuffer.h"
#include "PxgEssentialCore.h"
#include "PxgKernelWrangler.h"
#include "PxgRadixSortDesc.h"
#include "cudamanager/PxCudaTypes.h"
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec3.h"
#include "foundation/PxVec4.h"
#include "foundation/PxPinnedArray.h"
namespace physx
{
class PxCudaContext;
class PxgCudaKernelWranglerManager;
class PxgRadixSortCore
{
public:
PxPinnedArray<PxgRadixSortBlockDesc> mRSDesc;
PxgCudaBufferN<2> mRadixSortDescBuf; //radix sort with rank
PxgCudaBuffer mRadixCountTotalBuf;
PxU32 mRadixCountSize;
PxgEssentialCore* mEssentialCore;
PxgRadixSortCore(PxgEssentialCore* core);
void allocate(PxU32 nbRequired = 1);
static void updateGPURadixSortDesc(PxCudaContext* cudaContext, const CUstream& stream, CUdeviceptr inputKeyd, CUdeviceptr inputRankd,
CUdeviceptr outputKeyd, CUdeviceptr outputRankd, CUdeviceptr radixCountd, PxgRadixSortDesc* rsDescs,
CUdeviceptr radixSortDescBuf0, CUdeviceptr radixSortDescBuf1, const PxU32 count);
static void sort(PxgCudaKernelWranglerManager* gpuKernelWranglerManager, PxCudaContext*cudaContext, const CUstream& stream,
const PxU32 numOfKeys, PxgCudaBuffer* radixSortDescBuf, const PxU32 numBits, PxgRadixSortDesc* rsDescs);
static void sort(PxgCudaKernelWranglerManager* gpuKernelWranglerManager, PxCudaContext*cudaContext, const CUstream& stream,
PxgCudaBuffer* radixSortDescBuf, const PxU32 numBits);
static PX_FORCE_INLINE PxI32 getNbBits(PxI32 x)
{
PxI32 n = 0;
while (x >= 2)
{
++n;
x /= 2;
}
return n;
}
void sort(CUdeviceptr inputKeyd, CUdeviceptr inputRankd, CUdeviceptr outputKeyd, CUdeviceptr outputRankd, const PxU32 numOfKeys, const PxU32 numBits, const CUstream& stream, PxU32 id = 0)
{
PxgRadixSortDesc* rsDescs = &mRSDesc[id * 2];
updateGPURadixSortDesc(mEssentialCore->mCudaContext, stream, inputKeyd, inputRankd, outputKeyd, outputRankd, mRadixCountTotalBuf.getDevicePtr(), rsDescs,
mRadixSortDescBuf[0].getDevicePtr(), mRadixSortDescBuf[1].getDevicePtr(), numOfKeys);
sort(mEssentialCore->mGpuKernelWranglerManager, mEssentialCore->mCudaContext, stream, numOfKeys, mRadixSortDescBuf.begin(), numBits, rsDescs);
}
void sort(CUdeviceptr inputKeyd, CUdeviceptr inputRankd, CUdeviceptr outputKeyd, CUdeviceptr outputRankd, const PxU32 numOfKeys, const PxU32 numBits, PxU32 id = 0)
{
sort(inputKeyd, inputRankd, outputKeyd, outputRankd, numOfKeys, numBits, mEssentialCore->mStream, id);
}
};
}
#endif

View File

@@ -0,0 +1,146 @@
// 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_SDF_BUILDER_H
#define PXG_SDF_BUILDER_H
#include "PxSDFBuilder.h"
#include "foundation/PxSimpleTypes.h"
#include "PxgKernelLauncher.h"
#include "PxgBVH.h"
#include "GuSDF.h"
#include "foundation/PxVec4.h"
#include "PxgAlgorithms.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
class PxgKernelLauncher;
// Create a linear BVH as described in Fast and Simple Agglomerative LBVH construction
// this is a bottom-up clustering method that outputs one node per-leaf
// Taken from Flex
class PxgLinearBVHBuilderGPU
{
public:
PxgLinearBVHBuilderGPU(PxgKernelLauncher& kernelLauncher);
// takes a bvh (host ref), and pointers to the GPU lower and upper bounds for each triangle
// the priorities array allows specifying a 5-bit [0-31] value priority such that lower priority
// leaves will always be returned first
void buildFromLeaveBounds(PxgBVH& bvh, const PxVec4* lowers, const PxVec4* uppers, const PxI32* priorities, PxI32 n, PxBounds3* totalBounds,
CUstream stream, bool skipAllocate = false);
void buildFromTriangles(PxgBVH& bvh, const PxVec3* vertices, const PxU32* triangleIndices, const PxI32* priorities,
PxI32 n, PxBounds3* totalBounds, CUstream stream, PxReal boxMargin = 1e-5f);
void buildTreeAndWindingClustersFromTriangles(PxgBVH& bvh, PxgWindingClusterApproximation* windingNumberClustersD, const PxVec3* vertices, const PxU32* triangleIndices, const PxI32* priorities,
PxI32 n, PxBounds3* totalBounds, CUstream stream, PxReal boxMargin = 1e-5f, bool skipAllocate = false);
void resizeBVH(PxgBVH& bvh, PxU32 numNodes);
void releaseBVH(PxgBVH& bvh);
//Allocates or resizes the linear bvh builder including the bvh itself
void allocateOrResize(PxgBVH& bvh, PxU32 numItems);
void release();
PxI32* mMaxTreeDepth;
private:
void prepareHierarchConstruction(PxgBVH& bvh, const PxVec4* lowers, const PxVec4* uppers, const PxI32* priorities, PxI32 n, PxBounds3* totalBounds, CUstream stream);
PxgKernelLauncher mKernelLauncher;
PxGpuRadixSort<PxU32> mSort;
// temporary data used during building
PxU32* mIndices;
PxI32* mKeys;
PxReal* mDeltas;
PxI32* mRangeLefts;
PxI32* mRangeRights;
PxI32* mNumChildren;
// bounds data when total item bounds built on GPU
PxVec3* mTotalLower;
PxVec3* mTotalUpper;
PxVec3* mTotalInvEdges;
PxU32 mMaxItems;
};
class PxgSDFBuilder : public PxSDFBuilder, public PxUserAllocated
{
private:
PxgKernelLauncher mKernelLauncher;
void computeDenseSDF(const PxgBvhTriangleMesh& mesh, const PxgWindingClusterApproximation* windingNumberClustersD,
const Gu::GridQueryPointSampler& sampler, PxU32 sizeX, PxU32 sizeY, PxU32 sizeZ, PxReal* sdfDataD, CUstream stream, PxReal* windingNumbersD = NULL);
// returns NULL if GPU errors occurred.
PxReal* buildDenseSDF(const PxVec3* vertices, PxU32 numVertices, const PxU32* indicesOrig, PxU32 numTriangleIndices, PxU32 width, PxU32 height, PxU32 depth,
const PxVec3& minExtents, const PxVec3& maxExtents, bool cellCenteredSamples, CUstream stream);
void compressSDF(PxReal* denseSdfD, PxU32 width, PxU32 height, PxU32 depth,
PxU32 subgridSize, PxReal narrowBandThickness, PxU32 bytesPerSubgridPixel, PxReal errorThreshold,
PxReal& subgridGlobalMinValue, PxReal& subgridGlobalMaxValue, PxArray<PxReal>& sdfCoarse, PxArray<PxU32>& sdfSubgridsStartSlots, PxArray<PxU8>& sdfDataSubgrids,
PxU32& sdfSubgrids3DTexBlockDimX, PxU32& sdfSubgrids3DTexBlockDimY, PxU32& sdfSubgrids3DTexBlockDimZ, CUstream stream);
void fixHoles(PxU32 width, PxU32 height, PxU32 depth, PxReal* sdfDataD, const PxVec3& cellSize, const PxVec3& minExtents, const PxVec3& maxExtents,
Gu::GridQueryPointSampler& sampler, CUstream stream);
bool allocateBuffersForCompression(PxReal*& backgroundSdfD, PxU32 numBackgroundSdfSamples, PxU32*& subgridAddressesD, PxU8*& subgridActiveD, PxU32 numAddressEntries,
PxReal*& subgridGlobalMinValueD, PxReal*& subgridGlobalMaxValueD, PxGpuScan& scan);
void releaseBuffersForCompression(PxReal*& backgroundSdfD, PxU32*& subgridAddressesD, PxU8*& subgridActiveD, PxReal*& subgridGlobalMinValueD,
PxReal*& subgridGlobalMaxValueD, PxGpuScan& scan);
public:
PxgSDFBuilder(PxgKernelLauncher& kernelLauncher);
virtual bool buildSDF(const PxVec3* vertices, PxU32 numVertices, const PxU32* indicesOrig, PxU32 numTriangleIndices, PxU32 width, PxU32 height, PxU32 depth,
const PxVec3& minExtents, const PxVec3& maxExtents, bool cellCenteredSamples, PxReal* sdf, CUstream stream) PX_OVERRIDE;
virtual bool buildSparseSDF(const PxVec3* vertices, PxU32 numVertices, const PxU32* indicesOrig, PxU32 numTriangleIndices, PxU32 width, PxU32 height, PxU32 depth,
const PxVec3& minExtents, const PxVec3& maxExtents, PxReal narrowBandThickness, PxU32 subgridSize, PxSdfBitsPerSubgridPixel::Enum bytesPerSubgridPixel,
PxArray<PxReal>& sdfCoarse, PxArray<PxU32>& sdfSubgridsStartSlots, PxArray<PxU8>& sdfDataSubgrids,
PxReal& subgridsMinSdfValue, PxReal& subgridsMaxSdfValue,
PxU32& sdfSubgrids3DTexBlockDimX, PxU32& sdfSubgrids3DTexBlockDimY, PxU32& sdfSubgrids3DTexBlockDimZ, CUstream stream) PX_OVERRIDE;
void release();
};
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,55 @@
// 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_SHAPESIM_H
#define PXG_SHAPESIM_H
#include "foundation/PxTransform.h"
#include "foundation/PxBounds3.h"
#include "PxNodeIndex.h"
namespace physx
{
struct PxgShapeSim
{
PxTransform mTransform; //
PxBounds3 mLocalBounds; // local bounds
PxNodeIndex mBodySimIndex; // body sim index
PxU32 mHullDataIndex; // this index is shared with the np hull data(hull need to be gpu compatible)
PxU16 mShapeFlags; // shape flags
PxU16 mShapeType; // this indicates what type of shape(sphere, capsule, box or convexhull)
};
struct PxgNewShapeSim : PxgShapeSim
{
PxU32 mElementIndex; // transform cache and bound index
};
}//physx
#endif

View File

@@ -0,0 +1,110 @@
// 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_SHAPESIM_MANAGER_H
#define PXG_SHAPESIM_MANAGER_H
#include "foundation/PxArray.h"
#include "foundation/PxPinnedArray.h"
#include "PxgShapeSim.h"
#include "PxgCudaBuffer.h"
namespace physx
{
namespace Cm
{
class FlushPool;
}
namespace Sc
{
class ShapeSimBase;
}
struct PxsShapeCore;
class PxBaseTask;
class PxgHeapMemoryAllocatorManager;
class PxgGpuNarrowphaseCore;
class KernelWrangler;
struct PxgShapeSimData
{
PxgShapeSimData() : mShapeCore(NULL), mElementIndex_GPU(PX_INVALID_U32)
{
}
const PxsShapeCore* mShapeCore; // 4 or 8
// NodeIndex used to look up BodySim in island manager
PxNodeIndex mBodySimIndex_GPU; // 8 or 12 unique identified for body
// ElementID - copy of ElementSim's getElementID()
PxU32 mElementIndex_GPU; // 12 or 16 transform cache and bound index
};
class PxgShapeSimManager
{
PX_NOCOPY(PxgShapeSimManager)
public:
PxgShapeSimManager(PxgHeapMemoryAllocatorManager* heapMemoryManager);
void addPxgShape(Sc::ShapeSimBase* shapeSimBase, const PxsShapeCore* shapeCore, PxNodeIndex nodeIndex, PxU32 index);
void setPxgShapeBodyNodeIndex(PxNodeIndex nodeIndex, PxU32 index);
void removePxgShape(PxU32 index);
// PT: copies new shapes from CPU memory (mShapeSims) to GPU *host* memory (mPxgShapeSimPool)
void copyToGpuShapeSim(PxgGpuNarrowphaseCore* npCore, PxBaseTask* continuation, Cm::FlushPool& flushPool);
// PT: copies new shapes from GPU *host* memory (mPxgShapeSimPool) to GPU device memory (mNewShapeSimBuffer)
// and *then* copies from device-to-device memory (mNewShapeSimBuffer => mShapeSimBuffer)
void gpuMemDmaUpShapeSim(PxCudaContext* cudaContext, CUstream stream, KernelWrangler* kernelWrangler);
// PT: TODO: figure out the difference between mTotalNumShapes and mNbTotalShapeSim
// (they both existed in different places and got logically refactored here)
PX_FORCE_INLINE PxU32 getTotalNbShapes() const { return mTotalNumShapes; }
PX_FORCE_INLINE PxU32 getNbTotalShapeSims() const { return mNbTotalShapeSim; }
PX_FORCE_INLINE CUdeviceptr getShapeSimsDevicePtr() const { return mShapeSimBuffer.getDevicePtr(); }
PX_FORCE_INLINE const PxgShapeSim* getShapeSimsDeviceTypedPtr() const { return mShapeSimBuffer.getTypedPtr(); }
PX_FORCE_INLINE Sc::ShapeSimBase** getShapeSims() { return mShapeSimPtrs.begin(); }
private:
PxArray<PxgShapeSimData> mShapeSims;
PxArray<Sc::ShapeSimBase*> mShapeSimPtrs;
PxArray<PxU32> mNewShapeSims;
PxU32 mTotalNumShapes;
PxU32 mNbTotalShapeSim;
PxPinnedArray<PxgNewShapeSim> mPxgShapeSimPool;
PxgTypedCudaBuffer<PxgShapeSim> mShapeSimBuffer;
PxgTypedCudaBuffer<PxgNewShapeSim> mNewShapeSimBuffer;
friend class PxgCopyToShapeSimTask;
};
}
#endif

View File

@@ -0,0 +1,905 @@
// 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_SIMULATION_CONTROLLER_H
#define PXG_SIMULATION_CONTROLLER_H
#include "PxgBodySimManager.h"
#include "PxgJointManager.h"
#include "PxsSimulationController.h"
#include "PxgHeapMemAllocator.h"
#include "CmTask.h"
#include "PxgArticulationLink.h"
#include "DyArticulationJointCore.h"
#include "PxgArticulation.h"
#include "PxgArticulationTendon.h"
#include "PxgSimulationCoreDesc.h"
#include "PxgSoftBody.h"
#include "PxgFEMCloth.h"
#include "PxgParticleSystem.h"
#include "PxArticulationTendonData.h"
#include "foundation/PxPreprocessor.h"
#include "foundation/PxSimpleTypes.h"
#include "BpAABBManagerBase.h"
#include "PxgAABBManager.h"
#include "PxsTransformCache.h"
#include "PxgNarrowphaseCore.h"
#define PXG_SC_DEBUG 0
namespace physx
{
//this is needed to force PhysXSimulationControllerGpu linkage as Static Library!
void createPxgSimulationController();
namespace shdfnd
{
class PxVirtualAllocatorCallback;
}
namespace Dy
{
class ParticleSystemCore;
}
namespace Bp
{
class BroadPhase;
}
class PxgSimulationCore;
class PxgPBDParticleSystemCore;
class PxgSoftBodyCore;
class PxgFEMClothCore;
class PxgGpuContext;
class PxgNphaseImplementationContext;
struct PxsCachedTransform;
class PxgSimulationController;
class PxgCudaKernelWranglerManager;
class PxgCudaBroadPhaseSap;
struct SoftBodyAttachmentAndFilterData
{
public:
PxPinnedArray<PxgFEMRigidAttachment>* rigidAttachments;
PxPinnedArray<PxgRigidFilterPair>* rigidFilterPairs;
bool dirtyRigidAttachments;
PxInt32ArrayPinned* activeRigidAttachments;
bool dirtyActiveRigidAttachments;
PxPinnedArray<PxgFEMFEMAttachment>* softBodyAttachments;
bool dirtySoftBodyAttachments;
PxInt32ArrayPinned* activeSoftBodyAttachments;
bool dirtyActiveSoftBodyAttachments;
PxArray<Dy::DeformableVolume*>* dirtyDeformableVolumeForFilterPairs;
PxPinnedArray<PxgFEMFEMAttachment>* clothAttachments;
PxPinnedArray<PxgNonRigidFilterPair>* clothFilterPairs;
bool dirtyClothAttachments;
PxInt32ArrayPinned* activeClothAttachments;
bool dirtyActiveClothAttachments;
PxPinnedArray<PxgFEMFEMAttachment>* particleAttachments;
PxPinnedArray<PxgNonRigidFilterPair>* particleFilterPairs;
bool dirtyParticleAttachments;
PxInt32ArrayPinned* activeParticleAttachments;
bool dirtyActiveParticleAttachments;
};
class PxgCopyToBodySimTask : public Cm::Task
{
PxgSimulationController& mController;
PxU32 mNewBodySimOffset;
PxU32 mStartIndex;
PxU32 mNbToProcess;
public:
PxgCopyToBodySimTask(PxgSimulationController& controller, PxU32 bodySimOffset, PxU32 startIdx, PxU32 nbToProcess) : Cm::Task(0), mController(controller),
mNewBodySimOffset(bodySimOffset), mStartIndex(startIdx),
mNbToProcess(nbToProcess)
{
}
virtual void runInternal();
virtual const char* getName() const
{
return "PxgCopyToBodySimTask";
}
private:
PX_NOCOPY(PxgCopyToBodySimTask)
};
class PxgCopyToArticulationSimTask : public Cm::Task
{
PxgSimulationController& mController;
PxU32 mNewBodySimOffset;
PxU32 mStartIndex, mNbToProcess;
PxI32* mSharedArticulationLinksIndex;
PxI32* mSharedDofIndex;
PxI32* mSharedSpatialTendonIndex;
PxI32* mSharedSpatialTendonAttachmentIndex;
PxI32* mSharedFixedTendonIndex;
PxI32* mSharedFixedTendonJointIndex;
PxI32* mSharedArticulationMimicJointIndex;
PxI32* mSharedPathToRootIndex;
public:
PxgCopyToArticulationSimTask(PxgSimulationController& controller, const PxU32 bodySimOffset, PxU32 startIdx,
PxU32 nbToProcess, PxI32* sharedArticulationLinksIndex, PxI32* sharedDofIndex,
PxI32* sharedSpatialTendonIndex,
PxI32* sharedSpatialTendonAttachmentsIndex,
PxI32* sharedFixedTendonIndex,
PxI32* sharedFixedTendonJointIndex,
PxI32* sharedArticulationMimicJointIndex,
PxI32* sharedPathToRootIndex) :
Cm::Task(0), mController(controller), mNewBodySimOffset(bodySimOffset), mStartIndex(startIdx),
mNbToProcess(nbToProcess), mSharedArticulationLinksIndex(sharedArticulationLinksIndex),
mSharedDofIndex(sharedDofIndex),
mSharedSpatialTendonIndex(sharedSpatialTendonIndex),
mSharedSpatialTendonAttachmentIndex(sharedSpatialTendonAttachmentsIndex),
mSharedFixedTendonIndex(sharedFixedTendonIndex),
mSharedFixedTendonJointIndex(sharedFixedTendonJointIndex),
mSharedArticulationMimicJointIndex(sharedArticulationMimicJointIndex),
mSharedPathToRootIndex(sharedPathToRootIndex)
{
}
virtual void runInternal();
virtual const char* getName() const
{
return "PxgCopyToArticulationSimTask";
}
private:
PX_NOCOPY(PxgCopyToArticulationSimTask)
};
class PxgUpdateArticulationSimTask : public Cm::Task
{
PxgSimulationController& mController;
PxU32 mStartIndex, mNbToProcess;
PxI32* mSharedArticulationLinksIndex;
PxI32* mSharedArticulationDofIndex;
PxI32* mSharedSpatialTendonIndex;
PxI32* mSharedSpatialTendonAttachmentIndex;
PxI32* mSharedFixedTendonIndex;
PxI32* mSharedFixedTendonJointIndex;
PxI32* mSharedMimicJointIndex;
public:
PxgUpdateArticulationSimTask(PxgSimulationController& controller, PxU32 startIdx,
PxU32 nbToProcess, PxI32* sharedArticulationLinksLindex,
PxI32* sharedArticulationDofIndex,
PxI32* sharedSpatialTendonIndex,
PxI32* sharedSpatialTendonAttachmentIndex,
PxI32* sharedFixedTendonIndex,
PxI32* sharedFixedTendonJointIndex,
PxI32* sharedMimicJointIndex) :
Cm::Task(0), mController(controller), mStartIndex(startIdx),
mNbToProcess(nbToProcess), mSharedArticulationLinksIndex(sharedArticulationLinksLindex),
mSharedArticulationDofIndex(sharedArticulationDofIndex),
mSharedSpatialTendonIndex(sharedSpatialTendonIndex),
mSharedSpatialTendonAttachmentIndex(sharedSpatialTendonAttachmentIndex),
mSharedFixedTendonIndex(sharedFixedTendonIndex),
mSharedFixedTendonJointIndex(sharedFixedTendonJointIndex),
mSharedMimicJointIndex(sharedMimicJointIndex)
{
}
virtual void runInternal();
virtual const char* getName() const
{
return "PxgUpdateArticulationSimTask";
}
private:
PX_NOCOPY(PxgUpdateArticulationSimTask)
};
class PxgCopyToSoftBodySimTask : public Cm::Task
{
PxgSimulationController& mController;
PxU32 mStartIndex, mNbToProcess;
public:
static const PxU32 NbSoftBodiesPerTask = 50;
PxgCopyToSoftBodySimTask(PxgSimulationController& controller, PxU32 startIdx, PxU32 nbToProcess) :
Cm::Task(0), mController(controller), mStartIndex(startIdx),
mNbToProcess(nbToProcess)
{
}
virtual void runInternal();
virtual const char* getName() const
{
return "PxgCopyToSoftBodySimTask";
}
private:
PX_NOCOPY(PxgCopyToSoftBodySimTask)
};
class PxgCopyToFEMClothSimTask : public Cm::Task
{
PxgSimulationController& mController;
PxU32 mStartIndex, mNbToProcess;
public:
static const PxU32 NbFEMClothsPerTask = 50;
PxgCopyToFEMClothSimTask(PxgSimulationController& controller, PxU32 startIdx, PxU32 nbToProcess) :
Cm::Task(0), mController(controller), mStartIndex(startIdx),
mNbToProcess(nbToProcess)
{
}
virtual void runInternal();
virtual const char* getName() const
{
return "PxgCopyToFEMClothSimTask";
}
private:
PX_NOCOPY(PxgCopyToFEMClothSimTask)
};
class PxgCopyToPBDParticleSystemSimTask : public Cm::Task
{
PxgSimulationController& mController;
PxgParticleSystemCore* core;
PxU32 mStartIndex, mNbToProcess;
public:
PxgCopyToPBDParticleSystemSimTask(PxgSimulationController& controller, PxU32 startIdx, PxU32 nbToProcess) :
Cm::Task(0), mController(controller), mStartIndex(startIdx),
mNbToProcess(nbToProcess)
{
}
virtual void runInternal();
virtual const char* getName() const
{
return "PxgCopyToPBDParticleSystemSimTask";
}
private:
PX_NOCOPY(PxgCopyToPBDParticleSystemSimTask)
};
class PxgPostCopyToShapeSimTask : public Cm::Task
{
PxgSimulationController& mController;
public:
PxgPostCopyToShapeSimTask(PxgSimulationController& controller) : Cm::Task(0), mController(controller)
{
}
virtual void runInternal();
virtual const char* getName() const
{
return "PxgPostCopyToShapeSimTask";
}
private:
PX_NOCOPY(PxgPostCopyToShapeSimTask)
};
class PxgPostCopyToBodySimTask : public Cm::Task
{
PxgSimulationController& mController;
const bool mEnableBodyAccelerations;
public:
PxgPostCopyToBodySimTask(PxgSimulationController& controller, bool enableBodyAccelerations) : Cm::Task(0), mController(controller), mEnableBodyAccelerations(enableBodyAccelerations)
{
}
virtual void runInternal();
virtual const char* getName() const
{
return "PxgPostCopyToBodySimTask";
}
private:
PX_NOCOPY(PxgPostCopyToBodySimTask)
};
class PxgPostUpdateParticleAndSoftBodyTask : public Cm::Task
{
PxgSimulationController& mController;
PxVec3 mGravity;
PxReal mDt;
public:
PxgPostUpdateParticleAndSoftBodyTask(PxgSimulationController& controller) : Cm::Task(0), mController(controller) {}
virtual void runInternal();
void setGravity(const PxVec3 gravity) { mGravity = gravity; }
void setDt(const PxReal dt) { mDt = dt; }
virtual const char* getName() const
{
return "PxgPostUpdateParticleAndSoftBodyTask";
}
private:
PX_NOCOPY(PxgPostUpdateParticleAndSoftBodyTask)
};
template <typename Attachment>
class AttachmentManager
{
public:
PxPinnedArray<Attachment> mAttachments;
PxInt32ArrayPinned mActiveAttachments;
PxHashMap<PxU32, PxU32> mHandleToAttachmentMapping;
PxHashMap<PxU32, PxU32> mHandleToActiveIndex;
PxArray<PxU32> mHandles;
PxU32 mBaseHandle;
bool mAttachmentsDirty;
bool mActiveAttachmentsDirty;
AttachmentManager(PxgHeapMemoryAllocatorManager* manager) :
mAttachments(manager->mMappedMemoryAllocators),
mActiveAttachments(manager->mMappedMemoryAllocators),
mBaseHandle(0),
mAttachmentsDirty(false),
mActiveAttachmentsDirty(false)
{
}
void addAttachment(const Attachment& attachment, const PxU32 handle)
{
const PxU32 size = mAttachments.size();
mAttachments.pushBack(attachment);
mHandles.pushBack(handle);
mHandleToAttachmentMapping[handle] = size;
mAttachmentsDirty = true;
}
bool removeAttachment(const PxU32 handle)
{
deactivateAttachment(handle);
//Now remove this current handle...
PxHashMap<PxU32, PxU32>::Entry mapping;
bool found = mHandleToAttachmentMapping.erase(handle, mapping);
if (found)
{
mAttachments.replaceWithLast(mapping.second);
mHandles.replaceWithLast(mapping.second);
if (mapping.second < mAttachments.size())
{
PxU32 newHandle = mHandles[mapping.second];
mHandleToAttachmentMapping[newHandle] = mapping.second;
const PxHashMap<PxU32, PxU32>::Entry* activeMapping = mHandleToActiveIndex.find(newHandle);
if (activeMapping)
{
mActiveAttachments[activeMapping->second] = mapping.second;
}
}
mAttachmentsDirty = true;
}
return found;
}
void activateAttachment(const PxU32 handle)
{
PX_ASSERT(!mHandleToActiveIndex.find(handle));
PxU32 index = mHandleToAttachmentMapping[handle];
mHandleToActiveIndex[handle] = mActiveAttachments.size();
mActiveAttachments.pushBack(index);
mActiveAttachmentsDirty = true;
}
void deactivateAttachment(const PxU32 handle)
{
PxHashMap<PxU32, PxU32>::Entry mapping;
bool found = mHandleToActiveIndex.erase(handle, mapping);
if (found)
{
mActiveAttachments.replaceWithLast(mapping.second);
if (mapping.second < mActiveAttachments.size())
{
PxU32 replaceHandle = mHandles[mActiveAttachments[mapping.second]];
mHandleToActiveIndex[replaceHandle] = mapping.second;
}
mActiveAttachmentsDirty = true;
}
}
};
class PxgSimulationController : public PxsSimulationController
{
PX_NOCOPY(PxgSimulationController)
public:
PxgSimulationController(PxsKernelWranglerManager* gpuWranglerManagers, PxCudaContextManager* cudaContextManager,
PxgGpuContext* dynamicContext, PxgNphaseImplementationContext* npContext, Bp::BroadPhase* bp, bool useGpuBroadphase,
PxsSimulationControllerCallback* callback, PxgHeapMemoryAllocatorManager* heapMemoryManager,
PxU32 maxSoftBodyContacts, PxU32 maxFemClothContacts, PxU32 maxParticleContacts, PxU32 collisionStackSizeBytes, bool enableBodyAccelerations);
virtual ~PxgSimulationController();
virtual void addPxgShape(Sc::ShapeSimBase* shapeSimBase, const PxsShapeCore* shapeCore, PxNodeIndex nodeIndex, PxU32 index) PX_OVERRIDE;
virtual void setPxgShapeBodyNodeIndex(PxNodeIndex nodeIndex, PxU32 index) PX_OVERRIDE;
virtual void removePxgShape(PxU32 index) PX_OVERRIDE;
virtual void addDynamic(PxsRigidBody* rigidBody, const PxNodeIndex& nodeIndex) PX_OVERRIDE;
virtual void addDynamics(PxsRigidBody** rigidBody, const PxU32* nodeIndex, PxU32 nbBodies) PX_OVERRIDE;
virtual void addArticulation(Dy::FeatherstoneArticulation* articulation, const PxNodeIndex& nodeIndex) PX_OVERRIDE;
virtual void releaseArticulation(Dy::FeatherstoneArticulation* articulation, const PxNodeIndex& nodeIndex) PX_OVERRIDE;
virtual void releaseDeferredArticulationIds() PX_OVERRIDE;
virtual void addParticleFilter(Dy::DeformableVolume* deformableVolume, Dy::ParticleSystem* particleSystem,
PxU32 particleId, PxU32 userBufferId, PxU32 tetId) PX_OVERRIDE;
virtual void removeParticleFilter(Dy::DeformableVolume* deformableVolume,
const Dy::ParticleSystem* particleSystem, PxU32 particleId, PxU32 userBufferId, PxU32 tetId) PX_OVERRIDE;
virtual PxU32 addParticleAttachment(Dy::DeformableVolume* deformableVolume, const Dy::ParticleSystem* particleSystem,
PxU32 particleId, PxU32 userBufferId, PxU32 tetId, const PxVec4& barycentrics, const bool isActive) PX_OVERRIDE;
virtual void removeParticleAttachment(Dy::DeformableVolume* deformableVolume, PxU32 handle) PX_OVERRIDE;
virtual void addRigidFilter(Dy::DeformableVolume* deformableVolume, const PxNodeIndex& rigidNodeIndex, PxU32 vertIndex) PX_OVERRIDE;
virtual void removeRigidFilter(Dy::DeformableVolume* deformableVolume, const PxNodeIndex& rigidNodeIndex, PxU32 vertIndex) PX_OVERRIDE;
virtual PxU32 addRigidAttachment(Dy::DeformableVolume* deformableVolume, const PxNodeIndex& softBodyNodeIndex,
PxsRigidBody* rigidBody, const PxNodeIndex& rigidNodeIndex, PxU32 vertIndex, const PxVec3& actorSpacePose,
PxConeLimitedConstraint* constraint, const bool isActive, bool doConversion) PX_OVERRIDE;
virtual PxU32 addTetRigidAttachment(Dy::DeformableVolume* deformableVolume,
PxsRigidBody* rigidBody, const PxNodeIndex& rigidNodeIndex, PxU32 tetIdx, const PxVec4& barycentrics, const PxVec3& actorSpacePose,
PxConeLimitedConstraint* constraint, const bool isActive, bool doConversion) PX_OVERRIDE;
virtual void removeRigidAttachment(Dy::DeformableVolume* deformableVolume, PxU32 handle) PX_OVERRIDE;
virtual void addTetRigidFilter(Dy::DeformableVolume* deformableVolume,
const PxNodeIndex& rigidNodeIndex, PxU32 tetId) PX_OVERRIDE;
virtual void removeTetRigidFilter(Dy::DeformableVolume* deformableVolume,
const PxNodeIndex& rigidNodeIndex, PxU32 tetId) PX_OVERRIDE;
virtual void addSoftBodyFilter(Dy::DeformableVolume* deformableVolume0, Dy::DeformableVolume* deformableVolume1, PxU32 tetIdx0,
PxU32 tetIdx1) PX_OVERRIDE;
virtual void removeSoftBodyFilter(Dy::DeformableVolume* deformableVolume0, Dy::DeformableVolume* deformableVolume1, PxU32 tetIdx0,
PxU32 tetId1) PX_OVERRIDE;
virtual void addSoftBodyFilters(Dy::DeformableVolume* deformableVolume0, Dy::DeformableVolume* deformableVolume1, PxU32* tetIndices0, PxU32* tetIndices1,
PxU32 tetIndicesSize) PX_OVERRIDE;
virtual void removeSoftBodyFilters(Dy::DeformableVolume* deformableVolume0, Dy::DeformableVolume* deformableVolume1, PxU32* tetIndices0, PxU32* tetIndices1,
PxU32 tetIndicesSize) PX_OVERRIDE;
virtual PxU32 addSoftBodyAttachment(Dy::DeformableVolume* deformableVolume0, Dy::DeformableVolume* deformableVolume1, PxU32 tetIdx0, PxU32 tetIdx1,
const PxVec4& tetBarycentric0, const PxVec4& tetBarycentric1, PxConeLimitedConstraint* constraint, PxReal constraintOffset,
const bool addToActive, bool doConversion) PX_OVERRIDE;
virtual void removeSoftBodyAttachment(Dy::DeformableVolume* deformableVolume0, PxU32 handle) PX_OVERRIDE;
virtual void addClothFilter(Dy::DeformableVolume* deformableVolume, Dy::DeformableSurface* deformableSurface, PxU32 triIdx, PxU32 tetIdx) PX_OVERRIDE;
virtual void removeClothFilter(Dy::DeformableVolume* deformableVolume, Dy::DeformableSurface* deformableSurface, PxU32 triId, PxU32 tetIdx) PX_OVERRIDE;
virtual PxU32 addClothAttachment(Dy::DeformableVolume* deformableVolume, Dy::DeformableSurface* deformableSurface, PxU32 triIdx,
const PxVec4& triBarycentric, PxU32 tetIdx, const PxVec4& tetBarycentric,
PxConeLimitedConstraint* constraint, PxReal constraintOffset,
const bool isActive, bool doConversion) PX_OVERRIDE;
virtual void removeClothAttachment(Dy::DeformableVolume* deformableVolume, PxU32 handle) PX_OVERRIDE;
virtual PxU32 addRigidAttachment(Dy::DeformableSurface* deformableSurface, const PxNodeIndex& clothNodeIndex,
PxsRigidBody* rigidBody, const PxNodeIndex& rigidNodeIndex, PxU32 vertIndex, const PxVec3& actorSpacePose,
PxConeLimitedConstraint* constraint, const bool isActive) PX_OVERRIDE;
virtual void removeRigidAttachment(Dy::DeformableSurface* deformableSurface, PxU32 handle) PX_OVERRIDE;
virtual void addTriRigidFilter(Dy::DeformableSurface* deformableSurface,
const PxNodeIndex& rigidNodeIndex, PxU32 triIdx) PX_OVERRIDE;
virtual void removeTriRigidFilter(Dy::DeformableSurface* deformableSurface, const PxNodeIndex& rigidNodeIndex,PxU32 triIdx) PX_OVERRIDE;
virtual PxU32 addTriRigidAttachment(Dy::DeformableSurface* deformableSurface,
PxsRigidBody* rigidBody, const PxNodeIndex& rigidNodeIndex, PxU32 triIdx, const PxVec4& barycentrics,
const PxVec3& actorSpacePose, PxConeLimitedConstraint* constraint,
const bool isActive) PX_OVERRIDE;
virtual void removeTriRigidAttachment(Dy::DeformableSurface* deformableSurface, PxU32 handle) PX_OVERRIDE;
virtual void addClothFilter(Dy::DeformableSurface* deformableSurface0, Dy::DeformableSurface* deformableSurface1, PxU32 triIdx0, PxU32 triIdx1) PX_OVERRIDE;
virtual void removeClothFilter(Dy::DeformableSurface* deformableSurface0, Dy::DeformableSurface* deformableSurface1, PxU32 triIdx0, PxU32 triId1) PX_OVERRIDE;
virtual PxU32 addTriClothAttachment(Dy::DeformableSurface* deformableSurface0, Dy::DeformableSurface* deformableSurface1, PxU32 triIdx0, PxU32 triIdx1,
const PxVec4& triBarycentric0, const PxVec4& triBarycentric1, const bool addToActive) PX_OVERRIDE;
virtual void removeTriClothAttachment(Dy::DeformableSurface* deformableSurface0, PxU32 handle) PX_OVERRIDE;
PxU32 addRigidAttachmentInternal(const PxU32 nonRigidId, const PxU32 elemId, const bool isVertex, const PxVec4& barycentric, PxsRigidBody* rigidBody,
const PxNodeIndex& rigidNodeIndex, const PxVec3& actorSpacePose, PxConeLimitedConstraint* constraint,
AttachmentManager<PxgFEMRigidAttachment>& attachments, bool addToActive);
void addSoftBodyFiltersInternal(Dy::DeformableVolume* deformableVolume0, Dy::DeformableVolume* deformableVolume1, PxU32* tetIndices, PxU32 size);
void removeSoftBodyFiltersInternal(Dy::DeformableVolume* deformableVolume0, Dy::DeformableVolume* deformableVolume1, PxU32* tetIndices, PxU32 size);
void createDeformableSurfaceCore();
void createDeformableVolumeCore();
virtual void addSoftBody(Dy::DeformableVolume* deformableVolume, const PxNodeIndex& nodeIndex) PX_OVERRIDE;
virtual void releaseSoftBody(Dy::DeformableVolume* deformableVolume) PX_OVERRIDE;
virtual void releaseDeferredSoftBodyIds() PX_OVERRIDE;
virtual void activateSoftbody(Dy::DeformableVolume* deformableVolume) PX_OVERRIDE;
virtual void deactivateSoftbody(Dy::DeformableVolume* deformableVolume) PX_OVERRIDE;
virtual void activateSoftbodySelfCollision(Dy::DeformableVolume* deformableVolume) PX_OVERRIDE;
virtual void deactivateSoftbodySelfCollision(Dy::DeformableVolume* deformableVolume) PX_OVERRIDE;
virtual void setSoftBodyWakeCounter(Dy::DeformableVolume* deformableVolume) PX_OVERRIDE;
virtual void addFEMCloth(Dy::DeformableSurface* deformableSurface, const PxNodeIndex& nodeIndex) PX_OVERRIDE;
virtual void releaseFEMCloth(Dy::DeformableSurface* deformableSurface) PX_OVERRIDE;
virtual void releaseDeferredFEMClothIds() PX_OVERRIDE;
virtual void activateCloth(Dy::DeformableSurface* deformableSurface) PX_OVERRIDE;
virtual void deactivateCloth(Dy::DeformableSurface* deformableSurface) PX_OVERRIDE;
virtual void setClothWakeCounter(Dy::DeformableSurface* deformableSurface) PX_OVERRIDE;
virtual void addParticleSystem(Dy::ParticleSystem* particleSystem, const PxNodeIndex& nodeIndex) PX_OVERRIDE;
virtual void releaseParticleSystem(Dy::ParticleSystem* particleSystem) PX_OVERRIDE;
virtual void releaseDeferredParticleSystemIds() PX_OVERRIDE;
virtual void updateDynamic(Dy::FeatherstoneArticulation* articulation, const PxNodeIndex& nodeIndex) PX_OVERRIDE;
virtual void updateBodies(PxsRigidBody** rigidBodies, PxU32* nodeIndices, const PxU32 nbBodies, PxsExternalAccelerationProvider* externalAccelerations) PX_OVERRIDE;
virtual void addJoint(const Dy::Constraint&) PX_OVERRIDE;
virtual void updateJoint(const PxU32 edgeIndex, Dy::Constraint* constraint) PX_OVERRIDE;
virtual void updateBodies(PxBaseTask* continuation) PX_OVERRIDE;
virtual void updateShapes(PxBaseTask* continuation) PX_OVERRIDE;
virtual void preIntegrateAndUpdateBound(PxBaseTask* continuation, const PxVec3 gravity, const PxReal dt) PX_OVERRIDE;
virtual void updateParticleSystemsAndSoftBodies() PX_OVERRIDE;
virtual void sortContacts() PX_OVERRIDE;
virtual void update(PxBitMapPinned& changedHandleMap) PX_OVERRIDE;
virtual void mergeChangedAABBMgHandle() PX_OVERRIDE;
virtual void gpuDmabackData(PxsTransformCache& cache, Bp::BoundsArray& boundArray, PxBitMapPinned& changedAABBMgrHandles, bool enableDirectGPUAPI) PX_OVERRIDE;
virtual void updateScBodyAndShapeSim(PxsTransformCache& cache, Bp::BoundsArray& boundArray, PxBaseTask* continuation) PX_OVERRIDE;
virtual void updateArticulation(Dy::FeatherstoneArticulation* articulation, const PxNodeIndex& nodeIndex) PX_OVERRIDE;
virtual void updateArticulationJoint(Dy::FeatherstoneArticulation* articulation, const PxNodeIndex& nodeIndex) PX_OVERRIDE;
virtual void updateArticulationExtAccel(Dy::FeatherstoneArticulation* articulation, const PxNodeIndex& nodeIndex) PX_OVERRIDE;
virtual void updateArticulationAfterIntegration(PxsContext* /*llContext*/, Bp::AABBManagerBase* /*aabbManager*/,
PxArray<Sc::BodySim*>& /*ccdBodies*/, PxBaseTask* /*continuation*/, IG::IslandSim& /*islandSim*/, float /*dt*/) PX_OVERRIDE {}
virtual PxU32* getActiveBodies() PX_OVERRIDE;
virtual PxU32* getDeactiveBodies() PX_OVERRIDE;
virtual void** getRigidBodies() PX_OVERRIDE;
virtual PxU32 getNbBodies() PX_OVERRIDE;
virtual Sc::ShapeSimBase** getShapeSims() PX_OVERRIDE;
virtual PxU32* getUnfrozenShapes() PX_OVERRIDE;
virtual PxU32* getFrozenShapes() PX_OVERRIDE;
virtual PxU32 getNbFrozenShapes() PX_OVERRIDE;
virtual PxU32 getNbUnfrozenShapes() PX_OVERRIDE;
virtual PxU32 getNbShapes() PX_OVERRIDE;
virtual void clear() PX_OVERRIDE { mNbFrozenShapes = 0; mNbUnfrozenShapes = 0; }
virtual void setBounds(Bp::BoundsArray* boundArray) PX_OVERRIDE;
virtual void reserve(const PxU32 nbBodies) PX_OVERRIDE;
PX_INLINE PxU32 getArticulationRemapIndex(const PxU32 nodeIndex) { return mBodySimManager.getArticulationRemapIndex(nodeIndex); }
virtual void setDeformableSurfaceGpuPostSolveCallback(PxPostSolveCallback* postSolveCallback) PX_OVERRIDE PX_FINAL;
virtual void setDeformableVolumeGpuPostSolveCallback(PxPostSolveCallback* postSolveCallback) PX_OVERRIDE PX_FINAL;
// deprecated direct-GPU API
PX_DEPRECATED virtual void copySoftBodyDataDEPRECATED(void** data, void* dataEndIndices, void* softBodyIndices, PxSoftBodyGpuDataFlag::Enum flag, const PxU32 nbCopySoftBodies, const PxU32 maxSize, CUevent copyEvent) PX_OVERRIDE PX_FINAL;
PX_DEPRECATED virtual void applySoftBodyDataDEPRECATED(void** data, void* dataEndIndices, void* softBodyIndices, PxSoftBodyGpuDataFlag::Enum flag, const PxU32 nbUpdatedSoftBodies, const PxU32 maxSize, CUevent applyEvent, CUevent signalEvent) PX_OVERRIDE PX_FINAL;
PX_DEPRECATED virtual void applyParticleBufferDataDEPRECATED(const PxU32* indices, const PxGpuParticleBufferIndexPair* indexPair, const PxParticleBufferFlags* flags, PxU32 nbUpdatedBuffers, CUevent waitEvent, CUevent signalEvent) PX_OVERRIDE;
// end deprecated direct-GPU API
// new direct-GPU API
virtual bool getRigidDynamicData(void* data, const PxRigidDynamicGPUIndex* gpuIndices, PxRigidDynamicGPUAPIReadType::Enum dataType, PxU32 nbElements, float oneOverDt, CUevent startEvent, CUevent finishEvent) const PX_OVERRIDE PX_FINAL;
virtual bool setRigidDynamicData(const void* data, const PxRigidDynamicGPUIndex* gpuIndices, PxRigidDynamicGPUAPIWriteType::Enum dataType, PxU32 nbElements, CUevent startEvent, CUevent finishEvent) PX_OVERRIDE PX_FINAL;
virtual bool getArticulationData(void* data, const PxArticulationGPUIndex* gpuIndices, PxArticulationGPUAPIReadType::Enum dataType, PxU32 nbElements, CUevent startEvent, CUevent finishEvent) const PX_OVERRIDE PX_FINAL;
virtual bool setArticulationData(const void* data, const PxArticulationGPUIndex* gpuIndices, PxArticulationGPUAPIWriteType::Enum dataType, PxU32 nbElements, CUevent startEvent, CUevent finishEvent) PX_OVERRIDE PX_FINAL;
virtual bool computeArticulationData(void* data, const PxArticulationGPUIndex* gpuIndices, PxArticulationGPUAPIComputeType::Enum operation, PxU32 nbElements, CUevent startEvent, CUevent finishEvent) PX_OVERRIDE PX_FINAL;
virtual bool evaluateSDFDistances(PxVec4* localGradientAndSDFConcatenated, const PxShapeGPUIndex* shapeIndices, const PxVec4* localSamplePointsConcatenated, const PxU32* samplePointCountPerShape, PxU32 nbElements, PxU32 maxPointCount, CUevent startEvent, CUevent finishEvent) PX_OVERRIDE PX_FINAL;
virtual bool copyContactData(void* data, PxU32* numContactPairs, const PxU32 maxContactPairs, CUevent startEvent, CUevent copyEvent) PX_OVERRIDE PX_FINAL;
virtual PxArticulationGPUAPIMaxCounts getArticulationGPUAPIMaxCounts() const PX_OVERRIDE PX_FINAL;
virtual bool getD6JointData(void* data, const PxD6JointGPUIndex* gpuIndices, PxD6JointGPUAPIReadType::Enum dataType, PxU32 nbElements, PxF32 oneOverDt, CUevent startEvent, CUevent finishEvent) const PX_OVERRIDE PX_FINAL;
// end new direct-GPU API
virtual PxU32 getInternalShapeIndex(const PxsShapeCore& shapeCore) PX_OVERRIDE PX_FINAL;
virtual void syncParticleData() PX_OVERRIDE;
virtual void updateBoundsAndShapes(Bp::AABBManagerBase& aabbManager, bool useDirectApi) PX_OVERRIDE;
PX_FORCE_INLINE PxgSimulationCore* getSimulationCore() { return mSimulationCore; }
PX_FORCE_INLINE PxgJointManager& getJointManager() { return mJointManager; }
PX_FORCE_INLINE PxgBodySimManager& getBodySimManager() { return mBodySimManager; }
PX_FORCE_INLINE PxgPBDParticleSystemCore* getPBDParticleSystemCore() { return mPBDParticleSystemCore; }
PX_FORCE_INLINE PxgSoftBodyCore* getSoftBodyCore() { return mSoftBodyCore; }
PX_FORCE_INLINE PxgFEMClothCore* getFEMClothCore() { return mFEMClothCore; }
PX_FORCE_INLINE PxgSoftBody* getSoftBodies() { return mSoftBodyPool.begin(); }
PX_FORCE_INLINE PxU32 getNbSoftBodies() { return mSoftBodyPool.size(); }
PX_FORCE_INLINE PxU32* getActiveSoftBodies() { return mBodySimManager.mActiveSoftbodies.begin(); }
PX_FORCE_INLINE PxU32 getNbActiveSoftBodies() { return mBodySimManager.mActiveSoftbodies.size(); }
PX_FORCE_INLINE PxU32* getSoftBodyNodeIndex() { return mSoftBodyNodeIndexPool.begin(); }
PX_FORCE_INLINE PxgFEMCloth* getFEMCloths() { return mFEMClothPool.begin(); }
PX_FORCE_INLINE PxU32 getNbFEMCloths() { return mFEMClothPool.size(); }
PX_FORCE_INLINE PxU32* getActiveFEMCloths() { return mBodySimManager.mActiveFEMCloths.begin(); }
PX_FORCE_INLINE PxU32 getNbActiveFEMCloths() { return mBodySimManager.mActiveFEMCloths.size(); }
PX_FORCE_INLINE PxU32* getFEMClothNodeIndex() { return mFEMClothNodeIndexPool.begin(); }
void postCopyToShapeSim();
void postCopyToBodySim(bool enableBodyAccelerations);
//integrate particle system and update bound/update grid/self collision
void preIntegrateAndUpdateBoundParticleSystem(const PxVec3 gravity, const PxReal dt);
void preIntegrateAndUpdateBoundSoftBody(const PxVec3 gravity, const PxReal dt);
void preIntegrateAndUpdateBoundFEMCloth(const PxVec3 gravity, const PxReal dt);
void updateJointsAndSyncData();
void computeSoftBodySimMeshData(Dy::DeformableVolume* deformableVolume, PxU32 tetId, const PxVec4& tetBarycentric,
PxU32& outTetId, PxVec4& outTetBarycentric);
PX_FORCE_INLINE PxU32 getMaxLinks() { return mMaxLinks; }
PX_FORCE_INLINE PxU32 getMaxFemContacts() { return mMaxFemClothContacts; }
virtual PxU32 getNbDeactivatedDeformableSurfaces() const PX_OVERRIDE;
virtual PxU32 getNbActivatedDeformableSurfaces() const PX_OVERRIDE;
virtual Dy::DeformableSurface** getDeactivatedDeformableSurfaces() const PX_OVERRIDE;
virtual Dy::DeformableSurface** getActivatedDeformableSurfaces() const PX_OVERRIDE;
virtual PxU32 getNbDeactivatedDeformableVolumes() const PX_OVERRIDE;
virtual PxU32 getNbActivatedDeformableVolumes() const PX_OVERRIDE;
virtual Dy::DeformableVolume** getDeactivatedDeformableVolumes() const PX_OVERRIDE;
virtual Dy::DeformableVolume** getActivatedDeformableVolumes() const PX_OVERRIDE;
virtual const PxReal* getDeformableVolumeWakeCounters() const PX_OVERRIDE;
virtual void setEnableOVDReadback(bool enableOVDReadback) PX_OVERRIDE;
virtual bool getEnableOVDReadback() const PX_OVERRIDE;
virtual void setEnableOVDCollisionReadback(bool enableOVDCollisionsReadback) PX_OVERRIDE;
virtual bool getEnableOVDCollisionReadback() const PX_OVERRIDE;
#if PX_SUPPORT_OMNI_PVD
virtual void setOVDCallbacks(PxsSimulationControllerOVDCallbacks& ovdCallbacks) PX_OVERRIDE;
PX_FORCE_INLINE PxsSimulationControllerOVDCallbacks* getOVDCallbacks() { return mOvdCallbacks; }
#endif
virtual bool hasDeformableSurfaces() const PX_OVERRIDE { return mFEMClothCore != NULL; }
virtual bool hasDeformableVolumes() const PX_OVERRIDE { return mSoftBodyCore != NULL; }
bool getRecomputeArticulationBlockFormat() const { return mRecomputeArticulationBlockFormat; }
private:
void copyToGpuBodySim(PxBaseTask* continuation);
void copyToGpuParticleSystem(PxBaseTask* continuation);
void copyToGpuSoftBody(PxBaseTask* continuation);
void copyToGpuFEMCloth(PxBaseTask* continuation);
void copyToGpuBodySim(const PxU32 bodySimOffset, PxU32 bodyStartIndex, PxU32 nbToCopy);
void copyToGpuArticulationSim(const PxU32 bodySimOffset, PxU32 startIndex, PxU32 nbToCopy,
PxI32* sharedArticulationLinksIndex, PxI32* sharedArticulationDofIndex,
PxI32* sharedArticulationSpatialTendonIndex,
PxI32* sharedArticulationAttachmentIndex,
PxI32* sharedArticulationFixedTendonIndex,
PxI32* sharedArticulationTendonJointIndex,
PxI32* sharedArticulationMimicJointIndex,
PxI32* sharedArticulationPathToRootIndex);
void updateGpuArticulationSim(PxU32 startIndex, PxU32 nbToCopy,
PxI32* sharedArticulationLinksIndex, PxI32* sharedArticulationDofIndex,
PxI32* sharedSpatialTendonIndex, PxI32* sharedAttachmentIndex,
PxI32* sharedFixedTendonIndex, PxI32* sharedFixedTendonJointIndex,
PxI32* sharedMimicJointIndex);
void copyToGpuSoftBodySim(PxU32 startIndex, PxU32 nbToCopy);
void copyToGpuFEMClothSim(PxU32 startIndex, PxU32 nbToCopy);
void copyToGpuPBDParticleSystemSim(PxU32 startIndex, PxU32 nbToCopy);
// bounds are shared by NP and BP, so we have the update in the simulation controller.
// cache is for np, we update it together with bounds due to similar update logic
void updateBoundsAndTransformCache(Bp::AABBManagerBase& aabbManager, CUstream stream, PxsTransformCache& cache, PxgCudaBuffer& mGpuTransformCache);
void copyBoundsAndTransforms(Bp::BoundsArray& boundsArray, PxsTransformCache& transformCache,
PxgCudaBuffer& gpuTransformCache, PxU32 boundsArraySize,
PxU32 totalTransformCacheSize, CUstream npStream);
void mergeBoundsAndTransformsChanges(PxgBoundsArray& directGPUBoundsArray,
PxsTransformCache& transformCache,
PxgCudaBuffer& gpuTransformCache, PxU32 boundsArraySize, PxU32 totalTransformCacheSize,
PxU32 numChanges, CUstream npStream);
#if PXG_SC_DEBUG
void validateCacheAndBounds(PxBoundsArrayPinned& boundArray, PxCachedTransformArrayPinned& cachedTransform);
#endif
PxgPostCopyToShapeSimTask mPostCopyShapeSimTask;
PxgPostCopyToBodySimTask mPostCopyBodySimTask;
PxgPostUpdateParticleAndSoftBodyTask mPostUpdateParticleSystemTask;
PxgBodySimManager mBodySimManager;
PxgJointManager mJointManager;
PxgSimulationCore* mSimulationCore;
PxgSoftBodyCore* mSoftBodyCore;
PxgFEMClothCore* mFEMClothCore;
PxgPBDParticleSystemCore* mPBDParticleSystemCore;
PxgGpuContext* mDynamicContext;
PxgNphaseImplementationContext* mNpContext;
PxPinnedArray<PxgBodySim> mNewBodySimPool;
PxPinnedArray<PxgArticulationLink> mLinksPool;
PxFloatArrayPinned mLinkWakeCounterPool;
PxPinnedArray<Cm::UnAlignedSpatialVector> mLinkAccelPool;
PxPinnedArray<PxgArticulationLinkProp> mLinkPropPool;
PxPinnedArray<PxgArticulationLinkSleepData> mLinkSleepDataPool;
PxPinnedArray<ArticulationBitField> mLinkChildPool;
PxInt32ArrayPinned mLinkParentPool;
PxPinnedArray<PxTransform> mLinkBody2WorldPool;
PxPinnedArray<PxTransform> mLinkBody2ActorPool;
PxPinnedArray<Dy::ArticulationJointCore> mJointPool;
PxPinnedArray<Dy::ArticulationJointCoreData> mJointDataPool;
PxPinnedArray<PxgArticulationSimUpdate> mLinkJointIndexPool; //this record the start index of the link for an articulation in an array
PxPinnedArray<PxgArticulation> mArticulationPool;
PxPinnedArray<PxGpuSpatialTendonData> mSpatialTendonParamPool;
PxPinnedArray<PxgArticulationTendon> mSpatialTendonPool;
PxPinnedArray<PxgArticulationTendonElementFixedData> mAttachmentFixedPool;
PxPinnedArray<PxGpuTendonAttachmentData> mAttachmentModPool;
PxInt32ArrayPinned mTendonAttachmentMapPool; //store each start index of the attachment to the corresponding tendons
PxPinnedArray<PxGpuFixedTendonData> mFixedTendonParamPool;
PxPinnedArray<PxgArticulationTendon> mFixedTendonPool;
PxPinnedArray<PxgArticulationTendonElementFixedData> mTendonJointFixedDataPool;
PxPinnedArray<PxGpuTendonJointCoefficientData> mTendonJointCoefficientDataPool;
PxInt32ArrayPinned mTendonTendonJointMapPool; //store each start index of the attachment to the corresponding tendons
PxInt32ArrayPinned mPathToRootPool;
PxPinnedArray<Dy::ArticulationMimicJointCore> mMimicJointPool;
PxPinnedArray<PxgArticulationSimUpdate> mArticulationUpdatePool; //Articulation update headers
PxFloatArrayPinned mArticulationDofDataPool; //Articulation dof information (jointV, jointP etc.)
PxPinnedArray<PxgSoftBody> mNewSoftBodyPool;
PxArray<PxgSoftBodyData> mNewSoftBodyDataPool;
PxPinnedArray<PxgSoftBody> mSoftBodyPool;
PxArray<PxgSoftBodyData> mSoftBodyDataPool;
PxInt32ArrayPinned mSoftBodyElementIndexPool;
PxArray<PxU32> mNewSoftBodyNodeIndexPool;
PxArray<PxU32> mNewSoftBodyElementIndexPool;
PxArray<PxU32> mSoftBodyNodeIndexPool;
PxArray<PxU32> mNewTetMeshByteSizePool;
AttachmentManager<PxgFEMFEMAttachment> mParticleSoftBodyAttachments;
PxPinnedArray<PxgNonRigidFilterPair> mSoftBodyParticleFilterPairs;
PxArray<PxU32> mSoftBodyParticleFilterRefs;
AttachmentManager<PxgFEMRigidAttachment> mRigidSoftBodyAttachments;
PxPinnedArray<PxgRigidFilterPair> mSoftBodyRigidFilterPairs;
PxArray<PxU32> mSoftBodyRigidFilterRefs;
AttachmentManager<PxgFEMFEMAttachment> mSoftBodySoftBodyAttachments;
PxArray <Dy::DeformableVolume*> mDirtyDeformableVolumeForFilterPairs;
AttachmentManager<PxgFEMFEMAttachment> mSoftBodyClothAttachments;
PxPinnedArray<PxgNonRigidFilterPair> mSoftBodyClothTetVertFilterPairs;
PxArray<PxU32> mSoftBodyClothTetVertFilterRefs;
AttachmentManager<PxgFEMFEMAttachment> mClothClothAttachments;
PxPinnedArray<PxgNonRigidFilterPair> mClothClothVertTriFilterPairs;
PxArray<PxU32> mClothClothVertTriFilterRefs;
PxPinnedArray<PxgFEMCloth> mNewFEMClothPool;
PxArray<PxgFEMClothData> mNewFEMClothDataPool;
PxPinnedArray<PxgFEMCloth> mFEMClothPool;
PxArray<PxgFEMClothData> mFEMClothDataPool;
PxInt32ArrayPinned mFEMClothElementIndexPool;
PxArray<PxU32> mNewFEMClothNodeIndexPool;
PxArray<PxU32> mNewFEMClothElementIndexPool;
PxArray<PxU32> mFEMClothNodeIndexPool;
PxArray<PxU32> mNewTriangleMeshByteSizePool;
AttachmentManager<PxgFEMRigidAttachment> mClothRigidAttachments;
PxPinnedArray<PxgRigidFilterPair> mClothRigidFilterPairs;
PxArray<PxU32> mClothRigidFilterRefs;
PxInt32ArrayPinned mFrozenPool;
PxInt32ArrayPinned mUnfrozenPool;
PxInt32ArrayPinned mActivatePool;
PxInt32ArrayPinned mDeactivatePool;
PxU32 mNbFrozenShapes;
PxU32 mNbUnfrozenShapes;
bool mHasBeenSimulated;//if there are no bodies in the scene, we don't run the update method so that we shouldn't need to syncback data
PxI32 mSharedLinkIndex;
PxI32 mSharedDofIndex;
PxI32 mSharedSpatialTendonIndex;
PxI32 mSharedSpatialAttachmentIndex;
PxI32 mSharedFixedTendonIndex;
PxI32 mSharedFixedTendonJointIndex;
PxI32 mSharedMimicJointIndex;
PxI32 mSharedPathToRootIndex;
PxgCudaKernelWranglerManager* mGpuWranglerManager;
PxCudaContextManager* mCudaContextManager;
PxgHeapMemoryAllocatorManager* mHeapMemoryManager;
PxgCudaBroadPhaseSap* mBroadPhase;
PxU32 mMaxLinks;
PxU32 mMaxDofs;
PxU32 mMaxMimicJoints;
PxU32 mMaxSpatialTendons;
PxU32 mMaxAttachments;
PxU32 mMaxFixedTendons;
PxU32 mMaxTendonJoints;
PxU32 mMaxPathToRoots;
PxU32 mMaxSoftBodyContacts;
PxU32 mMaxFemClothContacts;
PxU32 mMaxParticleContacts;
PxU32 mCollisionStackSizeBytes;
bool mRecomputeArticulationBlockFormat;
bool mEnableOVDReadback;
bool mEnableOVDCollisionReadback;
#if PX_SUPPORT_OMNI_PVD
PxsSimulationControllerOVDCallbacks* mOvdCallbacks;
#endif
friend class PxgCopyToBodySimTask;
friend class PxgCopyToArticulationSimTask;
friend class PxgUpdateArticulationSimTask;
friend class PxgCopyToSoftBodySimTask;
friend class PxgCopyToFEMClothSimTask;
friend class PxgCopyToPBDParticleSystemSimTask;
friend class PxgSimulationCore;
};
}
#endif

View File

@@ -0,0 +1,594 @@
// 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_SIMULATION_CORE_H
#define PXG_SIMULATION_CORE_H
#include "PxgCudaBuffer.h"
#include "PxgSimulationCoreDesc.h"
#include "PxgSoftBody.h"
#include "PxgSimulationController.h"
#include "PxgFEMCloth.h"
#include "foundation/PxUserAllocated.h"
#include "PxgFEMCore.h"
#include "PxgShapeSimManager.h"
namespace physx
{
class PxCudaContextManager;
class PxCudaContext;
class KernelWrangler;
class PxgCudaSolverCore;
class PxgGpuNarrowphaseCore;
class PxgCudaBroadPhaseSap;
class PxgParticleSystemCore;
class PxgSoftBodyCore;
class PxgFEMClothCore;
struct PxsCachedTransform;
class PxgCudaKernelWranglerManager;
class PxgSoftBodyBuffer;
class PxgFEMClothBuffer;
class PxgParticleSystemBuffer;
class PxgBodySimManager;
class PxgGpuContext;
class PxSceneDesc;
class PxgSimulationCore : public PxUserAllocated
{
PX_NOCOPY(PxgSimulationCore)
public:
PxgSimulationCore(PxgCudaKernelWranglerManager* gpuKernelWrangler,
PxCudaContextManager* cudaContextManager,
PxgHeapMemoryAllocatorManager* heapMemoryManager,
PxgGpuContext* gpuContext,
const bool useGpuBroadphase);
~PxgSimulationCore();
void gpuMemDmaUpBodySim(PxPinnedArray<PxgBodySimVelocityUpdate>& updatedBodySim,
PxPinnedArray<PxgBodySim>& newBodySim,
PxPinnedArray<PxgArticulationLink>& newLinkPool,
PxFloatArrayPinned& newLinkWakeCounterPool,
PxPinnedArray<Cm::UnAlignedSpatialVector>& newLinkExtAccelPool,
PxPinnedArray<PxgArticulationLinkProp>& newLinkPropPool,
PxInt32ArrayPinned& newLinkParentsPool,
PxPinnedArray<Dy::ArticulationBitField>& newLinkChildPool,
PxPinnedArray<PxTransform>& newLinkBody2WorldsPool,
PxPinnedArray<PxTransform>& newLinkBody2ActorsPool,
PxPinnedArray<Dy::ArticulationJointCore>& newJointCorePool,
PxPinnedArray<Dy::ArticulationJointCoreData>& newJointDataPool,
PxPinnedArray<PxgArticulationSimUpdate>& newLinkJointIndexPool,
PxPinnedArray<PxgArticulation>& newArticulationPool,
PxPinnedArray<PxGpuSpatialTendonData>& newSpatialTendonParamsPool,
PxPinnedArray<PxgArticulationTendon>& newSpatialTendonPool,
PxPinnedArray<PxgArticulationTendonElementFixedData>& newAttachmentFixedPool,
PxPinnedArray<PxGpuTendonAttachmentData>& newAttachmentModPool,
PxInt32ArrayPinned& newTendonToAttachmentRemapPool,
PxPinnedArray<PxGpuFixedTendonData>& newFixedTendonParamsPool,
PxPinnedArray<PxgArticulationTendon>& newFixedTendonPool,
PxPinnedArray<PxgArticulationTendonElementFixedData>& newTendonJointFixedPool,
PxPinnedArray<PxGpuTendonJointCoefficientData>& newTendonJointCoefficientPool,
PxInt32ArrayPinned& newTendonToTendonJointRemapPool,
PxPinnedArray<Dy::ArticulationMimicJointCore>& newMimicJointPool,
PxInt32ArrayPinned& newPathToRootPool,
PxU32 nbTotalBodies, PxU32 nbTotalArticulations, PxU32 maxLinks,
PxU32 maxDofs, PxU32 maxMimicJoints, PxU32 maxSpatialTendons,
PxU32 maxAttachments, PxU32 maxFixedTendons, PxU32 maxTendonJoints,
bool enableBodyAccelerations);
void gpuMemDmaUpSoftBodies(PxPinnedArray<PxgSoftBody>& newSoftBodyPool,
PxU32* newTetMeshByteSizePool,
PxArray<PxgSoftBodyData>& newSoftBodyDataPool,
PxArray<PxU32>& newSoftBodyNodeIndexPool,
PxArray<PxU32>& newSoftBodyElememtIndexPool,
PxPinnedArray<PxgSoftBody>& softBodyPool,
PxArray<PxgSoftBodyData>& softBodyDataPool,
PxInt32ArrayPinned& softBodyElementIndexPool,
PxArray<PxU32>& softBodyNodeIndexPool,
PxgBodySimManager& bodySimManager,
SoftBodyAttachmentAndFilterData& data);
void gpuMemDmaUpFEMCloths(PxPinnedArray<PxgFEMCloth>& newFEMClothPool,
PxU32* newTriangleMeshByteSizePool,
PxArray<PxgFEMClothData>& newFEMClothDataPool,
PxArray<PxU32>& newFEMClothNodeIndexPool,
PxArray<PxU32>& newFEMClothElememtIndexPool,
PxPinnedArray<PxgFEMCloth>& femClothPool,
PxArray<PxgFEMClothData>& femClothDataPool,
PxInt32ArrayPinned& femClothElementIndexPool,
PxArray<PxU32>& femClothNodeIndexPool,
PxgBodySimManager& bodySimManager,
PxPinnedArray<PxgFEMRigidAttachment>& rigidAttachments,
PxPinnedArray<PxgRigidFilterPair>& rigidAttachmentIds,
bool dirtyRigidAttachments,
PxInt32ArrayPinned& activeRigidAttachments,
bool dirtyActiveRigidAttachments,
PxPinnedArray<PxgFEMFEMAttachment>& clothAttachments,
PxPinnedArray<PxgNonRigidFilterPair>& clothVertTriFilterIds,
bool dirtyClothAttachments,
PxInt32ArrayPinned& activeClothAttachments,
bool dirtyActiveClothAttachments
);
void gpuMemDmaUpParticleSystem(PxgBodySimManager& bodySimManager);
void mergeChangedAABBMgHandle();
void gpuMemDmaUp(const PxU32 nbTotalBodies, const PxU32 nbTotalShapes,
PxBitMapPinned& changedHandleMap, const bool enableDirectGPUAPI);
void gpuMemDmaBack(PxInt32ArrayPinned& frozenArray,
PxInt32ArrayPinned& unfrozenArray,
PxInt32ArrayPinned& activateArray,
PxInt32ArrayPinned& deactiveArray,
PxCachedTransformArrayPinned* cachedTransform,
const PxU32 cachedCapacity,
Bp::BoundsArray& boundArray, PxBitMapPinned& changedAABBMgrHandles,
const PxU32 numShapes, const PxU32 numActiveBodies, bool enableDirectGPUAPI);
void syncDmaback(PxU32& nbFrozenShapesThisFrame, PxU32& nbUnfrozenShapesThisFrame, bool didSimulate);
void updateBodies(const PxU32 nbUpdatedBodies, const PxU32 nbNewBodies);
void updateArticulations(const PxU32 nbNewArticulations, PxgArticulationSimUpdate* updates,
const PxU32 nbUpdatedArticulations, PxReal* dofData);
void updateJointsAndSyncData(const PxPinnedArray<PxgD6JointData>& rigidJointData,
const PxInt32ArrayPinned& dirtyRigidJointIndices,
const PxPinnedArray<PxgD6JointData>& artiJointData,
const PxInt32ArrayPinned& dirtyArtiJointIndices,
const PxPinnedArray<PxgConstraintPrePrep>& rigidJointPrePrep,
const PxPinnedArray<PxgConstraintPrePrep>& artiJointPrePrep,
const PxgJointManager::ConstraintIdMap& gpuConstraintIdMapHost,
bool isGpuConstraintIdMapDirty,
PxU32 nbTotalRigidJoints, PxU32 nbTotalArtiJoints);
void update(bool enableDirectGPUAPI);
void setBounds(Bp::BoundsArray* boundArray);
PxgArticulationBuffer** getArticulationDataBuffer() { return mArticulationDataBuffer.begin(); }
PxgTypedCudaBuffer<PxBounds3>* getBoundArrayBuffer();
void gpuDmaUpdateData();
bool getRigidDynamicData(void* data, const PxRigidDynamicGPUIndex* gpuIndices, PxRigidDynamicGPUAPIReadType::Enum dataType, PxU32 nbElements, float oneOverDt, CUevent startEvent, CUevent finishEvent) const;
bool setRigidDynamicData(const void* data, const PxRigidDynamicGPUIndex* gpuIndices, PxRigidDynamicGPUAPIWriteType::Enum dataType, PxU32 nbElements, CUevent startEvent, CUevent finishEvent);
void setSoftBodyWakeCounter(const PxU32 remapId, const PxReal wakeCounter, const PxU32 numSoftBodies);
void setFEMClothWakeCounter(const PxU32 remapId, const PxReal wakeCounter, const PxU32 numClothes);
// PT: wrappers to make it easier to find the places where this is used.
PX_FORCE_INLINE PxgDevicePointer<PxgBodySim> getBodySimBufferDevicePtr() const { return mBodySimCudaBuffer.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgBodySim> getBodySimBufferDeviceData() { return mBodySimCudaBuffer.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgBodySimVelocities> getBodySimPrevVelocitiesBufferDevicePtr() const { return mBodySimPreviousVelocitiesCudaBuffer.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgBodySimVelocities> getBodySimPrevVelocitiesBufferDeviceData() { return mBodySimPreviousVelocitiesCudaBuffer.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulation>& getArticulationBuffer() { return mArticulationBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgSolverBodySleepData>& getArticulationSleepDataBuffer() { return mArticulationSleepDataBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationBlockData>& getArticulationBatchData() { return mArticulationBatchBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationBlockLinkData>& getArticulationBatchLinkData() { return mArticulationLinkBatchBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationTraversalStackData>& getArticulationTraversalStackData() { return mArticulationTraversalStackBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationBitFieldStackData>& getTempPathToRootBitFieldStackData() { return mTempPathToRootBitFieldStackBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationBitFieldStackData>& getTempSharedBitFieldStackData() { return mTempSharedBitFieldStackBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationBitFieldStackData>& getTempRootBitFieldStackData() { return mTempRootBitFieldStackBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationBitFieldData>& getPathToRootBitFieldStackData() { return mPathToRootBitFieldStackBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationBlockDofData>& getArticulationBatchDofData() { return mArticulationDofBatchBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationBlockMimicJointData>& getArticulationBatchMimicJointData() { return mArticulationMimicJointBatchBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationBlockSpatialTendonData>& getArticulationBatchSpatialTendonData() { return mArticulationSpatialTendonBatchBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationBlockAttachmentData>& getArticulationBatchAttachmentData() { return mArticulationAttachmentBatchBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationInternalTendonConstraintData>& getArticulationBatchSpatialTendonConstraintData() { return mArticulationSpatialTendonConstraintsBatchBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationBlockFixedTendonData>& getArticulationBatchFixedTendonData() { return mArticulationFixedTendonBatchBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationBlockTendonJointData>& getArticulationBatchTendonJointData() { return mArticulationTendonJointBatchBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgArticulationInternalTendonConstraintData>& getArticulationBatchFixedTendonConstraintData() { return mArticulationFixedTendonConstraintsBatchBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgSoftBody>& getSoftBodyBuffer() { return mSoftBodyBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getActiveSoftBodyBuffer() { return mActiveSoftBodyBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getActiveSelfCollisionSoftBodyBuffer() { return mActiveSelfCollisionSoftBodyBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getSoftBodyElementIndexBuffer() { return mSoftBodyElementIndexBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgFEMCloth>& getFEMClothBuffer() { return mFEMClothBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getActiveFEMClothBuffer() { return mActiveFEMClothBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxU32>& getFEMClothElementIndexBuffer() { return mFEMClothElementIndexBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgD6JointData>& getD6RigidJointBuffer() { return mRigidJointBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgConstraintPrePrep>& getD6RigidJointPrePreBuffer() { return mRigidJointPrePrepBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgD6JointData>& getD6ArtiJointBuffer() { return mArtiJointBuffer; }
PX_FORCE_INLINE PxgTypedCudaBuffer<PxgConstraintPrePrep>& getD6ArtiJointPrePreBuffer() { return mArtiJointPrePrepBuffer; }
PX_FORCE_INLINE CUstream getStream() { return mStream; }
bool getD6JointData(void* data, const PxD6JointGPUIndex* gpuIndices, PxD6JointGPUAPIReadType::Enum dataType, PxU32 nbElements, PxF32 oneOverDt,
PxU32 directGpuApiIndexMapHostSize, CUevent startEvent, CUevent finishEvent) const;
//soft body
PX_FORCE_INLINE PxU32 getMaxTetraVerts() { return mMaxTetraVerts; }
PX_FORCE_INLINE PxU32 getMaxTetrahedrons() { return mMaxTetrahedrons; }
PX_FORCE_INLINE PxU32 getGMMaxTetraPartitions() { return mGMMaxPartitions; }
PX_FORCE_INLINE PxU32 getGMMaxTetraVerts() { return mGMMaxTetraVerts; }
PX_FORCE_INLINE PxU32 getGMMaxTetrahedrons() { return mGMMaxTetrahedrons; }
PX_FORCE_INLINE PxU32 getGMMaxTetrahedronsPerPartition() { return mGMMaxTetrahedronsPerPartition; }
PX_FORCE_INLINE PxU32 getGMMaxJacobiTetrahedrons() { return mGMMaxJacobiTetrahedrons; }
PX_FORCE_INLINE PxU32 getGMMaxJacobiVertices() { return mGMMaxJacobiVertices; }
PX_FORCE_INLINE bool getGMUsePartitionAveraging() { return mUsePartitionAveraging; }
// FEM-cloth
PX_FORCE_INLINE PxU32 getMaxClothVerts() { return mMaxNbClothVerts; }
PX_FORCE_INLINE PxU32 getMaxClothTriangles() { return mMaxNbClothTriangles; }
PX_FORCE_INLINE PxU32 getMaxClothTrianglesWithActiveEdges() { return mMaxNbClothTrianglesWithActiveEdges; }
PX_FORCE_INLINE PxU32 getMaxNonSharedTrianglePartitions() { return mMaxNbNonSharedTriPartitions; }
PX_FORCE_INLINE PxU32 getMaxNonSharedTrianglesPerPartition() { return mMaxNbNonSharedTrianglesPerPartition; }
PX_FORCE_INLINE PxU32 getMaxNbNonSharedTriangles() { return mMaxNbNonSharedTriangles; }
PX_FORCE_INLINE PxU32 getMaxSharedTrianglePairPartitions() { return mMaxNbSharedTriPairPartitions; }
PX_FORCE_INLINE PxU32 getMaxNonSharedTrianglePairPartitions() { return mMaxNbNonSharedTriPairPartitions; }
PX_FORCE_INLINE PxU32 getMaxNonSharedTriangleClusterId() { return mMaxNonSharedTriClusterId; }
PX_FORCE_INLINE PxU32 getMaxSharedTrianglePairClusterId() { return mMaxSharedTriPairClusterId; }
PX_FORCE_INLINE PxU32 getMaxNonSharedTrianglePairClusterId() { return mMaxNonSharedTriPairClusterId; }
PX_FORCE_INLINE PxU32 getMaxSharedTrianglePairsPerPartition() { return mMaxNbSharedTrianglePairsPerPartition; }
PX_FORCE_INLINE PxU32 getMaxNonSharedTrianglePairsPerPartition() { return mMaxNbNonSharedTrianglePairsPerPartition; }
PX_FORCE_INLINE PxU32 getMaxNbSharedTrianglePairs() { return mMaxNbSharedTrianglePairs; }
PX_FORCE_INLINE PxU32 getMaxNbNonSharedTrianglePairs() { return mMaxNbNonSharedTrianglePairs; }
PX_FORCE_INLINE bool hasActiveBendingPairs() { return mHasActiveBendingPairs; }
PX_FORCE_INLINE PxU32 getMaxNbCollisionPairUpdatesPerTimestep() { return mMaxNbCollisionPairUpdatesPerTimestep; }
PX_FORCE_INLINE PxU32 getMaxNbCollisionSubsteps() { return mMaxNbCollisionSubsteps; }
PX_FORCE_INLINE PxU32 getNumTotalFEMCloths() { return mNbTotalFEMCloths; }
PX_FORCE_INLINE PxU32 getNumTotalShapes() { return mPxgShapeSimManager.getNbTotalShapeSims(); }
PX_FORCE_INLINE PxU32 getNumTotalSoftbodies() { return mNbTotalSoftBodies; }
PX_FORCE_INLINE PxU32 getNbRigidSoftBodyAttachments() const { return mNbRigidSoftBodyAttachments; }
PX_FORCE_INLINE PxU32 getNbRigidSoftBodyFilters() const { return mNbRigidSoftBodyFilters; }
PX_FORCE_INLINE PxgDevicePointer<PxgFEMRigidAttachment> getRigidSoftBodyAttachments() { return mSoftBodyRigidAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxU32> getActiveRigidSoftBodyAttachments() { return mActiveSoftBodyRigidConstraints.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgFEMRigidAttachmentConstraint> getSoftBodyRigidConstraints() { return mSoftBodyRigidConstraints.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxU32> getGpuSoftBodyRigidCounter() { return mNumSoftBodyRigidAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxNodeIndex> getSoftBodyRigidAttachmentIds() { return mSoftBodyRigidAttachmentIds.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgRigidFilterPair> getRigidSoftBodyFilters() { return mSoftBodyRigidFilterPairs.getTypedDevicePtr(); }
PX_FORCE_INLINE PxU32 getNbSoftBodySoftBodyAttachments() const { return mNbSoftBodySoftBodyAttachments; }
PX_FORCE_INLINE PxgDevicePointer<PxgFEMFEMAttachment> getSoftBodySoftBodyAttachments() { return mSoftBodySoftBodyAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxU32> getActiveSoftBodySoftAttachments() { return mActiveSoftBodySoftBodyConstraints.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgFEMFEMAttachmentConstraint> getSoftBodySoftBodyConstraints() { return mSoftBodySoftBodyConstraints.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxU32> getGpuSoftBodySoftBodyCounter() { return mNumSoftBodySoftBodyAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxU32 getNbClothSoftBodyAttachments() const { return mNbClothSoftBodyAttachments; }
PX_FORCE_INLINE PxU32 getNbClothSoftBodyFilters() const { return mNbClothSoftBodyFilters; }
PX_FORCE_INLINE PxgDevicePointer<PxgFEMFEMAttachment> getClothSoftBodyAttachments() { return mSoftBodyClothAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxU32> getActiveClothSoftBodyAttachments() { return mActiveSoftBodyClothConstraints.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgFEMFEMAttachmentConstraint> getSoftBodyClothConstraints() { return mSoftBodyClothConstraints.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxU32> getGpuSoftBodyClothCounter() { return mNumSoftBodyClothAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgNonRigidFilterPair> getClothSoftBodyFilters() { return mSoftBodyClothFilterPairs.getTypedDevicePtr(); }
PX_FORCE_INLINE PxU32 getNbSoftBodyParticleAttachments() const { return mNbSoftBodyParticleAttachments; }
PX_FORCE_INLINE PxU32 getNbSoftBodyParticleFilters() const { return mNbSoftBodyParticleFilters; }
PX_FORCE_INLINE PxgDevicePointer<PxgFEMFEMAttachment> getSoftBodyParticleAttachments() { return mSoftBodyParticleAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxU32> getActiveSoftBodyParticleAttachments() { return mActiveSoftBodyParticleConstraints.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgFEMFEMAttachmentConstraint> getSoftBodyParticleConstraints() { return mSoftBodyParticleConstraints.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgNonRigidFilterPair> getSoftBodyParticleFilters() { return mSoftBodyParticleFilterPairs.getTypedDevicePtr(); }
PX_FORCE_INLINE PxU32 getNbActiveRigidClothAttachments() const { return mNbRigidClothAttachments; }
PX_FORCE_INLINE PxU32 getNbRigidClothFilters() const { return mNbRigidClothFilters; }
PX_FORCE_INLINE PxgDevicePointer<PxgFEMRigidAttachment> getRigidClothAttachments() { return mClothRigidAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxU32> getActiveRigidClothAttachments() { return mActiveClothRigidAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgFEMRigidAttachmentConstraint> getClothRigidConstraints() { return mClothRigidConstraints.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxU32> getGpuClothRigidCounter() { return mNumClothRigidAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxNodeIndex> getClothRigidAttachmentIds() { return mClothRigidAttachmentIds.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgRigidFilterPair> getRigidClothFilters() { return mClothRigidFilterPairs.getTypedDevicePtr(); }
PX_FORCE_INLINE PxU32 getNbActiveClothClothAttachments() const { return mNbClothClothAttachments; }
PX_FORCE_INLINE PxU32 getNbClothClothVertTriFilters() const { return mNbClothClothVertTriFilters; }
PX_FORCE_INLINE PxgDevicePointer<PxgFEMFEMAttachment> getClothClothAttachments() { return mClothClothAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxU32> getActiveClothClothAttachments() { return mActiveClothClothAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgFEMFEMAttachmentConstraint> getClothClothConstraints() { return mClothClothConstraints.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxU32> getGpuClothClothCounter() { return mNumClothClothAttachments.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgNonRigidFilterPair> getClothClothVertTriFilters() { return mClothClothVertTriFilterPairs.getTypedDevicePtr(); }
PX_FORCE_INLINE PxBitMapPinned& getActiveClothStateChangedMap() { return mActiveFEMClothStateChangedMap; }
PX_FORCE_INLINE PxReal* getActiveClothWakeCountsCPU() { return mFEMClothWakeCounts.begin(); }
PX_FORCE_INLINE PxgDevicePointer<PxReal> getActiveClothWakeCountsGPU() { return mFEMClothWakeCountsGPU.getTypedDevicePtr(); }
PX_FORCE_INLINE PxBitMapPinned& getActiveSBStateChangedMap() { return mActiveSBStateChangedMap; }
PX_FORCE_INLINE const PxReal* getActiveSBWakeCountsCPU() const { return mSBWakeCounts.begin(); }
PX_FORCE_INLINE const PxgDevicePointer<PxReal> getActiveSBWakeCountsGPU() const { return mSBWakeCountsGPU.getTypedDevicePtr(); }
PX_FORCE_INLINE PxReal* getActiveSBWakeCountsCPU() { return mSBWakeCounts.begin(); }
PX_FORCE_INLINE PxgDevicePointer<PxReal> getActiveSBWakeCountsGPU() { return mSBWakeCountsGPU.getTypedDevicePtr(); }
PX_FORCE_INLINE PxgDevicePointer<PxgSimulationCoreDesc> getSimulationCoreDesc() { return mUpdatedCacheAndBoundsDescBuffer.getTypedDevicePtr(); }
PxU32 getMaxArticulationLinks() const;
PxU32 getMaxArticulationDofs() const;
PxU32 getMaxArticulationMimicJoints() const;
PxU32 getMaxArticuationSpatialTendons() const;
PxU32 getMaxArticuationAttachments() const;
PxU32 getMaxArticuationFixedTendons() const;
PxU32 getMaxArticuationTendonJoints() const;
PxgGpuContext* mGpuContext;
PxgCudaKernelWranglerManager* mGpuKernelWranglerManager;
PxCudaContextManager* mCudaContextManager;
PxCudaContext* mCudaContext;
PxgHeapMemoryAllocatorManager* mHeapMemoryManager;
Bp::BoundsArray* mBoundArray;
bool mUseGpuBp;
private:
void constructDescriptor(CUdeviceptr boundsd, CUdeviceptr changedAABBMgrHandlesd, const PxU32 nbTotalShapes, const PxU32 bitMapWordCounts);
void createGpuStreamsAndEvents();
void releaseGpuStreamsAndEvents();
void syncData();
PxgSimulationCoreDesc* mUpdatedCacheAndBoundsDesc;
PxgNewBodiesDesc* mNewBodiesDesc;
PxgUpdateArticulationDesc* mUpdateArticulationDesc;
PxgUpdatedBodiesDesc* mUpdatedBodiesDesc;
PxgUpdatedJointsDesc* mUpdatedJointsDesc;
PxgUpdateActorDataDesc* mUpdatedActorDataDesc;
PxgTypedCudaBuffer<PxU32> mFrozenBuffer;
PxgTypedCudaBuffer<PxU32> mUnfrozenBuffer;
PxgTypedCudaBuffer<PxU32> mFrozenBlockAndResBuffer;
PxgTypedCudaBuffer<PxU32> mUnfrozenBlockAndResBuffer;
PxgTypedCudaBuffer<PxU32> mUpdatedBuffer;
PxgTypedCudaBuffer<PxU32> mActivateBuffer;
PxgTypedCudaBuffer<PxU32> mDeactivateBuffer;
PxgTypedCudaBuffer<PxU32> mUpdatedDirectBuffer;
// PT: new naming convention with "CudaBuffer" suffix and specific prefix for easier searching
PxgTypedCudaBuffer<PxgBodySim> mBodySimCudaBuffer; // PT: contains PxgBodySim structs.
PxgTypedCudaBuffer<PxgBodySimVelocities> mBodySimPreviousVelocitiesCudaBuffer; // PT: contains PxgBodySimVelocities structs. Only for direct GPU acceleration getters.
public:
PxgShapeSimManager mPxgShapeSimManager;
private:
PxgTypedCudaBuffer<PxgArticulation> mArticulationBuffer; //persistent buffer for articulation
PxgTypedCudaBuffer<PxgSolverBodySleepData> mArticulationSleepDataBuffer; //persistent buffer for sleepData
PxgTypedCudaBuffer<PxgArticulationBlockData> mArticulationBatchBuffer;
PxgTypedCudaBuffer<PxgArticulationBlockLinkData> mArticulationLinkBatchBuffer;
PxgTypedCudaBuffer<PxgArticulationTraversalStackData> mArticulationTraversalStackBuffer;
PxgTypedCudaBuffer<PxgArticulationBitFieldStackData> mTempPathToRootBitFieldStackBuffer;
PxgTypedCudaBuffer<PxgArticulationBitFieldStackData> mTempSharedBitFieldStackBuffer;
PxgTypedCudaBuffer<PxgArticulationBitFieldStackData> mTempRootBitFieldStackBuffer;
PxgTypedCudaBuffer<PxgArticulationBitFieldData> mPathToRootBitFieldStackBuffer;
PxgTypedCudaBuffer<PxgArticulationBlockDofData> mArticulationDofBatchBuffer;
PxgTypedCudaBuffer<PxgArticulationBlockMimicJointData> mArticulationMimicJointBatchBuffer;
PxgTypedCudaBuffer<PxgArticulationBlockSpatialTendonData> mArticulationSpatialTendonBatchBuffer;
PxgTypedCudaBuffer<PxgArticulationInternalTendonConstraintData> mArticulationSpatialTendonConstraintsBatchBuffer;
PxgTypedCudaBuffer<PxgArticulationBlockAttachmentData> mArticulationAttachmentBatchBuffer;
PxgTypedCudaBuffer<PxgArticulationBlockFixedTendonData> mArticulationFixedTendonBatchBuffer;
PxgTypedCudaBuffer<PxgArticulationInternalTendonConstraintData> mArticulationFixedTendonConstraintsBatchBuffer;
PxgTypedCudaBuffer<PxgArticulationBlockTendonJointData> mArticulationTendonJointBatchBuffer;
PxArray<PxgArticulationBuffer*> mArticulationDataBuffer;// persistent data, map with mArticulationBuffer
//PxU32 mMaxLinks;
//PxU32 mMaxDofs;
PxgTypedCudaBuffer<PxgSoftBody> mSoftBodyBuffer; //persistent buffer for soft bodies
PxgTypedCudaBuffer<PxU32> mActiveSoftBodyBuffer;
PxgTypedCudaBuffer<PxU32> mActiveSelfCollisionSoftBodyBuffer;
PxgTypedCudaBuffer<PxU32> mSoftBodyElementIndexBuffer;
PxgTypedCudaBuffer<PxgFEMCloth> mFEMClothBuffer; // persistent buffer for FEM-cloth
PxgTypedCudaBuffer<PxU32> mActiveFEMClothBuffer;
PxgTypedCudaBuffer<PxU32> mFEMClothElementIndexBuffer;
PxArray<PxgSoftBodyBuffer*> mSoftBodyDataBuffer; //persistent data, map with mSoftBodyBuffer
PxArray<PxgFEMClothBuffer*> mFEMClothDataBuffer; //persistent data, map with mFEMClothBuffer
PxBitMapPinned mActiveFEMClothStateChangedMap;
PxFloatArrayPinned mFEMClothWakeCounts;
PxgTypedCudaBuffer<PxReal> mFEMClothWakeCountsGPU;
PxBitMapPinned mActiveSBStateChangedMap;
PxFloatArrayPinned mSBWakeCounts;
PxgTypedCudaBuffer<PxReal> mSBWakeCountsGPU;
PxgTypedCudaBuffer<PxgD6JointData> mRigidJointBuffer;
PxgTypedCudaBuffer<PxgD6JointData> mArtiJointBuffer;
PxgTypedCudaBuffer<PxgConstraintPrePrep> mRigidJointPrePrepBuffer;
PxgTypedCudaBuffer<PxgConstraintPrePrep> mArtiJointPrePrepBuffer;
PxgTypedCudaBuffer<PxgConstraintIdMapEntry> mGpuConstraintIdMapDevice;
// See PxgJointManager::mGpuConstraintIdMapHost. This is just the device buffer counterpart.
PxgTypedCudaBuffer<PxgBodySimVelocityUpdate> mUpdatedBodySimBuffer;
PxgTypedCudaBuffer<PxgBodySim> mNewBodySimBuffer;
PxgTypedCudaBuffer<PxgArticulation> mNewArticulationBuffer;
PxgTypedCudaBuffer<PxgArticulationLink> mNewLinkBuffer;
PxgTypedCudaBuffer<PxReal> mNewLinkWakeCounterBuffer;
PxgTypedCudaBuffer<Cm::UnAlignedSpatialVector> mNewLinkExtAccelBuffer;
PxgTypedCudaBuffer<PxgArticulationLinkProp> mNewLinkPropBuffer;
PxgTypedCudaBuffer<PxU32> mNewLinkParentBuffer;
PxgTypedCudaBuffer<ArticulationBitField> mNewLinkChildBuffer;
PxgTypedCudaBuffer<PxTransform> mNewLinkBody2WorldsBuffer;
PxgTypedCudaBuffer<PxTransform> mNewLinkBody2ActorsBuffer;
PxgTypedCudaBuffer<Dy::ArticulationJointCore> mNewJointCoreBuffer;
PxgTypedCudaBuffer<Dy::ArticulationJointCoreData> mNewJointDataBuffer;
PxgTypedCudaBuffer<PxgArticulationSimUpdate> mNewLinkIndexBuffer;
PxgTypedCudaBuffer<PxGpuSpatialTendonData> mNewSpatialTendonParamsBuffer;
PxgTypedCudaBuffer<PxgArticulationTendon> mNewSpatialTendonsBuffer;
PxgTypedCudaBuffer<Dy::ArticulationMimicJointCore> mNewMimicJointBuffer;
PxgTypedCudaBuffer<PxU32> mNewPathToRootBuffer;
PxgTypedCudaBuffer<PxgArticulationTendonElementFixedData> mNewAttachmentFixedBuffer;
PxgTypedCudaBuffer<PxGpuTendonAttachmentData> mNewAttachmentModBuffer;
PxgTypedCudaBuffer<PxU32> mNewTendonAttachmentRemapBuffer;
PxgTypedCudaBuffer<PxGpuFixedTendonData> mNewFixedTendonParamsBuffer;
PxgTypedCudaBuffer<PxgArticulationTendon> mNewFixedTendonsBuffer;
PxgTypedCudaBuffer<PxgArticulationTendonElementFixedData> mNewTendonJointsFixedBuffer;
PxgTypedCudaBuffer<PxGpuTendonJointCoefficientData> mNewTendonJointsCoefficientBuffer;
PxgTypedCudaBuffer<PxU32> mNewTendonTendonJointRemapBuffer;
PxgTypedCudaBuffer<PxU32> mActiveNodeIndices; //this is index mapping between solver body data index and the node index
PxgTypedCudaBuffer<PxgSimulationCoreDesc> mUpdatedCacheAndBoundsDescBuffer;
PxgTypedCudaBuffer<PxgNewBodiesDesc> mBodiesDescBuffer;
PxgTypedCudaBuffer<PxgUpdateArticulationDesc> mArticulationDescBuffer;
PxgTypedCudaBuffer<PxgUpdatedBodiesDesc> mUpdatedBodiesDescBuffer;
PxgTypedCudaBuffer<PxgUpdatedJointsDesc> mUpdatedJointDescBuffer;
PxgTypedCudaBuffer<PxgUpdateActorDataDesc> mUpdatedActorDescBuffer;
PxgTypedCudaBuffer<PxBounds3> mBoundsBuffer; //Bp in CPU so we can't use the BoundsBuffer in the GPU BP
PxgTypedCudaBuffer<PxU32> mChangedAABBMgrHandlesBuffer; //Bp in CPU so we can't use the changedAABBMgrHandlesBuffer in the GPU AABBManager
PxgTypedCudaBuffer<PxgFEMRigidAttachment> mSoftBodyRigidAttachments;
PxgTypedCudaBuffer<PxgRigidFilterPair> mSoftBodyRigidFilterPairs;
PxgTypedCudaBuffer<PxgFEMRigidAttachmentConstraint> mSoftBodyRigidConstraints;
PxgTypedCudaBuffer<PxU32> mActiveSoftBodyRigidConstraints;
PxgTypedCudaBuffer<PxU32> mNumSoftBodyRigidAttachments;
PxgTypedCudaBuffer<PxNodeIndex> mSoftBodyRigidAttachmentIds;
PxgTypedCudaBuffer<PxgFEMFEMAttachment> mSoftBodySoftBodyAttachments;
PxgTypedCudaBuffer<PxgFEMFEMAttachmentConstraint> mSoftBodySoftBodyConstraints;
PxgTypedCudaBuffer<PxU32> mActiveSoftBodySoftBodyConstraints;
PxgTypedCudaBuffer<PxU32> mNumSoftBodySoftBodyAttachments;
PxgTypedCudaBuffer<PxgFEMFEMAttachment> mSoftBodyClothAttachments;
PxgTypedCudaBuffer<PxgNonRigidFilterPair> mSoftBodyClothFilterPairs;
PxgTypedCudaBuffer<PxgFEMFEMAttachmentConstraint> mSoftBodyClothConstraints;
PxgTypedCudaBuffer<PxU32> mActiveSoftBodyClothConstraints;
PxgTypedCudaBuffer<PxU32> mNumSoftBodyClothAttachments;
PxgTypedCudaBuffer<PxgFEMFEMAttachment> mSoftBodyParticleAttachments;
PxgTypedCudaBuffer<PxgNonRigidFilterPair> mSoftBodyParticleFilterPairs;
PxgTypedCudaBuffer<PxgFEMFEMAttachmentConstraint> mSoftBodyParticleConstraints;
PxgTypedCudaBuffer<PxU32> mActiveSoftBodyParticleConstraints;
PxgTypedCudaBuffer<PxgFEMRigidAttachment> mClothRigidAttachments;
PxgTypedCudaBuffer<PxU32> mActiveClothRigidAttachments;
PxgTypedCudaBuffer<PxgRigidFilterPair> mClothRigidFilterPairs;
PxgTypedCudaBuffer<PxgFEMRigidAttachmentConstraint> mClothRigidConstraints;
PxgTypedCudaBuffer<PxU32> mNumClothRigidAttachments;
PxgTypedCudaBuffer<PxNodeIndex> mClothRigidAttachmentIds;
PxgTypedCudaBuffer<PxgFEMFEMAttachment> mClothClothAttachments;
PxgTypedCudaBuffer<PxU32> mActiveClothClothAttachments;
PxgTypedCudaBuffer<PxgNonRigidFilterPair> mClothClothVertTriFilterPairs;
PxgTypedCudaBuffer<PxgFEMFEMAttachmentConstraint> mClothClothConstraints;
PxgTypedCudaBuffer<PxU32> mNumClothClothAttachments;
PxU32* mPinnedEvent;
PxU32 mNbRigidSoftBodyAttachments;
PxU32 mNbRigidSoftBodyFilters;
PxU32 mNbSoftBodySoftBodyAttachments;
PxU32 mNbClothSoftBodyAttachments;
PxU32 mNbClothSoftBodyFilters;
PxU32 mNbSoftBodyParticleAttachments;
PxU32 mNbSoftBodyParticleFilters;
PxU32 mNbRigidClothAttachments;
PxU32 mNbRigidClothFilters;
PxU32 mNbClothClothAttachments;
PxU32 mNbClothClothVertTriFilters;
PxU32 mNbTotalBodySim;
PxU32 mNbTotalArticulations; //this is used for articulation
PxU32 mNbTotalSoftBodies;
PxU32 mNbTotalFEMCloths;
PxU32 mMaxTetraVerts; //max number of verts for all the tetrahedron mesh
PxU32 mMaxTetrahedrons;
PxU32 mGMMaxPartitions;
PxU32 mGMMaxTetraVerts;
PxU32 mGMMaxTetrahedrons;
PxU32 mGMMaxTetrahedronsPerPartition;
PxU32 mGMMaxJacobiTetrahedrons;
PxU32 mGMMaxJacobiVertices;
PxU32 mMaxNbClothVerts;
PxU32 mMaxNbClothTriangles;
PxU32 mMaxNbClothTrianglesWithActiveEdges;
PxU32 mMaxNbNonSharedTriangles;
PxU32 mMaxNbNonSharedTriPartitions;
PxU32 mMaxNbNonSharedTrianglesPerPartition;
PxU32 mMaxNbSharedTrianglePairs;
PxU32 mMaxNbNonSharedTrianglePairs;
PxU32 mMaxNbSharedTriPairPartitions;
PxU32 mMaxNbNonSharedTriPairPartitions;
PxU32 mMaxNonSharedTriClusterId;
PxU32 mMaxSharedTriPairClusterId;
PxU32 mMaxNonSharedTriPairClusterId;
PxU32 mMaxNbSharedTrianglePairsPerPartition;
PxU32 mMaxNbNonSharedTrianglePairsPerPartition;
PxU32 mMaxNbCollisionPairUpdatesPerTimestep;
PxU32 mMaxNbCollisionSubsteps;
//PxU32 mMaxParticles;
PxU32 mNbTotalRigidJoints;
PxU32 mNbTotalArtiJoints;
bool mUsePartitionAveraging;
bool mHasActiveBendingPairs;
CUstream mStream;
CUevent mEvent;
CUevent mDmaEvent;
PxVec3 mGravity;
PxArray<PxgSoftBody> mSoftBodiesToFree;
PxArray<PxgFEMCloth> mClothsToFree;
#if PX_SUPPORT_OMNI_PVD
PxU64 getRigidBodyDataTypeElementSize(PxRigidDynamicGPUAPIWriteType::Enum dataType);
void ovdRigidBodyCallback(const void* PX_RESTRICT data, const PxRigidDynamicGPUIndex* PX_RESTRICT gpuIndices, PxRigidDynamicGPUAPIWriteType::Enum dataType, PxU32 nbElements);
PxPinnedArray<PxU8> mOvdDataBuffer;
PxPinnedArray<PxU8> mOvdIndexBuffer;
#endif
};
}
#endif

View File

@@ -0,0 +1,395 @@
// 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.
#ifndef PXG_SIMULATION_CORE_DESC_H
#define PXG_SIMULATION_CORE_DESC_H
#include "foundation/PxSimpleTypes.h"
#include "DyVArticulation.h"
#include "PxDeformableSurface.h"
#include "PxDeformableVolume.h"
#include <vector_types.h>
#define PXG_CHECK_BITSHIFT_32(lowmask, highmask, bitshift) \
((1 << bitshift) - 1 == lowmask) && (0xffffffff >> bitshift == highmask)
#define PXG_BITSHIFT_TET_ID 20
#define PXG_BITSHIFT_ELEMENT_ID 20
PX_COMPILE_TIME_ASSERT(PX_MAX_NB_DEFORMABLE_SURFACE_TRI == PX_MAX_NB_DEFORMABLE_SURFACE_VTX);
PX_COMPILE_TIME_ASSERT(PXG_CHECK_BITSHIFT_32(PX_MAX_NB_DEFORMABLE_SURFACE_TRI, PX_MAX_NB_DEFORMABLE_SURFACE, PXG_BITSHIFT_ELEMENT_ID));
PX_COMPILE_TIME_ASSERT(PXG_CHECK_BITSHIFT_32(PX_MAX_NB_DEFORMABLE_VOLUME_TET, PX_MAX_NB_DEFORMABLE_VOLUME, PXG_BITSHIFT_TET_ID));
namespace physx
{
struct PxgSolverBodySleepData;
struct PxgShape;
struct PxgBodySim;
struct PxgShapeSim;
struct PxgArticulationLink;
struct PxgArticulationLinkProp;
struct PxsCachedTransform;
struct PxgBodySimVelocityUpdate;
struct PxgD6JointData;
struct PxgConstraintPrePrep;
class PxgArticulation;
class PxNodeIndex;
class PxgArticulationTendon;
class PxGpuSpatialTendonData;
class PxGpuFixedTendonData;
class PxGpuTendonAttachmentData;
class PxgArticulationTendonElementFixedData;
class PxGpuTendonJointCoefficientData;
namespace Dy
{
struct ArticulationJointCore;
class ArticulationJointCoreData;
}
struct PxgNewBodiesDesc
{
const PxgBodySim* mNewBodySim;
PxgBodySim* mBodySimBufferDeviceData;
PxU32 mNbNewBodies; //number of newly added bodies
};
struct PX_ALIGN_PREFIX(16) PxgArticulationSimUpdate
{
PxU32 dirtyFlags; //What data is updated (ArticulationDirtyFlag)
PxU32 articulationIndex; //which articulation on the GPU
PxU32 linkStartIndex; //Where the link/joint data starts in memory
PxU32 dofDataStartIndex; //Where the dof data starts in memory, e.g. jointVelocity, jointPosition, jointForce etc.
PxU32 spatialTendonStartIndex; //Where the spatial tendon starts in memory
PxU32 spatialTendonAttachmentStartIndex; //Where the spatial tendon attachment starts in memory
PxU32 fixedTendonStartIndex; //Where the fixed tendon starts in memory
PxU32 fixedTendonJointStartIndex; //Where the fixed tendon joint starts in memory
PxU32 mimicJointStartIndex;
PxU32 pathToRootIndex; //Where the pathToRoot array starts in memory
PxU8 userFlags; //(PxArticulationFlag)
PxU8 pad[7];
}PX_ALIGN_SUFFIX(16);
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 PxEncodeClothIndex(const PxU32 clothId, const PxU32 elementId)
{
// elementId can be PX_MAX_NB_DEFORMABLE_SURFACE_TRI/PX_MAX_NB_DEFORMABLE_SURFACE_VTX to get at mask for "any tri or vtx"
PX_ASSERT(clothId < PX_MAX_NB_DEFORMABLE_SURFACE);
PX_ASSERT(elementId <= PX_MAX_NB_DEFORMABLE_SURFACE_TRI);
PX_ASSERT(elementId <= PX_MAX_NB_DEFORMABLE_SURFACE_VTX);
return (clothId << PXG_BITSHIFT_ELEMENT_ID) | elementId;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 PxEncodeSoftBodyIndex(const PxU32 softBodyId, const PxU32 tetId)
{
// tetId can be PX_MAX_NB_DEFORMABLE_VOLUME_TET to get at mask for "any tet"
PX_ASSERT(softBodyId < PX_MAX_NB_DEFORMABLE_VOLUME);
PX_ASSERT(tetId <= PX_MAX_NB_DEFORMABLE_VOLUME_TET);
return (softBodyId << PXG_BITSHIFT_TET_ID) | tetId;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU64 PxEncodeParticleIndex(const PxU32 particleSystemId, const PxU32 particleId)
{
PX_ASSERT(particleSystemId < 0xffffffff);
PX_ASSERT(particleId < 0xffffffff);
return (PxU64(particleSystemId) << 32ull) | particleId;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 PxGetSoftBodyElementIndex(const PxU32 compressedId)
{
return PX_MAX_NB_DEFORMABLE_VOLUME_TET & compressedId;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 PxGetSoftBodyId(const PxU32 compressedId)
{
return compressedId >> PXG_BITSHIFT_TET_ID;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 PxGetClothElementIndex(const PxU32 compressedId)
{
return PX_MAX_NB_DEFORMABLE_SURFACE_TRI & compressedId;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 PxGetClothId(const PxU32 compressedId)
{
return compressedId >> PXG_BITSHIFT_ELEMENT_ID;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE bool PxGetIsVertexType(const float4& baryOrType)
{
return (baryOrType.x == 0.0f && baryOrType.y == 0.0f && baryOrType.z == 0.0f && baryOrType.w == 0.0f);
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 PxGetParticleIndex(const PxU64 compressedId)
{
return (0xffffffff) & compressedId;
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 PxGetParticleSystemId(const PxU64 compressedId)
{
return compressedId >> 32;
}
PX_ALIGN_PREFIX(16)
class PxgRigidFilterPair
{
public:
PX_CUDA_CALLABLE PxgRigidFilterPair() : index2(0)
{}
PxU64 index0; //rigid body index will always in index0
PxU64 index1;
PxU32 index2;
PxU32 pading[3];
PX_CUDA_CALLABLE PxI32 compare(const PxgRigidFilterPair& other) const
{
if (index0 < other.index0)
return -1;
if (index0 > other.index0)
return 1;
if (index1 < other.index1)
return -1;
if (index1 > other.index1)
return 1;
if (index2 < other.index2)
return -1;
if (index2 > other.index2)
return 1;
return 0;
}
}PX_ALIGN_SUFFIX(16);
struct PxgConeLimitParams
{
union
{
float4 low_high_limits;
float4 low_high_angle;
};
union
{
float4 axis_angle;
float4 barycentric;
};
};
//KS - consider splitting into 2x structures - 16 bytes and 8 bytes!
//soft body/cloth with rigid
class PxgFEMRigidAttachment : public PxgRigidFilterPair
{
public:
union
{
float4 localPose0;
float4 baryOrType0;
};
PxgConeLimitParams coneLimitParams;
float4 baryOrType1;
};
PX_ALIGN_PREFIX(16)
struct PxgParticleRigidConstraint
{
float4 raXn0_biasW[32];
float4 raXn1_biasW[32];
float4 raXn2_biasW[32];
float4 velMultiplierXYZ_invMassW[32];
float4 low_high_limits[32];
float4 axis_angle[32];
PxU64 particleId[32];
PxU64 rigidId[32];
}PX_ALIGN_SUFFIX(16);
PX_ALIGN_PREFIX(16)
class PxgNonRigidFilterPair
{
public:
PX_CUDA_CALLABLE PxgNonRigidFilterPair() : index2(0) // : referenceCount(0)
{}
PxU64 index0;
PxU32 index1;
PxU32 index2;
PX_CUDA_CALLABLE PxI32 compare(const PxgNonRigidFilterPair& other) const
{
if (index0 < other.index0)
return -1;
if (index0 > other.index0)
return 1;
if (index1 < other.index1)
return -1;
if (index1 > other.index1)
return 1;
if (index2 < other.index2)
return -1;
if (index2 > other.index2)
return 1;
return 0;
}
}PX_ALIGN_SUFFIX(16);
PX_ALIGN_PREFIX(16)
class PxgFEMFEMAttachment
{
public:
PxgConeLimitParams coneLimitParams;
float4 barycentricCoordinates0;
float4 barycentricCoordinates1;
PxU64 index0;
PxU32 index1;
PxReal constraintOffset;
}PX_ALIGN_SUFFIX(16);
PX_COMPILE_TIME_ASSERT(sizeof(PxgFEMFEMAttachment) % 16 == 0);
struct PxgUpdateArticulationDesc
{
PxgArticulation* mNewArticulations;
PxReal* mNewLinkWakeCounters;
PxgArticulationLink* mNewLinks;
PxgArticulationLinkProp* mNewLinkProps;
PxU32* mNewLinkParents;
Dy::ArticulationBitField* mNewLinkChildren;
PxTransform* mNewLinkBody2Worlds;
PxTransform* mNewLinkBody2Actors;
Cm::UnAlignedSpatialVector* mNewLinkExtAccels;
Dy::ArticulationJointCore* mNewJointCores;
Dy::ArticulationJointCoreData* mNewJointData;
PxgArticulationSimUpdate* mIndicesOffset;
PxgArticulation* mArticulationPool;
PxgSolverBodySleepData* mArticulationSleepDataPool;
PxGpuSpatialTendonData* mNewSpatialTendonParamsPool;
PxgArticulationTendon* mNewSpatialTendonPool;
PxgArticulationTendonElementFixedData* mNewAttachmentFixedPool;
PxGpuTendonAttachmentData* mNewAttachmentModPool;
PxU32* mNewTendonAttachmentRemapPool;
PxGpuFixedTendonData* mNewFixedTendonParamsPool;
PxgArticulationTendon* mNewFixedTendonPool;
PxgArticulationTendonElementFixedData* mNewTendonJointFixedPool;
PxGpuTendonJointCoefficientData* mNewTendonJointCoefficientPool;
PxU32* mNewTendonTendonJointRemapPool;
Dy::ArticulationMimicJointCore* mNewArticulationMimicJointPool;
PxU32* mNewPathToRootPool;
PxU32 mNbNewArticulations; //number of newly added aritculations
};
struct PxgUpdatedBodiesDesc
{
PxgBodySim* mBodySimBufferDeviceData;
PxgBodySimVelocityUpdate* mUpdatedBodySim;
PxU32 mNbUpdatedBodies;
};
struct PxgUpdatedJointsDesc
{
const PxgD6JointData* mD6RigidJointCPUPool; //map memory
PxgD6JointData* mD6RigidJointGPUPool; //device memory
const PxgConstraintPrePrep* mD6RigidJointPrePrepCPUPool; //map memory
PxgConstraintPrePrep* mD6RigidJointPrePrepGPUPool; //device memory
const PxgD6JointData* mD6ArtiJointCPUPool; //map memory
PxgD6JointData* mD6ArtiJointGPUPool; //device memory
const PxgConstraintPrePrep* mD6ArtiJointPrePrepCPUPool; //map memory
PxgConstraintPrePrep* mD6ArtiJointPrePrepGPUPool; //device memory
const PxU32* mUpdatedRigidJointIndices; //map memory
PxU32 mNbUpdatedRigidJoints;
const PxU32* mUpdatedArtiJointIndices; //map memory
PxU32 mNbUpdatedArtiJoints;
};
struct PxgSimulationCoreDesc
{
PxU32* mChangedAABBMgrHandles;
PxU32* mFrozen;
PxU32* mUnfrozen;
PxU32* mFrozenBlockAndRes;//this array is used to store frozen block value for the scan and also store the final frozen shape index
PxU32* mUnfrozenBlockAndRes;//this array is used to store unfrozen block value for the scane and also store the final unfrozen shape index
PxU32* mUpdated;
PxU32* mActivate;
PxU32* mDeactivate;
PxgBodySim* mBodySimBufferDeviceData;
const PxgShapeSim* mShapeSimsBufferDeviceData;
PxgArticulation* mArticulationPool;
PxgSolverBodySleepData* mArticulationSleepDataPool;
PxsCachedTransform* mTransformCache;
PxBounds3* mBounds;
PxU32* mBodyDataIndices;
PxgSolverBodySleepData* mSleepData;
PxgShape* mShapes;
PxU32 mNbTotalShapes; //number of total shapes;
PxU32 mBitMapWordCounts; //number of words in gChangedAABBMgrHandles, this will include shapes and aggregates
PxU32 mTotalFrozenShapes; // AD: these two members are the only reason we copy the whole descriptor back to cpu.
PxU32 mTotalUnfrozenShapes;
};
struct PxgUpdateActorDataDesc
{
PxgBodySim* mBodySimBufferDeviceData;
PxgShape* mShapes;
PxsCachedTransform* mTransformCache;
PxBounds3* mBounds;
PxNodeIndex* mRigidNodeIndices;
PxU32* mShapeIndices;
PxU32* mUpdated; //Direct API changed handle
PxU32* mChangedAABBMgrHandles; //CPU API changed handle
PxU32 mBitMapWordCounts;
const PxgShapeSim* mShapeSimsBufferDeviceData;
};
}
#endif

View File

@@ -0,0 +1,86 @@
// 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_SIMULATION_CORE_KERNEL_INDICES_H
#define PXG_SIMULATION_CORE_KERNEL_INDICES_H
namespace physx
{
struct PxgSimulationCoreKernelBlockDim
{
enum
{
UPDATE_BODY_EXTERNAL_VELOCITIES = 256,
UPDATE_BODIES_AND_SHAPES = 256,
UPDATE_LINKS_AND_JOINTCORES = 256,
UPDATE_JOINTS = 256,
UPDATE_TRANSFORMCACHE_AND_BOUNDARRAY = 256,
MERGE_TRANSFORMCACHE_AND_BOUNDARRAY_CHANGES = 256,
UPDATE_AABBMGR_HANDLES = 256,
COMPUTE_FROZEN_UNFROZEN_HISTOGRAM = 256,
OUTPUT_FROZEN_UNFROZEN_HISTOGRAM = 256,
CREATE_FROZEN_UNFROZEN_ARRAY = 256,
NEW_ARTICULATION = 256,
RIGID_DYNAMIC_GET_GLOBAL_POSE = 256,
RIGID_DYNAMIC_GET_LINVEL = 256,
RIGID_DYNAMIC_GET_ANGVEL = 256,
RIGID_DYNAMIC_GET_LINACCEL = 256,
RIGID_DYNAMIC_GET_ANGACCEL = 256,
RIGID_DYNAMIC_SET_GLOBAL_POSE = 256,
RIGID_DYNAMIC_SET_LINVEL = 256,
RIGID_DYNAMIC_SET_ANGVEL = 256,
RIGID_DYNAMIC_SET_FORCE = 256,
RIGID_DYNAMIC_SET_TORQUE = 256,
D6_JOINT_GET_FORCE = 256,
D6_JOINT_GET_TORQUE = 256
};
};
struct PxgSimulationCoreKernelGridDim
{
enum
{
UPDATE_BODY_EXTERNAL_VELOCITIES = 64,
UPDATE_BODIES_AND_SHAPES = 64,
NEW_ARTICULATION = 64,
UPDATE_SOFTBODIES = 64,
UPDATE_PARTICLESYSTEMS = 64,
UPDATE_LINKS_AND_JOINTCORES = 64,
UPDATE_JOINTS = 64,
UPDATE_TRANSFORMCACHE_AND_BOUNDARRAY = 256,
UPDATE_AABBMGR_HANDLES = 64,
COMPUTE_FROZEN_UNFROZEN_HISTOGRAM = 32, //this has to be 32 because we are doing warp scan
OUTPUT_FROZEN_UNFROZEN_HISTOGRAM = 32, //this has to be 32
CREATE_FROZEN_UNFROZEN_ARRAY = 64
};
};
}
#endif

View File

@@ -0,0 +1,128 @@
// 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_SMOOTHING_H
#define PXG_SMOOTHING_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec4.h"
#include "foundation/PxArray.h"
#include "PxSmoothing.h"
#include "PxgKernelWrangler.h"
#include "PxgAnisotropyData.h"
#include "PxgKernelLauncher.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
#if PX_SUPPORT_GPU_PHYSX
class PxgSmoothedPositionGenerator : public PxSmoothedPositionGenerator, public PxUserAllocated
{
private:
PxgKernelLauncher mKernelLauncher;
PxSmoothedPositionData mPositionSmoothingDataHost;
PxSmoothedPositionData* mPositionSmoothingDataPerParticleSystemDevice;
PxU32 mNumParticles;
bool mDirty;
bool mOwnsSmoothedPositionGPUBuffers;
PxVec4* mSmoothedPositions;
bool mEnabled;
void releaseGPUSmoothedPositionBuffers();
void allocateGPUSmoothedPositionBuffers();
public:
PxgSmoothedPositionGenerator(PxgKernelLauncher& cudaContextManager, PxU32 maxNumParticles, PxReal smoothingStrenght);
virtual ~PxgSmoothedPositionGenerator() { }
virtual void setSmoothing(float smoothingStrenght)
{
mPositionSmoothingDataHost.mSmoothing = smoothingStrenght;
mDirty = true;
}
virtual void release();
//Replaces the former readData method
virtual void setResultBufferHost(PxVec4* smoothedPositions)
{
mSmoothedPositions = smoothedPositions;
allocateGPUSmoothedPositionBuffers();
mDirty = true;
}
virtual void setResultBufferDevice(PxVec4* smoothedPositions)
{
if (mOwnsSmoothedPositionGPUBuffers)
releaseGPUSmoothedPositionBuffers();
mPositionSmoothingDataHost.mPositions = smoothedPositions;
mDirty = true;
mSmoothedPositions = NULL;
}
virtual void generateSmoothedPositions(PxGpuParticleSystem* gpuParticleSystem, PxU32 numParticles, CUstream stream);
virtual void generateSmoothedPositions(PxVec4* particlePositionsGpu, PxParticleNeighborhoodProvider& neighborhoodProvider, PxU32 numParticles, PxReal particleContactOffset, CUstream stream);
virtual PxU32 getMaxParticles() const
{
return mNumParticles;
}
virtual void setMaxParticles(PxU32 maxParticles);
virtual PxVec4* getSmoothedPositionsDevicePointer() const
{
return mPositionSmoothingDataHost.mPositions;
}
virtual void setEnabled(bool enabled)
{
mEnabled = enabled;
}
virtual bool isEnabled() const
{
return mEnabled;
}
};
#endif
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,243 @@
// 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_SOFTBODY_H
#define PXG_SOFTBODY_H
#include "PxsHeapMemoryAllocator.h"
#include "foundation/PxUserAllocated.h"
#include "foundation/PxVec4.h"
#include "PxgCudaBuffer.h"
#include "cutil_math.h"
#include "PxDeformableVolume.h"
#include "PxDeformableVolumeFlag.h"
#include "PxSoftBodyFlag.h" // deprecated
#include "PxgSimulationCoreDesc.h"
#define MAX_SELF_COLLISION_CONTACTS 1000
#define NUM_BLOCK_PER_SOFTBODY_SOLVE_TETRA 2
#define SB_PARTITION_LIMIT 8 // max # partitions allowed. This value SHOULD NOT change. See also GuCookingTetrahedronMesh.cpp.
namespace physx
{
namespace Gu
{
class DeformableVolumeMesh;
class BVTetrahedronMesh;
class TetrahedronMesh;
class DeformableVolumeAuxData;
};
struct PxgMat33Block;
struct PxgSpatialVectorBlock;
class PxgNonRigidFilterPair;
#if PX_VC
#pragma warning(push)
#pragma warning( disable : 4324 ) // Padding was added at the end of a structure because of a __declspec(align) value.
#endif
struct PxgSoftBodyData
{
public:
PxU32 mRemapOutputSizeGM;
PxU32 mMaxTetsPerPartitionsGM;
PxU32 mTetsRemapSize; //size of tetrahedrons remap from collision mesh to simulation mesh
PxU32 mNbPackedNodes;
};
PX_ALIGN_PREFIX(16)
class PxgSoftBody
{
public:
PX_DEPRECATED static PxU32 dataIndexFromFlagDEPRECATED(PxSoftBodyGpuDataFlag::Enum flag);
// AD: We only use this for the host mirror as the GPU-side are PxgCudaBuffers and we only assign the pointers.
// Make sure to pass the right allocator in here!
void deallocate(PxsHeapMemoryAllocator* allocator);
void* mTetMeshData;
PxU8* mTetMeshSurfaceHint;
uint4* mTetIndices;
PxU32* mTetIndicesRemapTable; //remap the tet indices to the source indices
PxMat33* mTetraStresses;
PxMat33* mTetraRestPoses;
PxReal* mTetraStressCoefficient;
float4* mTetraRotations; //sizeof mNumTets
float4* mPosition_InvMass;
float4* mRestPosition; //rest position of the verts - 4th component unused.
uint4* mSimTetIndices;
float4* mSimVelocity_InvMass;
float4* mSimPosition_InvMass;
const float4* mSimKinematicTarget;
bool* mVertsAreDeformed;
bool* mVertsCanNotDeform;
float4* mSimDeltaPos; //sizeof mNumVertsGM, store the deltaPos change for the grid model verts
PxgMat33Block* mSimTetraRestPoses;
PxgMat33Block* mOrigQinv;
PxU32* mSimOrderedTetrahedrons;
PxU32* mSimJacobiVertIndices;
float4* mSimTetraRotations; //sizeof mNumTetsGM
float4* mSimVelocity_invMassCP;//sizeof mRemapOutputSizeGM
float4* mSimPosition_InvMassCP; //sizeof mRemapOutputSizeGM
uint4* mSimRemapOutputCP; //sizeof numElements * numVertsPerElement
PxU32* mSimAccumulatedCopiesCP; //sizeof mNumVertsGM
PxU32* mSimAccumulatedPartitionsCP; //sizeof mMaxPartitionsGM
float4* mVertsBarycentricInGridModel; //the barycentric of verts(from collision mesh) in simulation mesh
PxU32* mVertsRemapInGridModel;// the verts in collision mesh map to the tetrahedrons in simulation mesh
PxU32* mTetsRemapColToSim; //tetrahedrons remap from collision mesh to simulation mesh
PxU32* mTetsAccumulatedRemapColToSim; // runsum of mTetsRemapColToSim sizeof mNumTets
PxU8* mSurfaceVertsHint;
PxU32* mSurfaceVertToTetRemap;
PxgSpatialVectorBlock* mSimTetraMultipliers;
float4* mSimDelta; //initialize to zero and zero every time in the apply delta kernel
PxBounds3* mPackedNodeBounds;
PxU16* mOrderedMaterialIndices; //indices to global material array ordered by partition, size of mNumVertsGM(simulation mesh)
PxU16* mMaterialIndices; //indices to global material array, size of mNumVertsGM(simulation mesh)
//filter pair for myself and other soft body. Index0 is myself and vertId. Index1 is other soft body and tetId
PxgNonRigidFilterPair* mFilteringPairs;
PxU32 mNumFilterPairs;
PxReal mLinearDamping;
PxReal mMaxLinearVelocity;
PxReal mPenBiasClamp;
PxReal mSettlingThreshold;
PxReal mSleepThreshold;
PxReal mSettlingDamping;
PxReal mSelfCollisionFilterDistance;
PxReal mSelfCollisionStressTolerance;
PxQuat mInitialRotation;
PxU32 mNumVerts;
PxU32 mNumTets;
PxU32 mNumVertsGM;
PxU32 mNumTetsGM;
PxU32 mNumPartitionsGM;
PxU32 mElementIndex;
PxU32 mGpuRemapIndex;
PxU8 mActorFlags;
PxU8 mBodyFlags;
PxU16 mVolumeFlags;
uint4* mSimPullIndices;
PxU32 mAwake;
PxU32 mNumTetsPerElement;
PxU32 mNumJacobiVertices;
PxReal mRestDistance;
PxReal mOriginalContactOffset;
PxReal mJacobiScale;
}PX_ALIGN_SUFFIX(16);
#if PX_VC
#pragma warning(pop)
#endif
class PxgSoftBodyBuffer : public PxUserAllocated
{
public:
PxgSoftBodyBuffer(PxgHeapMemoryAllocatorManager* heapMemoryManager);
PxgCudaBuffer tetMeshData;
PxgTypedCudaBuffer<PxU8> tetMeshSurfaceHint;
PxgTypedCudaBuffer<uint4> tetIndices;
PxgTypedCudaBuffer<PxU32> tetIndicesRemapTable;
PxgTypedCudaBuffer<PxMat33> tetStresses;
PxgTypedCudaBuffer<PxReal> tetStressCoefficient;
PxgTypedCudaBuffer<PxMat33> tetRestPoses;
PxgTypedCudaBuffer<float4> tetRotations;
PxgTypedCudaBuffer<uint4> tetIndicesGM;
PxgTypedCudaBuffer<float4> pPostion_InvMassGM;
PxgTypedCudaBuffer<bool> vertsAreDeformed;
PxgTypedCudaBuffer<bool> vertsCantDeform;
PxgTypedCudaBuffer<PxgMat33Block> tetRestPosesGM;
PxgTypedCudaBuffer<PxgMat33Block> origTetRestPosesGM;
PxgTypedCudaBuffer<float4> tetRotationsGM;
PxgTypedCudaBuffer<PxU32> orderedTetGM;
PxgTypedCudaBuffer<PxU32> jacobiVertIndicesGM;
PxgTypedCudaBuffer<PxgSpatialVectorBlock> tetMultipliersGM;
PxgTypedCudaBuffer<float4> pDeltaVGM;
PxgTypedCudaBuffer<float4> pBarycentricGM;
PxgTypedCudaBuffer<PxU32> pRemapGM;
PxgTypedCudaBuffer<PxU32> tetRemapColToSim;
PxgTypedCudaBuffer<PxU32> tetAccumulatedRemapColToSim;
PxgTypedCudaBuffer<PxU8> surfaceVertsHint;
PxgTypedCudaBuffer<PxU32> surfaceVertToTetRemap;
PxgTypedCudaBuffer<float4> pDeltaPosGM;
PxgTypedCudaBuffer<float4> pPosition_InvMassGMCP;
PxgTypedCudaBuffer<float4> pVelocity_InvMassGMCP;
PxgTypedCudaBuffer<PxU32> remapOutputGMCP;
PxgTypedCudaBuffer<PxU32> accumulatedPartitionsGMCP;
PxgTypedCudaBuffer<PxU32> accumulatedCopiesGMCP;
PxgTypedCudaBuffer<uint4> pullIndices;
PxgTypedCudaBuffer<PxU16> orderedMaterialIndices;
PxgTypedCudaBuffer<PxU16> materialIndices;
PxgTypedCudaBuffer<PxBounds3> packedNodeBounds; //for refit
PxgTypedCudaBuffer<PxgNonRigidFilterPair> filterPairs;
};
class PxgSoftBodyUtil
{
public:
static PxU32 computeTetMeshByteSize(const Gu::BVTetrahedronMesh* tetMesh);
static PxU32 loadOutTetMesh(void* mem, const Gu::BVTetrahedronMesh* tetMesh);
static void initialTetData(PxgSoftBody& softbody, const Gu::BVTetrahedronMesh* colTetMesh, const Gu::TetrahedronMesh* simTetMesh,
const Gu::DeformableVolumeAuxData* softBodyAuxData, const PxU16* materialsHandles, PxsHeapMemoryAllocator* alloc);
static void computeBasisMatrix(PxMat33* restPoses, const Gu::DeformableVolumeMesh* tetMesh);
};
}
#endif

View File

@@ -0,0 +1,297 @@
// 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_SOFTBODY_CORE_H
#define PXG_SOFTBODY_CORE_H
#include "PxgFEMCore.h"
#include "PxSoftBodyFlag.h"
#include "foundation/PxPreprocessor.h"
namespace physx
{
//this is needed to force PhysXSimulationControllerGpu linkage as Static Library!
void createPxgSoftBody();
struct PxGpuDynamicsMemoryConfig;
class PxgCudaBroadPhaseSap;
class PxgGpuNarrowphaseCore;
class PxgSoftBody;
struct PxgConstraintPrepareDesc;
class PxPostSolveCallback;
struct PxgSoftBodySoftBodyConstraintBlock
{
float4 barycentric0[32];
float4 barycentric1[32];
float4 normal_pen[32];
PxReal velMultiplier[32];
PxReal friction[32];
};
namespace Dy
{
class DeformableVolume;
}
class PxgSoftBodyCore : public PxgFEMCore
{
public:
PxgSoftBodyCore(PxgCudaKernelWranglerManager* gpuKernelWrangler, PxCudaContextManager* cudaContextManager,
PxgHeapMemoryAllocatorManager* heapMemoryManager, PxgSimulationController* simController,
PxgGpuContext* context, const PxU32 maxContacts, const PxU32 collisionStackSize, const bool isTGS);
~PxgSoftBodyCore();
//integrate verts position based on gravity
void preIntegrateSystems(PxgSoftBody* softbodies, PxU32* activeSoftbodies, const PxU32 nbActiveSoftbodies,
const PxVec3 gravity, const PxReal dt);
// calculate softbody's world bound
void refitBound(PxgSoftBody* softbodies, const PxU32 nbActiveSoftbodies);
void resetContactCounts();
void checkBufferOverflows();
void selfCollision();
//after narrow phase, we sort soft body contact by rigid id and particle id
void sortContacts(const PxU32 nbActiveSoftbodies);
void updateSimTetraRotations();
void updateTetraRotations();
void solve(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgConstraintPrepareDesc> prepDescd, PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd,
PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd, const PxReal dt, CUstream solverStream,
const bool isFirstIteration);
void solveTGS(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgConstraintPrepareDesc> prepDescd, PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd,
PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd, const PxReal dt, CUstream solverStream,
const bool isVelocityIteration, const PxReal biasCoefficient, const bool isFirstIteration, const PxVec3& gravity);
void calculateStress();
void plasticDeformation();
void constraintPrep(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgConstraintPrepareDesc> prepDescd, const PxReal invDt, PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, CUstream solverStream,
const bool isTGS, PxU32 nbSolverBodies, PxU32 nbArticulations);
bool updateUserData(PxPinnedArray<PxgSoftBody>& softBodyPool, PxArray<PxU32>& softBodyNodeIndexPool,
const PxU32* activeSoftBodies, const PxU32 nbActiveSoftBodies, void** bodySimsLL);
void copySoftBodyDataDEPRECATED(void** data, void* dataSizes, void* softBodyIndices, PxSoftBodyGpuDataFlag::Enum flag, const PxU32 nbCopySoftBodies, const PxU32 maxSize, CUevent copyEvent);
void applySoftBodyDataDEPRECATED(void** data, void* dataSizes, void* softBodyIndices, PxSoftBodyGpuDataFlag::Enum flag, const PxU32 nbUpdatedSoftBodies, const PxU32 maxSize, CUevent applyEvent, CUevent signalEvent);
CUstream getStream() { return mStream; }
void syncSoftBodies();
void createActivatedDeactivatedLists();
PxgCudaBuffer& getTempCellsHistogram() { return mTempCellsHistogramBuf; }
PxgTypedCudaBuffer<PxU32>& getTempBlockCellsHistogram() { return mTempBlockCellsHistogramBuf; }
PxgTypedCudaBuffer<PxU32>& getTempHistogramCount() { return mTempHistogramCountBuf; }
PxgTypedCudaBuffer<float4>& getClothVsSoftBodyContacts() { return mSCContactPointBuffer; }
PxgTypedCudaBuffer<float4>& getClothVsSoftBodyNormalPens() { return mSCContactNormalPenBuffer; }
PxgTypedCudaBuffer<float4>& getClothVsSoftBodyBarycentrics0() { return mSCContactBarycentricBuffer0; } //barycentric toward soft body contact
PxgTypedCudaBuffer<float4>& getClothVsSoftBodyBarycentrics1() { return mSCContactBarycentricBuffer1; } //barycentric toward cloth contact
PxgTypedCudaBuffer<PxgFemFemContactInfo>& getClothVsSoftBodyContactInfos() { return mSCContactInfoBuffer; }
PxgTypedCudaBuffer<PxU32>& getClothVsSoftBodyContactCount() { return mSCTotalContactCountBuffer; }
PxgTypedCudaBuffer<PxU32>& getPrevClothVsSoftBodyContactCount() { return mPrevSCContactCountBuffer; }
PxgCudaPagedLinearAllocator<PxgHeapMemoryAllocator>& getStackAllocator() { return mIntermStackAlloc; }
//apply position delta change original grid model tetra mesh
void finalizeVelocities(const PxReal dt, const PxReal scale, const bool isTGS);
//apply position delta change original grid model tetra mesh
void applyExternalTetraDeltaGM(const PxU32 nbActiveSoftbodies, const PxReal dt, CUstream stream);
private:
PX_DEPRECATED void copyOrApplySoftBodyDataDEPRECATED(PxU32 dataIndex, PxU32* softBodyIndices, PxU8** data, PxU32* dataSizes, PxU32 maxSizeInBytes, const PxU32 nbSoftbodies, const PxU32 applyDataToSoftBodies);
//integrate verts position based on gravity
void preIntegrateSystem(PxgDevicePointer<PxgSoftBody> softbodiesd, PxgDevicePointer<PxU32> activeSoftBodiesd,
const PxU32 nbActiveSoftBodies, const PxU32 maxVerts, const PxVec3 gravity, const PxReal dt, CUstream bpStream);
//These method are running at the solverStream
void prepRigidContactConstraint(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgConstraintPrepareDesc> prepDescd,
const PxReal invDt, PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, CUstream solverStream, const bool isTGS, PxU32 numSolverBodies, PxU32 numArticulations);
void prepRigidAttachmentConstraints(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgConstraintPrepareDesc> prepDescd,
const PxReal invDt, PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, CUstream stream, bool isTGS);
void prepSoftBodyAttachmentConstraints(CUstream stream);
void prepClothAttachmentConstraints(CUstream stream);
void prepParticleAttachmentConstraints(CUstream stream);
void solveRSContactsOutputRigidDelta(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd,
PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd, CUstream solverStream, const PxReal dt);
void solveRSContactsOutputRigidDeltaTGS(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd,
PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd, PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd, PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd, CUstream solverStream,
const PxReal dt);
//run on soft body stream
void prepSoftBodyParticleConstraint();
//run on soft body stream
void prepSoftBodyClothConstraint();
//These method are running at the soft body stream
void prepSoftbodyContactConstraint();
void updateTetModelVerts(PxgDevicePointer<PxgSoftBody> softbodiesd, PxgDevicePointer<PxU32> activeSoftbodiesd,
const PxU32 nbActiveSoftbodies, CUstream updateStream);
//solve in the grid model
void solveCorotationalFEM(PxgSoftBody* softbodies, PxgSoftBody* softbodiesd, PxgDevicePointer<PxU32> activeSoftbodiesd,
const PxU32 nbActiveSoftbodies, const PxReal dt, CUstream stream, const bool isTGS, const bool isFirstIteration);
void step(PxReal dt, CUstream stream, const PxU32 nbActiveSoftBodies, const PxVec3& gravity);
void solveRigidAttachment(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd, PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd,
PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd, CUstream solverStream, const PxReal dt);
void solveSoftBodyAttachmentDelta();
void solveParticleAttachmentDelta();
void solveClothAttachmentDelta();
void solveRigidAttachmentTGS(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd, PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd, PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd,
PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd, CUstream solverStream, const PxReal dt, const PxReal biasCoefficient, bool isVelocityIteration);
//solve soft body vs particle contact and output to soft body delta buffer
void solveSPContactsOutputSoftBodyDelta(const PxReal dt, const PxReal biasCoefficient);
//solve soft body vs particle contact and output to particle delta buffer
void solveSPContactsOutputParticleDelta(const PxReal dt, const PxReal biasCoefficient, CUstream particleStream);
//solve soft body vs cloth contact and update position
void solveSCContactsOutputDelta();
//solve soft body vs soft body contact and output to soft body delta buffer
void solveSSContactsOutputSoftBodyDelta(const float dt, const float biasCoefficient, const bool isTGS);
void queryRigidContactReferenceCount(PxgDevicePointer<PxgPrePrepDesc> prePrepDescd,
PxgDevicePointer<PxgSolverCoreDesc> solverCoreDescd, PxgDevicePointer<PxgSolverSharedDescBase> sharedDescd,
PxgDevicePointer<PxgArticulationCoreDesc> artiCoreDescd, CUstream solverStream, PxReal dt);
//--------------------------------------------------------------------------------------
//soft body vs cloth collision contacts
PxgTypedCudaBuffer<float4> mSCContactPointBuffer;
PxgTypedCudaBuffer<float4> mSCContactNormalPenBuffer;
PxgTypedCudaBuffer<float4> mSCContactBarycentricBuffer0;
PxgTypedCudaBuffer<float4> mSCContactBarycentricBuffer1;
PxgTypedCudaBuffer<PxgFemFemContactInfo> mSCContactInfoBuffer;
PxgTypedCudaBuffer<PxU32> mSCTotalContactCountBuffer;
PxgTypedCudaBuffer<PxU32> mPrevSCContactCountBuffer;
//contact prep buffer
PxgTypedCudaBuffer<PxgSoftBodySoftBodyConstraintBlock> mSCConstraintBuf; //constraint prep for cloth vs soft body
//To do: ideally, we want to use two separate stream to solve the rigid body and soft body collision
PxgTypedCudaBuffer<PxReal> mSCLambdaNBuf; // accumulated deltaLambdaN for collision between FEMCloth and soft body
CUevent mBoundUpdateEvent;//this event is used to synchronize the broad phase stream(updateBound is running on broad phase stream) and mStream
CUevent mSolveRigidEvent;
CUevent mConstraintPrepSoftBodyParticleEvent; //this event is used to synchronize constraint prep(soft body stream) and solve soft body vs particle system contacts (particle stream)
CUevent mSolveSoftBodyParticleEvent; //this event is used to synchronize particle system contacts (particle stream) before we call applyExternalTetraDelta
public:
PxArray<Dy::DeformableVolume*> mActivatingDeformableVolumes;
PxArray<Dy::DeformableVolume*> mDeactivatingDeformableVolumes;
PxPostSolveCallback* mPostSolveCallback;
};
struct PxgSoftBodyContactWriter
{
float4* outPoint;
float4* outNormalPen;
float4* outBarycentric0;
float4* outBarycentric1;
PxgFemFemContactInfo* outContactInfo;
PxU32* totalContactCount;
PxU32 maxContacts;
PxgSoftBodyContactWriter(PxgSoftBodyCore* softBodyCore, PxgFEMCore* femClothCore = NULL)
{
if (femClothCore)
{
totalContactCount = softBodyCore->getClothVsSoftBodyContactCount().getTypedPtr();
outPoint = softBodyCore->getClothVsSoftBodyContacts().getTypedPtr();
outNormalPen = softBodyCore->getClothVsSoftBodyNormalPens().getTypedPtr();
outBarycentric0 = softBodyCore->getClothVsSoftBodyBarycentrics0().getTypedPtr();
outBarycentric1 = softBodyCore->getClothVsSoftBodyBarycentrics1().getTypedPtr();
outContactInfo = softBodyCore->getClothVsSoftBodyContactInfos().getTypedPtr();
maxContacts = PxMin(softBodyCore->mMaxContacts, femClothCore->mMaxContacts);
}
else
{
totalContactCount = softBodyCore->getVolumeContactOrVTContactCount().getTypedPtr();
outPoint = softBodyCore->getFemContacts().getTypedPtr();
outNormalPen = softBodyCore->getFemNormalPens().getTypedPtr();
outBarycentric0 = softBodyCore->getFemBarycentrics0().getTypedPtr();
outBarycentric1 = softBodyCore->getFemBarycentrics1().getTypedPtr();
outContactInfo = softBodyCore->getVolumeContactOrVTContactInfos().getTypedPtr();
maxContacts = softBodyCore->mMaxContacts;
}
}
PX_FORCE_INLINE PX_CUDA_CALLABLE bool writeContact(PxU32 index, const float4& contact, const float4& normalPen, const float4& barycentric0, const float4& barycentric1,
PxU32 pairId0, PxU32 pairId1)
{
if (index >= maxContacts)
return false;
outPoint[index] = contact;
outNormalPen[index] = normalPen;
outBarycentric0[index] = barycentric0;
outBarycentric1[index] = barycentric1;
outContactInfo[index].pairInd0 = pairId0;
outContactInfo[index].pairInd1 = pairId1;
return true;
}
};
}
#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_SOFTBODY_CORE_KERNEL_INDICES_H
#define PXG_SOFTBODY_CORE_KERNEL_INDICES_H
namespace physx
{
struct PxgSoftBodyKernelBlockDim
{
enum
{
SB_PREINTEGRATION = 1024,
SB_REFIT = 256,
SB_INTERNALSOLVE = 256,
SB_UPDATEROTATION = 256,
SB_SOLVETETRA = 64,
SB_SOLVETETRA_LOW = 32,
SB_REORDERCONTACTS = 256,
SB_ACCUMULATE_DELTA = 512,
};
};
struct PxgSoftBodyKernelGridDim
{
enum
{
SB_REFIT = 32,
SB_SBMIDPHASE = 1024,
SB_SBCG = 1024,
SB_MESHCG = 1024,
SB_HFCG = 1024,
SB_UPDATEROTATION = 1024,
SB_SOLVETETRA = 64,
SB_REORDERCONTACTS = 1024,
SB_ACCUMULATE_DELTA = 32,
};
};
}
#endif

View File

@@ -0,0 +1,80 @@
// 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_SPARSE_GRID_DATA_STANDALONE_H
#define PXG_SPARSE_GRID_DATA_STANDALONE_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec4.h"
#include "PxSparseGridParams.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
/**
\brief Minimal set of data to access cells in a sparse grid
*/
struct PxSparseGridData
{
PxSparseGridParams mGridParams; //!< The grid descriptor
PxU32* mUniqueHashkeyPerSubgrid; //!< A unique id for every subgrid that is currently in use
PxU32* mSubgridNeighbors; //!< Contains 27 elements for every subgrid in use and provides indices to the neighbors in the 3x3x3 neighborhood
PxU32* mNumSubgridsInUse; //!< The number of subgrids that are currently in use
PxU32* mSubgridOrderMap; //!< Only used for subgrids that have subgrid reuse enabled for consistent order across frames
PxSparseGridData() : mSubgridOrderMap(NULL) {}
/**
\brief The number of cells in the sparse grid, not all of them are always in use
\return The number of cells
*/
PX_FORCE_INLINE PX_CUDA_CALLABLE PxU32 maxNumCells()
{
return mGridParams.maxNumSubgrids * mGridParams.subgridSizeX *mGridParams.subgridSizeY *mGridParams.subgridSizeZ;
}
/**
\brief The sparse grid's cell size
\return The cell size
*/
PX_FORCE_INLINE PX_CUDA_CALLABLE PxReal getCellSize()
{
return mGridParams.gridSpacing;
}
};
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif

View File

@@ -0,0 +1,270 @@
// 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_SPARSE_GRID_STANDALONE_H
#define PXG_SPARSE_GRID_STANDALONE_H
#include "cudamanager/PxCudaContext.h"
#include "cudamanager/PxCudaContextManager.h"
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxVec4.h"
#include "PxgAlgorithms.h"
#include "PxSparseGridParams.h"
#include "PxParticleSystemFlag.h"
#if !PX_DOXYGEN
namespace physx
{
#endif
/**
\brief Constructs a sparse grid structure given an array of particle positions
*/
class PxSparseGridBuilder
{
protected:
PxgKernelLauncher* mKernelLauncher;
PxGpuScan mScan;
PxGpuRadixSort<PxU32> mSort;
PxSparseGridParams mSparseGridParams;
PxU32* mHashkeyPerParticle;
PxU32* mSortedParticleToSubgrid;
PxU32* mSortedUniqueHashkeysPerSubgrid;
PxU32* mSubgridNeighborLookup;
//Optional
PxU32* mSortedToOriginalParticleIndex;
PxGpuScan mScanNeighbors;
PxGpuRadixSort<PxU32> mNeighborSort;
PxU32* mNeighborCollector;
PxU32* mRequiredNeighborMask;
PxU32 mMaxParticles;
PxU32 mNeighborhoodSize; //!< The minimum number of cells available around a particle that are guaranteed to be accessible. It can be computed as PxCeil(particleRadius/sparseGridSpacing)
bool mTrackParticleOrder;
bool mCopySubgridsInUseToHost;
PxU32 mNumSubgridsInUse;
PxU32* updateSubgrids(PxVec4* deviceParticlePos, const PxU32 numParticles, PxU32* devicePhases, CUstream stream,
PxU32 validPhase = PxParticlePhaseFlag::eParticlePhaseFluid, const PxU32* activeIndices = NULL);
void updateSubgridNeighbors(PxU32* totalCountPointer, CUstream stream);
public:
PxSparseGridBuilder() : mHashkeyPerParticle(NULL), mSortedToOriginalParticleIndex(NULL), mCopySubgridsInUseToHost(true), mNumSubgridsInUse(0) { }
~PxSparseGridBuilder()
{
release();
}
/**
\brief The number of subgrids that are in use. Subgrids in use contain at least one particle or have particles closely nearby
\return The number of subgrids in use
*/
PX_FORCE_INLINE PxU32 getNumSubgridsInUse() const
{
return mNumSubgridsInUse;
}
/**
\brief Sets the state of the flag that defines if the subgrid in use information gets copied to the host every frame
\param[in] enabled Enable or disable copying the number of subgrids in use to the host every frame
*/
PX_FORCE_INLINE void setCopySubgridsInUseToHostEnabled(bool enabled)
{
mCopySubgridsInUseToHost = enabled;
}
/**
\brief Gets the state of the flag that defines if the subgrid in use information gets copied to the host every frame
\return True if enabled
*/
PX_FORCE_INLINE bool getCopySubgridsInUseToHostEnabled() const
{
return mCopySubgridsInUseToHost;
}
/**
\brief Gets the sparse grid parameters
\return The sparse grid parameters
*/
PX_FORCE_INLINE PxSparseGridParams getGridParameters() const
{
return mSparseGridParams;
}
/**
\brief Sets the sparse grid parameters
\param[in] params The new sparse grid parameters
*/
PX_FORCE_INLINE void setGridParameters(PxSparseGridParams params)
{
release();
initialize(mKernelLauncher, params, mMaxParticles, mNeighborhoodSize, mTrackParticleOrder);
}
/**
\brief Gets the device pointer to the number of subgrids in use
\return The device pointer to the number of subgrids in use
*/
PX_FORCE_INLINE PxU32* getSubgridsInUseGpuPointer()
{
if (mNeighborhoodSize == 0)
return mScan.getSumPointer();
else
return mScanNeighbors.getSumPointer();
}
/**
\brief Gets the device array containing the subgrid hashkey for every subgrid in use
\return The device array containing the subgrid hashkey for every subgrid in use. Be aware that this data gets overwritten by the subgridEndIndicesBuffer data after a call to updateSubgridEndIndices
*/
PX_FORCE_INLINE PxU32* getUniqueHashkeysPerSubgrid()
{
return mSortedUniqueHashkeysPerSubgrid;
}
/**
\brief Gets the subgrid neighbor lookup table
\return The device pointer to the subgrid neighbor lookup table. Contains 27 elements for every subgrid in use and provides indices to the neighbors in the 3x3x3 neighborhood
*/
PX_FORCE_INLINE PxU32* getSubgridNeighborLookup()
{
return mSubgridNeighborLookup;
}
/**
\brief Gets the sorted particle to subgrid index device buffer.
\return The sorted particle to subgrid index device buffer
*/
PX_FORCE_INLINE PxU32* getSortedParticleToSubgrid()
{
return mSortedParticleToSubgrid;
}
/**
\brief Gets the sorted to original particle index device buffer.
\return The sorted to original particle index device buffer
*/
PX_FORCE_INLINE PxU32* getSortedToOriginalParticleIndex()
{
return mSortedToOriginalParticleIndex;
}
/**
\brief Gets the subgrid end indices buffer. This allows to traverse the (sorted) particles in a subgrid because the buffer holds an inclusive cumulative sum of the active subgrid particle counts.
\return The subgrid end indices device buffer
*/
PX_FORCE_INLINE PxU32* getSubgridEndIndicesBuffer()
{
return mSortedUniqueHashkeysPerSubgrid;
}
/**
\brief Gets the maximal number of particles that can be processed
\return The maximal number of particles
*/
PX_FORCE_INLINE PxU32 getMaxParticles() const
{
return mMaxParticles;
}
/**
\brief Sets the maximal number of particles that can be processed
\param[in] maxParticles The maximal number of particles
*/
PX_FORCE_INLINE void setMaxParticles(PxU32 maxParticles)
{
release();
initialize(mKernelLauncher, mSparseGridParams, maxParticles, mNeighborhoodSize, mTrackParticleOrder);
}
/**
\brief Initializes the sparse grid builder
\param[in] cudaContextManager A cuda context manager
\param[in] sparseGridParams The sparse grid parameters
\param[in] maxNumParticles The number of particles
\param[in] neighborhoodSize The size of the neighborhood around a particle that must be accessible.
\param[in] trackParticleOrder If set to true, the mSortedToOriginalParticleIndex array will be updated during every call of updateSparseGrid
*/
virtual void initialize(PxgKernelLauncher* cudaContextManager, const PxSparseGridParams& sparseGridParams,
PxU32 maxNumParticles, PxU32 neighborhoodSize, bool trackParticleOrder = false);
virtual void release();
//Completely rebuilds the sparse grid. Does not support to access data from previous timesteps. Supports a particle radius (neighborhoodSize)
/**
\brief Updates the sparse grid given an array of particle positions
\param[in] deviceParticlePos The particle positions device array
\param[in] numParticles The number of particles
\param[in] devicePhases The particle's phases device array (optional, can be null)
\param[in] stream The stream on which the work gets scheduled
\param[in] validPhase The valid phase mask marking the phase bits that particles must have set in order to contribute to the isosurface
\param[in] activeIndices Optional device array of active particle indices
*/
virtual void updateSparseGrid(PxVec4* deviceParticlePos, PxU32 numParticles, PxU32* devicePhases, CUstream stream,
PxU32 validPhase = PxParticlePhaseFlag::eParticlePhaseFluid, const PxU32* activeIndices = NULL);
/**
\brief Updates the subgrid end indices. This is only required if the particles per subgrid need to get processed (e. g. anisotropy generation)
\param[in] numParticles The number of particles
\param[in] stream The stream on which the work gets scheduled
*/
void updateSubgridEndIndices(PxU32 numParticles, CUstream stream);
};
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif