1839 lines
70 KiB
C++
1839 lines
70 KiB
C++
// 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.
|
|
|
|
#include "common/PxProfileZone.h"
|
|
#include "cudamanager/PxCudaContext.h"
|
|
#include "foundation/PxFoundation.h"
|
|
#include "foundation/PxPreprocessor.h"
|
|
|
|
#include "PxsContext.h"
|
|
#include "PxsSimpleIslandManager.h"
|
|
#include "PxsMaterialManager.h"
|
|
#include "CmFlushPool.h"
|
|
#include "foundation/PxArray.h"
|
|
#include "foundation/PxAllocator.h"
|
|
|
|
#include "PxvDynamics.h" // for PxsBodyCore
|
|
#include "PxvGeometry.h" // for PxsShapeCore
|
|
#include "mesh/GuTriangleMesh.h"
|
|
#include "hf/GuHeightField.h"
|
|
#include "PxgNphaseImplementationContext.h"
|
|
#include "PxgSolverCore.h"
|
|
|
|
//FDTODO: those incudes should eventually disappear as we get rid of the copy-pasted stuff
|
|
#include "PxgDynamicsContext.h"
|
|
#include "PxgKernelWrangler.h"
|
|
#include "PxgSimulationCore.h"
|
|
#include "PxgParticleSystemCore.h"
|
|
#include "PxgArticulationCore.h"
|
|
|
|
#include "cudamanager/PxCudaContextManager.h"
|
|
|
|
#include "GuConvexGeometry.h"
|
|
#include "GuConvexSupport.h"
|
|
|
|
#if PX_SUPPORT_GPU_PHYSX
|
|
#include "PxPhysXGpu.h"
|
|
#endif
|
|
#include "convexNpCommon.h"
|
|
|
|
using namespace physx;
|
|
using namespace Gu;
|
|
|
|
#define PXG_ENABLE_GPU_NP 1
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
PX_IMPLEMENT_OUTPUT_ERROR
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void PxgCMGpuDiscreteUpdateBase::processContactManagers(PxgContactManagers& managers, PxgGpuContactManagers& managersGPU, GPU_BUCKET_ID::Enum type)
|
|
{
|
|
PxRenderOutput renderOutput(mContext->mContext.getRenderBuffer());
|
|
|
|
managersGPU.mLostAndTotalReportedPairsCountPinned->y = 0;
|
|
managersGPU.mLostAndTotalReportedPairsCountPinned->x = 0;
|
|
|
|
const PxU32 numTests = managers.mCpuContactManagerMapping.size();
|
|
|
|
if (numTests == 0)
|
|
return;
|
|
|
|
PxU32 maxPatches = 1;
|
|
|
|
switch (type)
|
|
{
|
|
case GPU_BUCKET_ID::eConvex:
|
|
mContext->mGpuNarrowphaseCore->testSDKConvexConvexGjkEpaGpu(managersGPU,
|
|
mContext->mContext.getCreateAveragePoint(), managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize,
|
|
&renderOutput
|
|
);
|
|
break;
|
|
case GPU_BUCKET_ID::eConvexPlane:
|
|
mContext->mGpuNarrowphaseCore->testSDKConvexPlaneGjkEpaGpu(managersGPU,
|
|
mContext->mContext.getCreateAveragePoint(), managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize,
|
|
&renderOutput
|
|
);
|
|
break;
|
|
case GPU_BUCKET_ID::eConvexTrimesh:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKConvexTriMeshSATGpu(managersGPU,
|
|
mContext->mContext.getCreateAveragePoint(), managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize);
|
|
maxPatches = PXG_MULTIMANIFOLD_MAX_SUBMANIFOLDS;
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eConvexHeightfield:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKConvexHeightfieldGpu(managersGPU,
|
|
mContext->mContext.getCreateAveragePoint(), managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize);
|
|
maxPatches = PXG_MULTIMANIFOLD_MAX_SUBMANIFOLDS;
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eConvexCorePlane:
|
|
mContext->mGpuNarrowphaseCore->testSDKConvexCorePlaneGjkEpaGpu(managersGPU,
|
|
mContext->mContext.getCreateAveragePoint(), managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize,
|
|
&renderOutput);
|
|
break;
|
|
case GPU_BUCKET_ID::eConvexCoreConvex:
|
|
mContext->mGpuNarrowphaseCore->testSDKConvexCoreConvexGjkEpaGpu(managersGPU,
|
|
mContext->mContext.getCreateAveragePoint(), managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize,
|
|
&renderOutput);
|
|
break;
|
|
case GPU_BUCKET_ID::eConvexCoreTrimesh:
|
|
mContext->mGpuNarrowphaseCore->testSDKConvexCoreTrimeshGjkEpaGpu(managersGPU,
|
|
mContext->mContext.getCreateAveragePoint(), managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize,
|
|
&renderOutput);
|
|
maxPatches = Gu::Contact::MAX_PATCHES;
|
|
break;
|
|
case GPU_BUCKET_ID::eConvexCoreTetmesh:
|
|
mContext->mGpuNarrowphaseCore->testSDKConvexCoreTetmeshGjkEpaGpu(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
case GPU_BUCKET_ID::eConvexCoreClothmesh:
|
|
mContext->mGpuNarrowphaseCore->testSDKConvexCoreClothmeshGjkEpaGpu(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
case GPU_BUCKET_ID::eSphere:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKSphereGpu(managersGPU, managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize,
|
|
&renderOutput
|
|
);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eBoxBox:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKBoxBoxGpu(managersGPU, managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize,
|
|
&renderOutput
|
|
);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eSphereTrimesh:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKSphereTriMeshSATGpu(managersGPU,
|
|
mContext->mContext.getCreateAveragePoint(), managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize);
|
|
maxPatches = PXG_MULTIMANIFOLD_MAX_SUBMANIFOLDS;
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eSphereHeightfield:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKSphereHeightfieldGpu(managersGPU,
|
|
mContext->mContext.getCreateAveragePoint(), managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize);
|
|
maxPatches = PXG_MULTIMANIFOLD_MAX_SUBMANIFOLDS;
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eTrianglePlane:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKTriMeshPlaneGpu(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize);
|
|
break;
|
|
}
|
|
|
|
case GPU_BUCKET_ID::eTriangleHeightfield:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKTriMeshHeightfieldGpu(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize);
|
|
maxPatches = MAX_MESH_MESH_PATCHES;
|
|
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eTriangleTriangle:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKTriMeshTriMeshGpu(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mContactStreamPool->mDataStream,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStream,
|
|
mContext->mContext.mPatchStreamPool->mDataStreamSize, mContext->mContext.mContactStreamPool->mDataStreamSize,
|
|
mContext->mContext.mForceAndIndiceStreamPool->mDataStreamSize);
|
|
maxPatches = MAX_MESH_MESH_PATCHES;
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eSoftbody:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKSoftbody(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eSoftbodies:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKSoftbodies(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eSoftbodyFemCloth:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKSoftbodyCloth(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eSoftbodyTrimesh:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKSoftbodyTrimesh(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eSoftbodySdfTrimesh:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKSoftbodySdfTrimesh(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eSoftbodyHeightfield:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKSoftbodyHeightfield(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eFemClothSphere:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKFemClothSphere(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eFemClothPlane:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKFemClothPlane(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eFemClothBox:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKFemClothBox(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eFemClothConvexes:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKFemClothConvexes(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eFemClothes:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKFemClothCloth(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eFemClothTrimesh:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKFemClothTrimesh(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eFemClothSdfTrimesh:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKFemClothSdfTrimesh(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eFemClothHeightfield:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKFemClothHeightfield(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eConvexParticle:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKConvexParticle(managersGPU,
|
|
managers.mCpuContactManagerMapping.size());
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eParticlesystems:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKParticleSystemGpu(managersGPU,
|
|
managers.mCpuContactManagerMapping.size());
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eParticlesystemSoftbody:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKParticleSoftbody(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eParticlesystemFemCloth:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKParticleFemCloth(managersGPU,
|
|
managers.mCpuContactManagerMapping.size(), &renderOutput);
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eParticlesystemTrimesh:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKParticleTriMesh(managersGPU,
|
|
managers.mCpuContactManagerMapping.size());
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eParticlesystemSdfTrimesh:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKParticleSdfTriMesh(managersGPU,
|
|
managers.mCpuContactManagerMapping.size());
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eParticlesystemHeightfield:
|
|
{
|
|
mContext->mGpuNarrowphaseCore->testSDKParticleHeightfield(managersGPU,
|
|
managers.mCpuContactManagerMapping.size());
|
|
break;
|
|
}
|
|
case GPU_BUCKET_ID::eFallback:
|
|
case GPU_BUCKET_ID::eCount:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
mContext->mGpuNarrowphaseCore->updateFrictionPatches(managersGPU, managers.mCpuContactManagerMapping.size(),
|
|
mContext->mContext.mPatchStreamPool->mDataStream, mContext->mContext.mFrictionPatchStreamPool->mDataStream);
|
|
|
|
mContext->mMaxPatches = PxMax(mContext->mMaxPatches, maxPatches);
|
|
}
|
|
|
|
void PxgCMGpuDiscreteUpdateTask::runInternal()
|
|
{
|
|
mContext->removeLostPairs();
|
|
|
|
mPostBroadPhaseTask->removeReference();
|
|
|
|
PxgGpuNarrowphaseCore* npCore = mContext->mGpuNarrowphaseCore;
|
|
|
|
mContext->mGpuNarrowphaseCore->syncNotRigidWithNp();
|
|
|
|
mContext->mMaxPatches = 1;
|
|
|
|
for (PxU32 i = GPU_BUCKET_ID::eConvex; i < GPU_BUCKET_ID::eCount; ++i)
|
|
{
|
|
GPU_BUCKET_ID::Enum type = GPU_BUCKET_ID::Enum(i);
|
|
processContactManagers(npCore->getExistingContactManagers(type),
|
|
npCore->getExistingGpuContactManagers(type), type);
|
|
}
|
|
}
|
|
|
|
void PxgCMGpuDiscreteSecondPassUpdateTask::runInternal()
|
|
{
|
|
PxgGpuNarrowphaseCore* npCore = mContext->mGpuNarrowphaseCore;
|
|
|
|
npCore->prepareTempContactManagers();
|
|
|
|
npCore->syncNotRigidWithNp();
|
|
|
|
PxU32 numCpuContactManagerMappings = 0;
|
|
|
|
for (PxU32 i = GPU_BUCKET_ID::eConvex; i < GPU_BUCKET_ID::eCount; ++i)
|
|
{
|
|
GPU_BUCKET_ID::Enum type = GPU_BUCKET_ID::Enum(i);
|
|
|
|
PxgNewContactManagers& newContactManger = npCore->getNewContactManagers(type);
|
|
|
|
processContactManagers(newContactManger,
|
|
npCore->getNewGpuContactManagers(type),
|
|
GPU_BUCKET_ID::Enum(i));
|
|
|
|
numCpuContactManagerMappings += newContactManger.mCpuContactManagerMapping.size();
|
|
}
|
|
|
|
if(numCpuContactManagerMappings > 0)
|
|
{
|
|
mContext->mGpuNarrowphaseCore->pushBuffer();
|
|
}
|
|
}
|
|
|
|
PxgNphaseImplementationContext::PxgNphaseImplementationContext(
|
|
PxsContext& context, PxsKernelWranglerManager* gpuKernelWrangler, PxvNphaseImplementationFallback* fallbackForUnsupportedCMs,
|
|
const PxGpuDynamicsMemoryConfig& gpuDynamicsConfig, void* contactStreamBase, void* patchStreamBase, void* forceAndIndiceStreamBase,
|
|
PxBoundsArrayPinned& bounds, IG::IslandSim* islandSim, physx::Dy::Context* dynamicsContext, PxgHeapMemoryAllocatorManager* heapMemoryManager, bool useGPUBP) :
|
|
PxvNphaseImplementationContext (context),
|
|
mFallbackForUnsupportedCMs (fallbackForUnsupportedCMs),
|
|
mUpdateCMsFirstPassTask (this),
|
|
mUpdateCMsSecondPassTask (this),
|
|
mUpdateFallbackPairs (this),
|
|
mContactManagerOutputs (PxVirtualAllocator(heapMemoryManager->mMappedMemoryAllocators)),
|
|
mTotalNbPairs (0),
|
|
mBounds (bounds),
|
|
mUseGPUBP (useGPUBP)
|
|
{
|
|
#if PX_CHECKED
|
|
if(!context.getPCM())
|
|
outputError<PxErrorCode::ePERF_WARNING>(__LINE__, "Attempting to use GPU rigid body pipeline without using PCM contact gen! All contact gen will be performed on CPU.");
|
|
#endif
|
|
{
|
|
mGpuDynamicContext = static_cast<PxgGpuContext*>(dynamicsContext);
|
|
CUstream stream = mGpuDynamicContext->getGpuSolverCore()->getStream();
|
|
mGpuNarrowphaseCore = PX_NEW(PxgGpuNarrowphaseCore)(static_cast<PxgCudaKernelWranglerManager*>(gpuKernelWrangler), context.getCudaContextManager(), gpuDynamicsConfig,
|
|
contactStreamBase, patchStreamBase, forceAndIndiceStreamBase, islandSim, stream, heapMemoryManager, this);
|
|
|
|
mGpuDynamicContext->mGpuNpCore = mGpuNarrowphaseCore;
|
|
mGpuNarrowphaseCore->mGpuContext = mGpuDynamicContext;
|
|
|
|
for (PxU32 i = 0; i < GPU_BUCKET_ID::eCount; ++i)
|
|
{
|
|
mRecordedGpuPairCount[i] = mNbPairCount[i] = 0;
|
|
}
|
|
}
|
|
mMaxPatches = 1;
|
|
};
|
|
|
|
PxgNphaseImplementationContext::~PxgNphaseImplementationContext()
|
|
{
|
|
PxCudaContextManager* contMan = mContext.getCudaContextManager();
|
|
contMan->acquireContext();
|
|
PX_DELETE(mGpuNarrowphaseCore);
|
|
contMan->releaseContext();
|
|
}
|
|
|
|
void PxgCMGpuDiscreteUpdateFallbackTask::runInternal()
|
|
{
|
|
mContext->updateContactManagersFallback(mDt, mCont);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::removeLostPairs()
|
|
{
|
|
mGpuNarrowphaseCore->removeLostPairs();
|
|
|
|
//mGpuNarrowphaseCore->removeLostPairsConvexTriMesh(mContext.getEventProfiler());
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::prepareTempContactManagers(PxBaseTask* continuation)
|
|
{
|
|
mGpuNarrowphaseCore->prepareTempContactManagersTasks(mContext.getTaskPool(), continuation);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::updateContactManagersFallback(PxReal dt, PxBaseTask* continuation)
|
|
{
|
|
mFallbackForUnsupportedCMs->removeContactManagersFallback(mContactManagerOutputs.begin());
|
|
mFallbackForUnsupportedCMs->processContactManager(dt, mContactManagerOutputs.begin(), continuation);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::updateNarrowPhaseShape()
|
|
{
|
|
//run in npstream
|
|
mGpuNarrowphaseCore->prepareGpuNarrowphase(mContext.getTransformCache(), mContext.getContactDistances(),
|
|
mHasContactDistanceChanged);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::updateContactManager(PxReal dt, bool hasContactDistanceChanged, PxBaseTask* continuation,
|
|
PxBaseTask* firstPassNpContinuation, Cm::FanoutTask* updateBoundAndShapeTask)
|
|
{
|
|
PX_PROFILE_ZONE("Sim.queueNarrowPhase", 0);
|
|
|
|
mHasContactDistanceChanged = hasContactDistanceChanged;
|
|
|
|
mContext.clearManagerTouchEvents();
|
|
|
|
mUpdateFallbackPairs.setContinuation(continuation);
|
|
mUpdateFallbackPairs.setDt(dt);
|
|
mUpdateFallbackPairs.removeReference();
|
|
|
|
#if PX_ENABLE_SIM_STATS
|
|
mContext.mSimStats.mNbDiscreteContactPairsTotal = 0;
|
|
mContext.mSimStats.mNbDiscreteContactPairsWithCacheHits = 0;
|
|
mContext.mSimStats.mNbDiscreteContactPairsWithContacts = 0;
|
|
#else
|
|
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
|
#endif
|
|
|
|
mContext.mMaxPatches = 0;
|
|
|
|
mUpdateCMsFirstPassTask.setDt(dt);
|
|
mUpdateCMsFirstPassTask.setFirstPassContinuation(firstPassNpContinuation);
|
|
mUpdateCMsFirstPassTask.setContinuation(continuation);
|
|
|
|
updateBoundAndShapeTask->addDependent(mUpdateCMsFirstPassTask);
|
|
updateBoundAndShapeTask->removeReference();
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::postBroadPhaseUpdateContactManager(PxBaseTask* continuation)
|
|
{
|
|
continuation->addReference();
|
|
mUpdateCMsFirstPassTask.setPostBroadPhaseTask(continuation);
|
|
mUpdateCMsFirstPassTask.removeReference();
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::secondPassUpdateContactManager(PxReal dt, PxBaseTask* continuation)
|
|
{
|
|
PX_PROFILE_ZONE("Sim.queueNarrowPhase", 0);
|
|
mUpdateCMsSecondPassTask.setContinuation(continuation);
|
|
mUpdateCMsSecondPassTask.setDt(dt);
|
|
|
|
prepareTempContactManagers(&mUpdateCMsSecondPassTask);
|
|
|
|
mUpdateCMsSecondPassTask.removeReference();
|
|
|
|
mFallbackForUnsupportedCMs->processContactManagerSecondPass(dt, continuation);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::fetchUpdateContactManager()
|
|
{
|
|
mergeContactManagers(NULL);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::destroy()
|
|
{
|
|
this->~PxgNphaseImplementationContext();
|
|
PX_FREE_THIS;
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::processResults()
|
|
{
|
|
{
|
|
PX_PROFILE_ZONE("GpuNarrowPhase.processResults", 0);
|
|
|
|
PxcNpThreadContext* PX_RESTRICT threadContext = mContext.getNpThreadContext();
|
|
|
|
threadContext->mPCM = mContext.getPCM();
|
|
threadContext->mCreateAveragePoint = mContext.getCreateAveragePoint();
|
|
threadContext->mContactCache = mContext.getContactCacheFlag();
|
|
threadContext->mTransformCache = &(mContext.getTransformCache());
|
|
// PT: TODO: we don't setup the contact distances here?
|
|
|
|
PxU32 newTouchCMCount = 0, lostTouchCMCount = 0;
|
|
PxU32 nbConvexConvex = 0;
|
|
PxU32 nbConvexPlane = 0;
|
|
PxU32 nbConvexTriMesh = 0;
|
|
PxU32 nbConvexHf = 0;
|
|
PxU32 nbSphere = 0;
|
|
PxU32 nbSphereTriMesh = 0;
|
|
PxU32 nbSphereHf = 0;
|
|
PxU32 nbTrianglePlane = 0;
|
|
PxU32 nbTriangleHf = 0;
|
|
|
|
PxU32 maxPatches = threadContext->mMaxPatches;
|
|
{
|
|
nbConvexConvex = mGpuNarrowphaseCore->mContactManagers[GPU_BUCKET_ID::eConvex]->mContactManagers.mCpuContactManagerMapping.size();
|
|
nbConvexPlane = mGpuNarrowphaseCore->mContactManagers[GPU_BUCKET_ID::eConvexPlane]->mContactManagers.mCpuContactManagerMapping.size();
|
|
nbConvexTriMesh = mGpuNarrowphaseCore->mContactManagers[GPU_BUCKET_ID::eConvexTrimesh]->mContactManagers.mCpuContactManagerMapping.size();
|
|
nbConvexHf = mGpuNarrowphaseCore->mContactManagers[GPU_BUCKET_ID::eConvexHeightfield]->mContactManagers.mCpuContactManagerMapping.size();
|
|
|
|
nbSphere = mGpuNarrowphaseCore->mContactManagers[GPU_BUCKET_ID::eSphere]->mContactManagers.mCpuContactManagerMapping.size();
|
|
nbSphereTriMesh = mGpuNarrowphaseCore->mContactManagers[GPU_BUCKET_ID::eSphereTrimesh]->mContactManagers.mCpuContactManagerMapping.size();
|
|
nbSphereHf = mGpuNarrowphaseCore->mContactManagers[GPU_BUCKET_ID::eSphereHeightfield]->mContactManagers.mCpuContactManagerMapping.size();
|
|
|
|
nbTrianglePlane = mGpuNarrowphaseCore->mContactManagers[GPU_BUCKET_ID::eTrianglePlane]->mContactManagers.mCpuContactManagerMapping.size();
|
|
nbTriangleHf = mGpuNarrowphaseCore->mContactManagers[GPU_BUCKET_ID::eTriangleHeightfield]->mContactManagers.mCpuContactManagerMapping.size();
|
|
|
|
PxBitMap& localChangeTouchCM = threadContext->getLocalChangeTouch();
|
|
|
|
//KS - convex-convex can only produce a maximum of 1 contact patch and convex-mesh produces a max of 4. Mesh-mesh can produce a maximum of
|
|
//32 patches...
|
|
maxPatches = PxMax(maxPatches, mMaxPatches);
|
|
|
|
//Only process the array of found/lost touch events (let's confirm that this works...)
|
|
PxPinnedArray<PxsContactManager*>& lostFoundIndIterator = mGpuNarrowphaseCore->getLostFoundPairsCms();
|
|
PxPinnedArray<PxsContactManagerOutputCounts>& itChangedOutputs = mGpuNarrowphaseCore->getLostFoundPairsOutput();
|
|
|
|
PxU32 nbLostFoundPairs = mGpuNarrowphaseCore->getTotalNbLostFoundPairs();
|
|
|
|
// jcarius: Defensive coding added for OM-119911. In theory this should not be needed, as these counts
|
|
// should never get into an invalid state. We could/should remove this eventually.
|
|
// ### DEFENSIVE
|
|
PX_ASSERT(nbLostFoundPairs <= lostFoundIndIterator.size());
|
|
PX_ASSERT(nbLostFoundPairs <= itChangedOutputs.size());
|
|
if(nbLostFoundPairs > lostFoundIndIterator.size() || nbLostFoundPairs > itChangedOutputs.size())
|
|
{
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "PxgNphaseImplementationContext::processResults: Inconsistent pair numbers!");
|
|
nbLostFoundPairs = PxMin(lostFoundIndIterator.size(), itChangedOutputs.size());
|
|
}
|
|
|
|
PxU32 maxCmIndx = mContext.getContactManagerPool().getMaxUsedIndex();
|
|
localChangeTouchCM.resize(maxCmIndx);
|
|
|
|
//KS - TODO - let's remove this loop entirely in the near future!
|
|
for(PxU32 a = 0; a < nbLostFoundPairs; ++a)
|
|
{
|
|
PxsContactManager* cm = lostFoundIndIterator[a];
|
|
|
|
//PX_ASSERT(cm->getWorkUnit().statusFlags != itChangedOutputs[a].statusFlag);
|
|
|
|
cm->getWorkUnit().mStatusFlags = itChangedOutputs[a].statusFlag; //KS - cache status flag in PxcNpWorkUnit to simplify logic elsewhere....
|
|
|
|
if(itChangedOutputs[a].nbPatches)
|
|
newTouchCMCount++;
|
|
else
|
|
lostTouchCMCount++;
|
|
|
|
localChangeTouchCM.growAndSet(cm->getIndex());
|
|
}
|
|
}
|
|
|
|
#if PX_ENABLE_SIM_STATS
|
|
threadContext->mDiscreteContactPairs[PxGeometryType::eSPHERE][PxGeometryType::eSPHERE] += nbSphere;
|
|
threadContext->mDiscreteContactPairs[PxGeometryType::eCONVEXMESH][PxGeometryType::eCONVEXMESH]+= nbConvexConvex;
|
|
threadContext->mDiscreteContactPairs[PxGeometryType::ePLANE][PxGeometryType::eCONVEXMESH] += nbConvexPlane;
|
|
threadContext->mDiscreteContactPairs[PxGeometryType::eCONVEXMESH][PxGeometryType::eTRIANGLEMESH]+= nbConvexTriMesh;
|
|
threadContext->mDiscreteContactPairs[PxGeometryType::eCONVEXMESH][PxGeometryType::eHEIGHTFIELD] += nbConvexHf;
|
|
threadContext->mDiscreteContactPairs[PxGeometryType::eSPHERE][PxGeometryType::eTRIANGLEMESH] += nbSphereTriMesh;
|
|
threadContext->mDiscreteContactPairs[PxGeometryType::eSPHERE][PxGeometryType::eHEIGHTFIELD] += nbSphereHf;
|
|
threadContext->mDiscreteContactPairs[PxGeometryType::ePLANE][PxGeometryType::eTRIANGLEMESH] += nbTrianglePlane;
|
|
threadContext->mDiscreteContactPairs[PxGeometryType::eTRIANGLEMESH][PxGeometryType::eHEIGHTFIELD] += nbTriangleHf;
|
|
#else
|
|
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
|
#endif
|
|
|
|
threadContext->addLocalNewTouchCount(newTouchCMCount);
|
|
threadContext->addLocalLostTouchCount(lostTouchCMCount);
|
|
|
|
threadContext->mMaxPatches = maxPatches;
|
|
|
|
mContext.putNpThreadContext(threadContext);
|
|
}
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::appendContactManagers()
|
|
{
|
|
}
|
|
|
|
PxsContactManagerOutputCounts* PxgNphaseImplementationContext::getLostFoundPatchOutputCounts()
|
|
{
|
|
return mGpuNarrowphaseCore->mLostFoundPairsOutputData.begin() + mGpuNarrowphaseCore->mTotalLostFoundPairs;
|
|
}
|
|
|
|
PxsContactManager** PxgNphaseImplementationContext::getLostFoundPatchManagers()
|
|
{
|
|
return mGpuNarrowphaseCore->mLostFoundPairsCms.begin() + mGpuNarrowphaseCore->mTotalLostFoundPairs;
|
|
}
|
|
|
|
PxU32 PxgNphaseImplementationContext::getNbLostFoundPatchManagers()
|
|
{
|
|
return mGpuNarrowphaseCore->mTotalLostFoundPatches;
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::mergeContactManagers(PxBaseTask* /*continuation*/)
|
|
{
|
|
mContext.getCudaContextManager()->acquireContext();
|
|
|
|
if (mContactManagerOutputs.capacity() < mTotalNbPairs)
|
|
{
|
|
PX_PROFILE_ZONE("GpuNarrowPhase.allocateManagerOutputs", 0);
|
|
mContactManagerOutputs.reserve(PxMax(mTotalNbPairs, mContactManagerOutputs.capacity() * 2));
|
|
}
|
|
mContactManagerOutputs.forceSize_Unsafe(mTotalNbPairs);
|
|
|
|
mFallbackForUnsupportedCMs->appendContactManagersFallback(mContactManagerOutputs.begin());
|
|
|
|
PxMemCopy(mRecordedGpuPairCount, mNbPairCount, sizeof(PxU32) * GPU_BUCKET_ID::eCount);
|
|
|
|
const PxU32 nbFallbackPairs = mNbPairCount[GPU_BUCKET_ID::eFallback];
|
|
mGpuNarrowphaseCore->fetchNarrowPhaseResults(mContext.mContactStreamPool, mContext.mPatchStreamPool, mContext.mForceAndIndiceStreamPool,
|
|
mContactManagerOutputs.begin(),
|
|
mFallbackForUnsupportedCMs->getShapeInteractionsGPU(),
|
|
mFallbackForUnsupportedCMs->getRestDistancesGPU(),
|
|
mFallbackForUnsupportedCMs->getTorsionalDataGPU(),
|
|
nbFallbackPairs, mFallbackForUnsupportedCMs->getLostFoundPatchOutputCounts(),
|
|
mFallbackForUnsupportedCMs->getLostFoundPatchManagers(), mFallbackForUnsupportedCMs->getNbLostFoundPatchManagers());
|
|
|
|
// AD: need to make sure we're safe if fetchNarrowphaseResults did not run completely because of abort.
|
|
if (mGpuNarrowphaseCore->mCudaContext->isInAbortMode())
|
|
{
|
|
// We have some coupling issues here: we index into this array with mNpIndex, which is never bounds-checked
|
|
// so if we force the size to 0 here, we will still access the memory no matter what. Because we keep passing
|
|
// this thing around as a pointer. This needs to be guarded in all places where we get a contactOutputIterator.
|
|
// we cleared all the data to 0 inside this function, the same as we are doing for contactManagerOutputs that overflow
|
|
// the contact stream. So we are able to handle things being NULL in there. I really hope this is the case.
|
|
mContactManagerOutputs.forceSize_Unsafe(0);
|
|
mTotalNbPairs = 0;
|
|
}
|
|
|
|
bool contactsOverflown = mContext.mContactStreamPool->isOverflown(), forcesOverflown = mContext.mForceAndIndiceStreamPool->isOverflown(),
|
|
patchesOverflown = mContext.mPatchStreamPool->isOverflown();
|
|
|
|
if (contactsOverflown || forcesOverflown || patchesOverflown)
|
|
{
|
|
PxU8* contactLimit = mContext.mContactStreamPool->mDataStream + mContext.mContactStreamPool->mSharedDataIndexGPU;
|
|
PxU8* forceLimit = mContext.mForceAndIndiceStreamPool->mDataStream + mContext.mForceAndIndiceStreamPool->mSharedDataIndexGPU;
|
|
PxU8* patchLimit = mContext.mPatchStreamPool->mDataStream + mContext.mPatchStreamPool->mSharedDataIndexGPU;
|
|
|
|
for (PxU32 i = 0; i < nbFallbackPairs; ++i)
|
|
{
|
|
PxsContactManagerOutput* output = mContactManagerOutputs.begin() + i;
|
|
|
|
if ((output->nbContacts && (output->contactPoints < contactLimit)) ||
|
|
(output->nbContacts && ((PxU8*) output->contactForces < forceLimit)) ||
|
|
(output->nbPatches && (output->contactPatches < patchLimit)))
|
|
{
|
|
output->nbContacts = 0;
|
|
output->nbPatches = 0;
|
|
output->contactForces = NULL;
|
|
output->contactPatches = NULL;
|
|
output->contactPoints = NULL;
|
|
}
|
|
}
|
|
|
|
if (contactsOverflown)
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Contact buffer overflow detected, please increase its size in the scene desc!\n");
|
|
else if (patchesOverflown)
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Patch buffer overflow detected, please increase its size in the scene desc!\n");
|
|
else if (forcesOverflown)
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Force buffer overflow detected, please increase its size in the scene desc!\n");
|
|
|
|
}
|
|
|
|
//mGpuNarrowphaseCore->appendContactManagers(mContext.getEventProfiler(), outputs, mNbFallbackPairs);
|
|
|
|
//mContactManagerOutputs.unmap();
|
|
//mGpuNarrowphaseCore->appendContactManagersConvexTriMesh(mContext.getEventProfiler());
|
|
//mGpuNarrowphaseCore->waitAndResetCopyQueues();
|
|
|
|
processResults();
|
|
mContext.getCudaContextManager()->releaseContext();
|
|
}
|
|
|
|
PxsContactManagerOutput* PxgNphaseImplementationContext::getGPUContactManagerOutputBase()
|
|
{
|
|
return mGpuNarrowphaseCore->getGPUContactManagerOutputBase();
|
|
}
|
|
|
|
PxReal* PxgNphaseImplementationContext::getGPURestDistances()
|
|
{
|
|
return mGpuNarrowphaseCore->getGPURestDistances();
|
|
}
|
|
Sc::ShapeInteraction** PxgNphaseImplementationContext::getGPUShapeInteractions()
|
|
{
|
|
return mGpuNarrowphaseCore->getGPUShapeInteractions();
|
|
}
|
|
|
|
PxsTorsionalFrictionData* PxgNphaseImplementationContext::getGPUTorsionalData()
|
|
{
|
|
return mGpuNarrowphaseCore->getGPUTorsionalData();
|
|
}
|
|
|
|
static void prepGpuContactManagerOutput(PxsContactManagerOutput& output, const PxcNpWorkUnit& workUnit, PxU32 patchCount, PxI32 touching)
|
|
{
|
|
output.nbPatches = PxTo8(patchCount);
|
|
output.prevPatches = 0;
|
|
output.nbContacts = 0;
|
|
output.contactForces = NULL;
|
|
output.contactPatches = NULL;
|
|
output.contactPoints = NULL;
|
|
output.frictionPatches = NULL;
|
|
output.flags = workUnit.mFlags;
|
|
|
|
PxU8 statusFlag = 0;
|
|
|
|
if(workUnit.mFlags & PxcNpWorkUnitFlag::eOUTPUT_CONSTRAINTS)
|
|
statusFlag |= PxsContactManagerStatusFlag::eREQUEST_CONSTRAINTS;
|
|
|
|
const bool staticOrKinematic = workUnit.mFlags & PxcNpWorkUnitFlag::eHAS_KINEMATIC_ACTOR ||
|
|
!(workUnit.mFlags & (PxcNpWorkUnitFlag::eDYNAMIC_BODY0 | PxcNpWorkUnitFlag::eDYNAMIC_BODY1 | PxcNpWorkUnitFlag::eSOFT_BODY));
|
|
|
|
//This flag is used by the particle system to figure out whether it can output simple or complex (2-way) collision structures
|
|
if (staticOrKinematic)
|
|
statusFlag |= PxsContactManagerStatusFlag::eSTATIC_OR_KINEMATIC;
|
|
|
|
if (touching > 0)
|
|
{
|
|
statusFlag |= PxsContactManagerStatusFlag::eHAS_TOUCH;
|
|
}
|
|
else if (touching < 0)
|
|
{
|
|
statusFlag |= PxsContactManagerStatusFlag::eHAS_NO_TOUCH;
|
|
}
|
|
|
|
output.statusFlag = statusFlag;
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::preallocateNewBuffers(PxU32 nbNewPairs, PxU32 maxIndex)
|
|
{
|
|
if (maxIndex >= mGpuContactManagerBitMap[0].size())
|
|
{
|
|
PxU32 newSize = (2 * (maxIndex + 256));
|
|
for (PxU32 i = 0; i < GPU_BUCKET_ID::eCount; ++i)
|
|
{
|
|
mGpuContactManagerBitMap[i].resize(newSize);
|
|
}
|
|
}
|
|
|
|
mGpuNarrowphaseCore->preallocateNewBuffers(nbNewPairs);
|
|
}
|
|
|
|
static PX_FORCE_INLINE bool isDynamicMesh(const PxsShapeCore* shapeCore)
|
|
{
|
|
const PxGeometry& geom = shapeCore->mGeometry.getGeometry();
|
|
const Gu::TriangleMesh* mesh = static_cast<const Gu::TriangleMesh*>(static_cast<const PxTriangleMeshGeometry&>(geom).triangleMesh);
|
|
return mesh->getSdfDataFast().mSdf != NULL;
|
|
}
|
|
|
|
static PX_FORCE_INLINE bool isGpuMesh(PxgGpuNarrowphaseCore* narrowPhaseCore, const PxsShapeCore* shapeCore)
|
|
{
|
|
const PxGeometry& geom = shapeCore->mGeometry.getGeometry();
|
|
return narrowPhaseCore->isMeshGPUCompatible(static_cast<const PxTriangleMeshGeometryLL&>(geom));
|
|
}
|
|
|
|
PX_FORCE_INLINE void PxgNphaseImplementationContext::registerContactManagerInternal(PxsContactManager* cm, const PxcNpWorkUnit& workUnit, PxU32 patchCount,
|
|
PxI32 touching, const Sc::ShapeInteraction* shapeInteraction, GPU_BUCKET_ID::Enum bucketId)
|
|
{
|
|
PxsContactManagerOutput output;
|
|
prepGpuContactManagerOutput(output, workUnit, patchCount, touching);
|
|
|
|
mGpuNarrowphaseCore->registerContactManager(cm, shapeInteraction, output, bucketId);
|
|
|
|
mGpuContactManagerBitMap[bucketId].set(cm->getIndex());
|
|
mNbPairCount[bucketId]++;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
// PT: using a struct to limit the amount of refactoring when we add a parameter, and the amount of PX_UNUSED we have to write.
|
|
// For now we don't try to be clever, we just pass all that data to all the functions.
|
|
struct gNpParams
|
|
{
|
|
PxgGpuNarrowphaseCore* mGpuNPCore;
|
|
const PxsShapeCore* mShapeCore0;
|
|
const PxsShapeCore* mShapeCore1;
|
|
PxGeometryType::Enum mType0;
|
|
PxGeometryType::Enum mType1;
|
|
bool mIsRigid0;
|
|
bool mIsRigid1;
|
|
|
|
PX_FORCE_INLINE bool isMeshGPUCompatible0() const
|
|
{
|
|
return mGpuNPCore->isMeshGPUCompatible(mShapeCore0->mGeometry.get<const PxTriangleMeshGeometryLL>());
|
|
}
|
|
|
|
PX_FORCE_INLINE bool isMeshGPUCompatible1() const
|
|
{
|
|
return mGpuNPCore->isMeshGPUCompatible(mShapeCore1->mGeometry.get<const PxTriangleMeshGeometryLL>());
|
|
}
|
|
};
|
|
}
|
|
|
|
static PX_FORCE_INLINE bool isConvexCoreGpuCompatible(const PxsShapeCore* shapeCore)
|
|
{
|
|
return Gu::isGPUCompatible(shapeCore->mGeometry.get<const PxConvexCoreGeometry>());
|
|
}
|
|
|
|
static PX_FORCE_INLINE bool isConvexGpuCompatible(const PxsShapeCore* shapeCore)
|
|
{
|
|
return shapeCore->mGeometry.get<const PxConvexMeshGeometryLL>().gpuCompatible;
|
|
}
|
|
|
|
typedef GPU_BUCKET_ID::Enum (*internalMethod)(const gNpParams&);
|
|
|
|
// PT: generic function when the pair of types unconditionally maps to a bucket
|
|
static PX_FORCE_INLINE GPU_BUCKET_ID::Enum bucket(const gNpParams&, GPU_BUCKET_ID::Enum id)
|
|
{
|
|
return id;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCasePlaneConvexCore(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0 == PxGeometryType::ePLANE);
|
|
PX_ASSERT(p.mType1 == PxGeometryType::eCONVEXCORE);
|
|
|
|
if (isConvexCoreGpuCompatible(p.mShapeCore1))
|
|
return GPU_BUCKET_ID::eConvexCorePlane;
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
// PT: then conditional functions where things aren't so simple
|
|
|
|
static GPU_BUCKET_ID::Enum cndCasePlaneConvex(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::ePLANE);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eCONVEXMESH);
|
|
|
|
if(isConvexGpuCompatible(p.mShapeCore1))
|
|
return GPU_BUCKET_ID::eConvexPlane;
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCasePrimitiveConvex(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0<=PxGeometryType::eCONVEXMESH);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eCONVEXMESH);
|
|
|
|
const bool isShape0Primitive = (p.mShapeCore0->mGeometry.getType() < PxGeometryType::eCONVEXMESH);
|
|
const bool isShape0GpuCompatible = isShape0Primitive || isConvexGpuCompatible(p.mShapeCore0);
|
|
const bool isShape1GpuCompatible = isConvexGpuCompatible(p.mShapeCore1);
|
|
|
|
if(isShape0GpuCompatible && isShape1GpuCompatible)
|
|
return GPU_BUCKET_ID::eConvex;
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseConvexCoreConvex(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0 <= PxGeometryType::eCONVEXMESH && p.mType0 != PxGeometryType::ePLANE);
|
|
PX_ASSERT(p.mType1 <= PxGeometryType::eCONVEXMESH && p.mType1 != PxGeometryType::ePLANE);
|
|
|
|
if (p.mType0 == PxGeometryType::eCONVEXCORE && !isConvexCoreGpuCompatible(p.mShapeCore0))
|
|
return GPU_BUCKET_ID::eFallback;
|
|
|
|
if (p.mType1 == PxGeometryType::eCONVEXCORE && !isConvexCoreGpuCompatible(p.mShapeCore1))
|
|
return GPU_BUCKET_ID::eFallback;
|
|
|
|
if (p.mType1 == PxGeometryType::eCONVEXMESH && !isConvexGpuCompatible(p.mShapeCore1))
|
|
return GPU_BUCKET_ID::eFallback;
|
|
|
|
return GPU_BUCKET_ID::eConvexCoreConvex;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseConvexCoreTrimesh(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0 == PxGeometryType::eCONVEXCORE);
|
|
PX_ASSERT(p.mType1 == PxGeometryType::eTRIANGLEMESH);
|
|
|
|
if (!p.mIsRigid1) // a cloth
|
|
{
|
|
|
|
if (isConvexCoreGpuCompatible(p.mShapeCore0))
|
|
return GPU_BUCKET_ID::eConvexCoreClothmesh;
|
|
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Non-GPU-compatible convex core geometry is not able to collide with cloth.\n");
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
if (isConvexCoreGpuCompatible(p.mShapeCore0) && p.isMeshGPUCompatible1())
|
|
return GPU_BUCKET_ID::eConvexCoreTrimesh;
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseConvexCoreHeightfield(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0 == PxGeometryType::eCONVEXCORE);
|
|
PX_ASSERT(p.mType1 == PxGeometryType::eHEIGHTFIELD);
|
|
|
|
PX_UNUSED(p);
|
|
//if (isConvexCoreGpuCompatible(p.mShapeCore0) && p.isMeshGPUCompatible1())
|
|
// return GPU_BUCKET_ID::eConvexCoreHeightfield;
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseConvexCoreTetra(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0 == PxGeometryType::eCONVEXCORE);
|
|
PX_ASSERT(p.mType1 == PxGeometryType::eTETRAHEDRONMESH);
|
|
|
|
if (isConvexCoreGpuCompatible(p.mShapeCore0))
|
|
return GPU_BUCKET_ID::eConvexCoreTetmesh;
|
|
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Non-GPU-compatible convex core geometry is not able to collide with deformable volume tetrahedron mesh.\n");
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseConvexCoreParticle(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0 == PxGeometryType::eCONVEXCORE);
|
|
PX_ASSERT(p.mType1 == PxGeometryType::ePARTICLESYSTEM);
|
|
|
|
if (isConvexCoreGpuCompatible(p.mShapeCore0))
|
|
return GPU_BUCKET_ID::eParticlesystems;
|
|
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Non-GPU-compatible convex core geometry is not able to collide with particle system.\n");
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseConvexCoreNotImplemented(const gNpParams& p)
|
|
{
|
|
PX_UNUSED(p);
|
|
PX_ASSERT(p.mType0 == PxGeometryType::eCONVEXCORE || p.mType1 == PxGeometryType::eCONVEXCORE);
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Not implemented yet.\n");
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseSphereMesh(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::eSPHERE);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eTRIANGLEMESH);
|
|
|
|
const bool isCloth1 = !p.mIsRigid1;
|
|
if(isCloth1)
|
|
return GPU_BUCKET_ID::eFemClothSphere;
|
|
|
|
if(p.isMeshGPUCompatible1())
|
|
return GPU_BUCKET_ID::eSphereTrimesh;
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCasePlaneMesh(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::ePLANE);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eTRIANGLEMESH);
|
|
|
|
const bool isCloth1 = !p.mIsRigid1;
|
|
return isCloth1 ? GPU_BUCKET_ID::eFemClothPlane : GPU_BUCKET_ID::eTrianglePlane;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseCapsuleMesh(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::eCAPSULE);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eTRIANGLEMESH);
|
|
|
|
const bool isCloth1 = !p.mIsRigid1;
|
|
if(isCloth1)
|
|
return GPU_BUCKET_ID::eFemClothSphere;
|
|
|
|
if(p.isMeshGPUCompatible1())
|
|
return GPU_BUCKET_ID::eSphereTrimesh;
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseBoxMesh(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::eBOX);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eTRIANGLEMESH);
|
|
|
|
const bool isCloth1 = !p.mIsRigid1;
|
|
if(isCloth1)
|
|
return GPU_BUCKET_ID::eFemClothBox;
|
|
|
|
if(p.isMeshGPUCompatible1())
|
|
return GPU_BUCKET_ID::eConvexTrimesh;
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseConvexMesh(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::eCONVEXMESH);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eTRIANGLEMESH);
|
|
|
|
const bool type0supported = isConvexGpuCompatible(p.mShapeCore0);
|
|
const bool isCloth1 = !p.mIsRigid1;
|
|
if(isCloth1)
|
|
{
|
|
if (type0supported)
|
|
{
|
|
return GPU_BUCKET_ID::eFemClothConvexes;
|
|
}
|
|
else
|
|
{
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Non-GPU-compatible convex mesh is not able to collide with cloth.\n");
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
}
|
|
|
|
if(type0supported && p.isMeshGPUCompatible1())
|
|
return GPU_BUCKET_ID::eConvexTrimesh;
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static PX_FORCE_INLINE GPU_BUCKET_ID::Enum cndCaseMeshMesh(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::eTRIANGLEMESH);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eTRIANGLEMESH);
|
|
|
|
// PT: TODO: this returns true if a SDF is present, which is a bit confusing - can't we use SDFs for static meshes?
|
|
const bool isDynamic0 = isDynamicMesh(p.mShapeCore0);
|
|
const bool isDynamic1 = isDynamicMesh(p.mShapeCore1);
|
|
|
|
const bool isRigidBodyMesh0 = p.mIsRigid0 && isGpuMesh(p.mGpuNPCore, p.mShapeCore0);
|
|
const bool isRigidBodyMesh1 = p.mIsRigid1 && isGpuMesh(p.mGpuNPCore, p.mShapeCore1);
|
|
|
|
const bool isValidTriTriPair = isRigidBodyMesh0 && isRigidBodyMesh1 && (isDynamic0 || isDynamic1);
|
|
if(isValidTriTriPair)
|
|
return GPU_BUCKET_ID::eTriangleTriangle;
|
|
|
|
/////
|
|
|
|
const bool isCloth0 = !p.mIsRigid0;
|
|
const bool isCloth1 = !p.mIsRigid1;
|
|
if(isCloth0 && isCloth1)
|
|
return GPU_BUCKET_ID::eFemClothes;
|
|
|
|
/////
|
|
|
|
if(isCloth1)
|
|
{
|
|
const bool isRigidBodySDFMesh0 = isRigidBodyMesh0 && isDynamic0;
|
|
if(isRigidBodySDFMesh0)
|
|
return GPU_BUCKET_ID::eFemClothSdfTrimesh;
|
|
}
|
|
|
|
if(isCloth0)
|
|
{
|
|
const bool isRigidBodySDFMesh1 = isRigidBodyMesh1 && isDynamic1;
|
|
if(isRigidBodySDFMesh1)
|
|
return GPU_BUCKET_ID::eFemClothSdfTrimesh;
|
|
}
|
|
|
|
/////
|
|
|
|
// PT: TODO: copied from original code, maybe could be simplified
|
|
if((!isCloth0 && isCloth1) || (!isCloth1 && isCloth0))
|
|
{
|
|
if((!isCloth0 && p.mGpuNPCore->isClothMeshGPUCompatible(p.mShapeCore1->mGeometry.get<const PxTriangleMeshGeometryLL>())) ||
|
|
(!isCloth1 && p.mGpuNPCore->isClothMeshGPUCompatible(p.mShapeCore0->mGeometry.get<const PxTriangleMeshGeometryLL>())))
|
|
{
|
|
return GPU_BUCKET_ID::eFemClothTrimesh;
|
|
}
|
|
else
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Non-GPU-compatible triangle mesh is not able to collide with cloth.\n");
|
|
}
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static PX_FORCE_INLINE GPU_BUCKET_ID::Enum cndCaseMeshCustom(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::eTRIANGLEMESH);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eCUSTOM);
|
|
|
|
const bool isCloth0 = !p.mIsRigid0;
|
|
|
|
//Cloth currently cannot collide against a custom geometry - there is a filter in filterRbCollisionPairShared
|
|
PX_ASSERT(!isCloth0);
|
|
PX_UNUSED(isCloth0);
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseConvexHeightfield(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::eCONVEXMESH);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eHEIGHTFIELD);
|
|
|
|
if(isConvexGpuCompatible(p.mShapeCore0))
|
|
return GPU_BUCKET_ID::eConvexHeightfield;
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCasePrimitiveParticle(const gNpParams& p)
|
|
{
|
|
PX_UNUSED(p);
|
|
PX_ASSERT(p.mType0<PxGeometryType::eCONVEXMESH);
|
|
PX_ASSERT(p.mType1==PxGeometryType::ePARTICLESYSTEM);
|
|
return GPU_BUCKET_ID::eParticlesystems;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseConvexParticle(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::eCONVEXMESH);
|
|
PX_ASSERT(p.mType1==PxGeometryType::ePARTICLESYSTEM);
|
|
|
|
if(isConvexGpuCompatible(p.mShapeCore0))
|
|
return GPU_BUCKET_ID::eConvexParticle;
|
|
else
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Non-GPU-compatible convex mesh is not able to collide with particle system.\n");
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseParticleTetra(const gNpParams& p)
|
|
{
|
|
PX_UNUSED(p);
|
|
PX_ASSERT(p.mType0==PxGeometryType::ePARTICLESYSTEM);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eTETRAHEDRONMESH);
|
|
return GPU_BUCKET_ID::eParticlesystemSoftbody;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseParticleMesh(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::ePARTICLESYSTEM);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eTRIANGLEMESH);
|
|
|
|
// PT: copied from original code but don't ask me
|
|
const bool isRigidBodyMesh = p.mIsRigid1 && isGpuMesh(p.mGpuNPCore, p.mShapeCore1);
|
|
const bool isRigidBodySDFMesh = isRigidBodyMesh && isDynamicMesh(p.mShapeCore1);
|
|
|
|
if(p.mGpuNPCore->isClothMeshGPUCompatible(p.mShapeCore1->mGeometry.get<const PxTriangleMeshGeometryLL>()))
|
|
{
|
|
GPU_BUCKET_ID::Enum bucketId = GPU_BUCKET_ID::eParticlesystemFemCloth;
|
|
const bool isCloth1 = !p.mIsRigid1;
|
|
if(isCloth1)
|
|
bucketId = GPU_BUCKET_ID::eParticlesystemFemCloth;
|
|
else if (p.mShapeCore1->mGeometry.get<const PxTriangleMeshGeometryLL>().materialsLL.numIndices <= 1) // rigid body
|
|
{
|
|
if (isRigidBodySDFMesh)
|
|
bucketId = GPU_BUCKET_ID::eParticlesystemSdfTrimesh;
|
|
else
|
|
bucketId = GPU_BUCKET_ID::eParticlesystemTrimesh;
|
|
}
|
|
return bucketId;
|
|
}
|
|
else
|
|
{
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Non-GPU-compatible triangle mesh is not able to collide with particle system.\n");
|
|
}
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseParticleCustom(const gNpParams& p)
|
|
{
|
|
PX_UNUSED(p);
|
|
PX_ASSERT(p.mType0==PxGeometryType::ePARTICLESYSTEM);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eCUSTOM);
|
|
//Error message already generated in filterRbCollisionPairShared
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseConvexTetra(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::eCONVEXMESH);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eTETRAHEDRONMESH);
|
|
|
|
if(!isConvexGpuCompatible(p.mShapeCore0))
|
|
{
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Non-GPU-compatible convex mesh is not able to collide with deformable volume tetrahedron mesh.\n");
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
return GPU_BUCKET_ID::eSoftbody;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseTetraMesh(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::eTETRAHEDRONMESH);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eTRIANGLEMESH);
|
|
|
|
const bool isRigidBodyMesh = p.mIsRigid1 && isGpuMesh(p.mGpuNPCore, p.mShapeCore1);
|
|
const bool isRigidBodySDFMesh = isRigidBodyMesh && isDynamicMesh(p.mShapeCore1);
|
|
|
|
if(p.mGpuNPCore->isClothMeshGPUCompatible(p.mShapeCore1->mGeometry.get<const PxTriangleMeshGeometryLL>()))
|
|
{
|
|
const bool isCloth1 = !p.mIsRigid1;
|
|
if(isCloth1)
|
|
{
|
|
return GPU_BUCKET_ID::eSoftbodyFemCloth;
|
|
}
|
|
else if(p.mShapeCore1->mGeometry.get<const PxTriangleMeshGeometryLL>().materialsLL.numIndices <= 1) // rigid body
|
|
{
|
|
if (isRigidBodySDFMesh)
|
|
return GPU_BUCKET_ID::eSoftbodySdfTrimesh;
|
|
else
|
|
return GPU_BUCKET_ID::eSoftbodyTrimesh;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "Non-GPU-compatible triangle mesh is not able to collide with deformable volume tetrahedron mesh.\n");
|
|
}
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseTetraCustom(const gNpParams& p)
|
|
{
|
|
PX_UNUSED(p);
|
|
PX_ASSERT(p.mType0==PxGeometryType::eTETRAHEDRONMESH);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eCUSTOM);
|
|
//Error message already generated in filterRbCollisionPairShared
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum cndCaseMeshHeightfield(const gNpParams& p)
|
|
{
|
|
PX_ASSERT(p.mType0==PxGeometryType::eTRIANGLEMESH);
|
|
PX_ASSERT(p.mType1==PxGeometryType::eHEIGHTFIELD);
|
|
|
|
const bool isCloth0 = !p.mIsRigid0;
|
|
if(isCloth0)
|
|
return GPU_BUCKET_ID::eFemClothHeightfield;
|
|
|
|
return GPU_BUCKET_ID::eFallback;
|
|
}
|
|
|
|
static GPU_BUCKET_ID::Enum caseSphereSphere(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSphere); }
|
|
static GPU_BUCKET_ID::Enum caseSpherePlane(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSphere); }
|
|
static GPU_BUCKET_ID::Enum caseSphereCapsule(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSphere); }
|
|
static GPU_BUCKET_ID::Enum caseSphereBox(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSphere); }
|
|
static GPU_BUCKET_ID::Enum caseSphereConvex(const gNpParams& p) { return cndCasePrimitiveConvex(p); }
|
|
static GPU_BUCKET_ID::Enum caseSphereParticle(const gNpParams& p) { return cndCasePrimitiveParticle(p); }
|
|
static GPU_BUCKET_ID::Enum caseSphereTetra(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSoftbody); }
|
|
static GPU_BUCKET_ID::Enum caseSphereMesh(const gNpParams& p) { return cndCaseSphereMesh(p); }
|
|
static GPU_BUCKET_ID::Enum caseSphereHeightfield(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSphereHeightfield); }
|
|
static GPU_BUCKET_ID::Enum caseSphereCustom(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eFallback); }
|
|
|
|
static GPU_BUCKET_ID::Enum casePlanePlane(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eFallback); }
|
|
static GPU_BUCKET_ID::Enum casePlaneCapsule(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSphere); }
|
|
static GPU_BUCKET_ID::Enum casePlaneBox(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eConvexPlane); }
|
|
static GPU_BUCKET_ID::Enum casePlaneConvexCore(const gNpParams& p) { return cndCasePlaneConvexCore(p); }
|
|
static GPU_BUCKET_ID::Enum casePlaneConvex(const gNpParams& p) { return cndCasePlaneConvex(p); }
|
|
static GPU_BUCKET_ID::Enum casePlaneParticle(const gNpParams& p) { return cndCasePrimitiveParticle(p); }
|
|
static GPU_BUCKET_ID::Enum casePlaneTetra(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSoftbody); }
|
|
static GPU_BUCKET_ID::Enum casePlaneMesh(const gNpParams& p) { return cndCasePlaneMesh(p); }
|
|
static GPU_BUCKET_ID::Enum casePlaneHeightfield(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eFallback); }
|
|
static GPU_BUCKET_ID::Enum casePlaneCustom(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eFallback); }
|
|
|
|
static GPU_BUCKET_ID::Enum caseCapsuleCapsule(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSphere); }
|
|
static GPU_BUCKET_ID::Enum caseCapsuleBox(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eConvex); }
|
|
static GPU_BUCKET_ID::Enum caseCapsuleConvex(const gNpParams& p) { return cndCasePrimitiveConvex(p); }
|
|
static GPU_BUCKET_ID::Enum caseCapsuleParticle(const gNpParams& p) { return cndCasePrimitiveParticle(p); }
|
|
static GPU_BUCKET_ID::Enum caseCapsuleTetra(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSoftbody); }
|
|
static GPU_BUCKET_ID::Enum caseCapsuleMesh(const gNpParams& p) { return cndCaseCapsuleMesh(p); }
|
|
static GPU_BUCKET_ID::Enum caseCapsuleHeightfield(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSphereHeightfield); }
|
|
static GPU_BUCKET_ID::Enum caseCapsuleCustom(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eFallback); }
|
|
|
|
static GPU_BUCKET_ID::Enum caseBoxBox(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eBoxBox); }
|
|
static GPU_BUCKET_ID::Enum caseBoxConvex(const gNpParams& p) { return cndCasePrimitiveConvex(p); }
|
|
static GPU_BUCKET_ID::Enum caseBoxParticle(const gNpParams& p) { return cndCasePrimitiveParticle(p); }
|
|
static GPU_BUCKET_ID::Enum caseBoxTetra(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSoftbody); }
|
|
static GPU_BUCKET_ID::Enum caseBoxMesh(const gNpParams& p) { return cndCaseBoxMesh(p); }
|
|
static GPU_BUCKET_ID::Enum caseBoxHeightfield(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eConvexHeightfield); }
|
|
static GPU_BUCKET_ID::Enum caseBoxCustom(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eFallback); }
|
|
|
|
static GPU_BUCKET_ID::Enum caseConvexCoreConvex(const gNpParams& p) { return cndCaseConvexCoreConvex(p); }
|
|
static GPU_BUCKET_ID::Enum caseConvexCoreTrimesh(const gNpParams& p) { return cndCaseConvexCoreTrimesh(p); }
|
|
static GPU_BUCKET_ID::Enum caseConvexCoreHeightfield(const gNpParams& p){ return cndCaseConvexCoreHeightfield(p); }
|
|
static GPU_BUCKET_ID::Enum caseConvexCoreTetra(const gNpParams& p) { return cndCaseConvexCoreTetra(p); }
|
|
static GPU_BUCKET_ID::Enum caseConvexCoreParticle(const gNpParams& p) { return cndCaseConvexCoreParticle(p); }
|
|
static GPU_BUCKET_ID::Enum caseConvexCoreNotImplemented(const gNpParams& p){ return cndCaseConvexCoreNotImplemented(p); }
|
|
|
|
static GPU_BUCKET_ID::Enum caseConvexConvex(const gNpParams& p) { return cndCasePrimitiveConvex(p); }
|
|
static GPU_BUCKET_ID::Enum caseConvexParticle(const gNpParams& p) { return cndCaseConvexParticle(p); }
|
|
static GPU_BUCKET_ID::Enum caseConvexTetra(const gNpParams& p) { return cndCaseConvexTetra(p); }
|
|
static GPU_BUCKET_ID::Enum caseConvexMesh(const gNpParams& p) { return cndCaseConvexMesh(p); }
|
|
static GPU_BUCKET_ID::Enum caseConvexHeightfield(const gNpParams& p) { return cndCaseConvexHeightfield(p); }
|
|
static GPU_BUCKET_ID::Enum caseConvexCustom(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eFallback); }
|
|
|
|
static GPU_BUCKET_ID::Enum caseParticleParticle(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eFallback); }
|
|
static GPU_BUCKET_ID::Enum caseParticleTetra(const gNpParams& p) { return cndCaseParticleTetra(p); }
|
|
static GPU_BUCKET_ID::Enum caseParticleMesh(const gNpParams& p) { return cndCaseParticleMesh(p); }
|
|
static GPU_BUCKET_ID::Enum caseParticleHeightfield(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eParticlesystemHeightfield); }
|
|
static GPU_BUCKET_ID::Enum caseParticleCustom(const gNpParams& p) { return cndCaseParticleCustom(p); }
|
|
|
|
static GPU_BUCKET_ID::Enum caseTetraTetra(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSoftbodies); }
|
|
static GPU_BUCKET_ID::Enum caseTetraMesh(const gNpParams& p) { return cndCaseTetraMesh(p); }
|
|
static GPU_BUCKET_ID::Enum caseTetraHeightfield(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eSoftbodyHeightfield); }
|
|
static GPU_BUCKET_ID::Enum caseTetraCustom(const gNpParams& p) { return cndCaseTetraCustom(p); }
|
|
|
|
static GPU_BUCKET_ID::Enum caseMeshMesh(const gNpParams& p) { return cndCaseMeshMesh(p); }
|
|
static GPU_BUCKET_ID::Enum caseMeshHeightfield(const gNpParams& p) { return cndCaseMeshHeightfield(p); }
|
|
static GPU_BUCKET_ID::Enum caseMeshCustom(const gNpParams& p) { return cndCaseMeshCustom(p); }
|
|
|
|
static GPU_BUCKET_ID::Enum caseHeightfieldHeightfield(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eFallback); }
|
|
static GPU_BUCKET_ID::Enum caseHeightfieldCustom(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eFallback); }
|
|
|
|
static GPU_BUCKET_ID::Enum caseCustomCustom(const gNpParams& p) { return bucket(p, GPU_BUCKET_ID::eFallback); }
|
|
|
|
static internalMethod gTable[][PxGeometryType::eGEOMETRY_COUNT] =
|
|
{
|
|
//PxGeometryType::eSPHERE
|
|
{
|
|
caseSphereSphere, //PxGeometryType::eSPHERE
|
|
caseSpherePlane, //PxGeometryType::ePLANE
|
|
caseSphereCapsule, //PxGeometryType::eCAPSULE
|
|
caseSphereBox, //PxGeometryType::eBOX
|
|
caseConvexCoreConvex, //PxGeometryType::eCONVEXCORE
|
|
caseSphereConvex, //PxGeometryType::eCONVEXMESH
|
|
caseSphereParticle, //PxGeometryType::ePARTICLESYSTEM
|
|
caseSphereTetra, //PxGeometryType::eTETRAHEDRONMESH
|
|
caseSphereMesh, //PxGeometryType::eTRIANGLEMESH
|
|
caseSphereHeightfield, //PxGeometryType::eHEIGHTFIELD
|
|
caseSphereCustom, //PxGeometryType::eCUSTOM
|
|
},
|
|
|
|
//PxGeometryType::ePLANE
|
|
{
|
|
NULL, //PxGeometryType::eSPHERE
|
|
casePlanePlane, //PxGeometryType::ePLANE
|
|
casePlaneCapsule, //PxGeometryType::eCAPSULE
|
|
casePlaneBox, //PxGeometryType::eBOX
|
|
casePlaneConvexCore, //PxGeometryType::eCONVEXCORE
|
|
casePlaneConvex, //PxGeometryType::eCONVEXMESH
|
|
casePlaneParticle, //PxGeometryType::ePARTICLESYSTEM
|
|
casePlaneTetra, //PxGeometryType::eTETRAHEDRONMESH
|
|
casePlaneMesh, //PxGeometryType::eTRIANGLEMESH
|
|
casePlaneHeightfield, //PxGeometryType::eHEIGHTFIELD
|
|
casePlaneCustom, //PxGeometryType::eCUSTOM
|
|
},
|
|
|
|
//PxGeometryType::eCAPSULE
|
|
{
|
|
NULL, //PxGeometryType::eSPHERE
|
|
NULL, //PxGeometryType::ePLANE
|
|
caseCapsuleCapsule, //PxGeometryType::eCAPSULE
|
|
caseCapsuleBox, //PxGeometryType::eBOX
|
|
caseConvexCoreConvex, //PxGeometryType::eCONVEXCORE
|
|
caseCapsuleConvex, //PxGeometryType::eCONVEXMESH
|
|
caseCapsuleParticle, //PxGeometryType::ePARTICLESYSTEM
|
|
caseCapsuleTetra, //PxGeometryType::eTETRAHEDRONMESH
|
|
caseCapsuleMesh, //PxGeometryType::eTRIANGLEMESH
|
|
caseCapsuleHeightfield, //PxGeometryType::eHEIGHTFIELD
|
|
caseCapsuleCustom, //PxGeometryType::eCUSTOM
|
|
},
|
|
|
|
//PxGeometryType::eBOX
|
|
{
|
|
NULL, //PxGeometryType::eSPHERE
|
|
NULL, //PxGeometryType::ePLANE
|
|
NULL, //PxGeometryType::eCAPSULE
|
|
caseBoxBox, //PxGeometryType::eBOX
|
|
caseConvexCoreConvex,//PxGeometryType::eCONVEXCORE
|
|
caseBoxConvex, //PxGeometryType::eCONVEXMESH
|
|
caseBoxParticle, //PxGeometryType::ePARTICLESYSTEM
|
|
caseBoxTetra, //PxGeometryType::eTETRAHEDRONMESH
|
|
caseBoxMesh, //PxGeometryType::eTRIANGLEMESH
|
|
caseBoxHeightfield, //PxGeometryType::eHEIGHTFIELD
|
|
caseBoxCustom, //PxGeometryType::eCUSTOM
|
|
},
|
|
|
|
//PxGeometryType::eCONVEXCORE
|
|
{
|
|
NULL, //PxGeometryType::eSPHERE
|
|
NULL, //PxGeometryType::ePLANE
|
|
NULL, //PxGeometryType::eCAPSULE
|
|
NULL, //PxGeometryType::eBOX
|
|
caseConvexCoreConvex, //PxGeometryType::eCONVEXCORE
|
|
caseConvexCoreConvex, //PxGeometryType::eCONVEXMESH
|
|
caseConvexCoreParticle, //PxGeometryType::ePARTICLESYSTEM
|
|
caseConvexCoreTetra, //PxGeometryType::eTETRAHEDRONMESH
|
|
caseConvexCoreTrimesh, //PxGeometryType::eTRIANGLEMESH
|
|
caseConvexCoreHeightfield, //PxGeometryType::eHEIGHTFIELD
|
|
caseConvexCoreNotImplemented,//PxGeometryType::eCUSTOM
|
|
},
|
|
|
|
//PxGeometryType::eCONVEXMESH
|
|
{
|
|
NULL, //PxGeometryType::eSPHERE
|
|
NULL, //PxGeometryType::ePLANE
|
|
NULL, //PxGeometryType::eCAPSULE
|
|
NULL, //PxGeometryType::eBOX
|
|
NULL, //PxGeometryType::eCONVEXCORE
|
|
caseConvexConvex, //PxGeometryType::eCONVEXMESH
|
|
caseConvexParticle, //PxGeometryType::ePARTICLESYSTEM
|
|
caseConvexTetra, //PxGeometryType::eTETRAHEDRONMESH
|
|
caseConvexMesh, //PxGeometryType::eTRIANGLEMESH
|
|
caseConvexHeightfield, //PxGeometryType::eHEIGHTFIELD
|
|
caseConvexCustom, //PxGeometryType::eCUSTOM
|
|
},
|
|
|
|
//PxGeometryType::ePARTICLESYSTEM
|
|
{
|
|
NULL, //PxGeometryType::eSPHERE
|
|
NULL, //PxGeometryType::ePLANE
|
|
NULL, //PxGeometryType::eCAPSULE
|
|
NULL, //PxGeometryType::eBOX
|
|
NULL, //PxGeometryType::eCONVEXCORE
|
|
NULL, //PxGeometryType::eCONVEXMESH
|
|
caseParticleParticle, //PxGeometryType::ePARTICLESYSTEM
|
|
caseParticleTetra, //PxGeometryType::eTETRAHEDRONMESH
|
|
caseParticleMesh, //PxGeometryType::eTRIANGLEMESH
|
|
caseParticleHeightfield, //PxGeometryType::eHEIGHTFIELD
|
|
caseParticleCustom, //PxGeometryType::eCUSTOM
|
|
},
|
|
|
|
//PxGeometryType::eTETRAHEDRONMESH
|
|
{
|
|
NULL, //PxGeometryType::eSPHERE
|
|
NULL, //PxGeometryType::ePLANE
|
|
NULL, //PxGeometryType::eCAPSULE
|
|
NULL, //PxGeometryType::eBOX
|
|
NULL, //PxGeometryType::eCONVEXCORE
|
|
NULL, //PxGeometryType::eCONVEXMESH
|
|
NULL, //PxGeometryType::ePARTICLESYSTEM
|
|
caseTetraTetra, //PxGeometryType::eTETRAHEDRONMESH
|
|
caseTetraMesh, //PxGeometryType::eTRIANGLEMESH
|
|
caseTetraHeightfield, //PxGeometryType::eHEIGHTFIELD
|
|
caseTetraCustom, //PxGeometryType::eCUSTOM
|
|
},
|
|
|
|
//PxGeometryType::eTRIANGLEMESH
|
|
{
|
|
NULL, //PxGeometryType::eSPHERE
|
|
NULL, //PxGeometryType::ePLANE
|
|
NULL, //PxGeometryType::eCAPSULE
|
|
NULL, //PxGeometryType::eBOX
|
|
NULL, //PxGeometryType::eCONVEXCORE
|
|
NULL, //PxGeometryType::eCONVEXMESH
|
|
NULL, //PxGeometryType::ePARTICLESYSTEM
|
|
NULL, //PxGeometryType::eTETRAHEDRONMESH
|
|
caseMeshMesh, //PxGeometryType::eTRIANGLEMESH
|
|
caseMeshHeightfield, //PxGeometryType::eHEIGHTFIELD
|
|
caseMeshCustom, //PxGeometryType::eCUSTOM
|
|
},
|
|
|
|
//PxGeometryType::eHEIGHTFIELD
|
|
{
|
|
NULL, //PxGeometryType::eSPHERE
|
|
NULL, //PxGeometryType::ePLANE
|
|
NULL, //PxGeometryType::eCAPSULE
|
|
NULL, //PxGeometryType::eBOX
|
|
NULL, //PxGeometryType::eCONVEXCORE
|
|
NULL, //PxGeometryType::eCONVEXMESH
|
|
NULL, //PxGeometryType::ePARTICLESYSTEM
|
|
NULL, //PxGeometryType::eTETRAHEDRONMESH
|
|
NULL, //PxGeometryType::eTRIANGLEMESH
|
|
caseHeightfieldHeightfield, //PxGeometryType::eHEIGHTFIELD
|
|
caseHeightfieldCustom, //PxGeometryType::eCUSTOM
|
|
},
|
|
|
|
//PxGeometryType::eCUSTOM
|
|
{
|
|
NULL, //PxGeometryType::eSPHERE
|
|
NULL, //PxGeometryType::ePLANE
|
|
NULL, //PxGeometryType::eCAPSULE
|
|
NULL, //PxGeometryType::eBOX
|
|
NULL, //PxGeometryType::eCONVEXCORE
|
|
NULL, //PxGeometryType::eCONVEXMESH
|
|
NULL, //PxGeometryType::ePARTICLESYSTEM
|
|
NULL, //PxGeometryType::eTETRAHEDRONMESH
|
|
NULL, //PxGeometryType::eTRIANGLEMESH
|
|
NULL, //PxGeometryType::eHEIGHTFIELD
|
|
caseCustomCustom, //PxGeometryType::eCUSTOM
|
|
},
|
|
};
|
|
PX_COMPILE_TIME_ASSERT(sizeof(gTable) / sizeof(gTable[0]) == PxGeometryType::eGEOMETRY_COUNT);
|
|
|
|
void PxgNphaseImplementationContext::registerContactManager(PxsContactManager* cm, const Sc::ShapeInteraction* shapeInteraction, PxI32 touching, PxU32 patchCount)
|
|
{
|
|
mTotalNbPairs++;
|
|
|
|
if(cm->getIndex() >= mGpuContactManagerBitMap[0].size())
|
|
{
|
|
const PxU32 newSize = (2*cm->getIndex()+256)&~255;
|
|
for (PxU32 i = 0; i < GPU_BUCKET_ID::eCount; ++i)
|
|
{
|
|
mGpuContactManagerBitMap[i].resize(newSize);
|
|
}
|
|
}
|
|
|
|
///////////////////////////
|
|
|
|
PxcNpWorkUnit& workUnit = cm->getWorkUnit();
|
|
|
|
const PxsShapeCore* shapeCore0 = workUnit.getShapeCore0();
|
|
const PxsShapeCore* shapeCore1 = workUnit.getShapeCore1();
|
|
|
|
PX_ASSERT(shapeCore0);
|
|
PX_ASSERT(shapeCore1);
|
|
|
|
PxGeometryType::Enum type0 = shapeCore0->mGeometry.getType();
|
|
PxGeometryType::Enum type1 = shapeCore1->mGeometry.getType();
|
|
|
|
bool isRigid0 = workUnit.mRigidCore0 ? true : false;
|
|
bool isRigid1 = workUnit.mRigidCore1 ? true : false;
|
|
|
|
const bool flip = (type1 < type0);
|
|
if(flip)
|
|
{
|
|
PxSwap(type0, type1);
|
|
PxSwap(shapeCore0, shapeCore1);
|
|
PxSwap(isRigid0, isRigid1);
|
|
}
|
|
|
|
///////////////////////////
|
|
|
|
GPU_BUCKET_ID::Enum bucketId = GPU_BUCKET_ID::eFallback;
|
|
|
|
const bool hasModification = (workUnit.mFlags & PxcNpWorkUnitFlag::eMODIFIABLE_CONTACT) != 0;
|
|
const bool gpuCollision = mContext.getPCM() && !hasModification && PXG_ENABLE_GPU_NP && (workUnit.mFlags & PxcNpWorkUnitFlag::eDETECT_DISCRETE_CONTACT);
|
|
if(gpuCollision)
|
|
{
|
|
const internalMethod func = gTable[type0][type1];
|
|
PX_ASSERT(func);
|
|
|
|
gNpParams p;
|
|
p.mGpuNPCore = mGpuNarrowphaseCore;
|
|
p.mShapeCore0 = shapeCore0;
|
|
p.mShapeCore1 = shapeCore1;
|
|
p.mType0 = type0;
|
|
p.mType1 = type1;
|
|
p.mIsRigid0 = isRigid0;
|
|
p.mIsRigid1 = isRigid1;
|
|
bucketId = func(p);
|
|
}
|
|
|
|
if(bucketId!=GPU_BUCKET_ID::eFallback)
|
|
{
|
|
registerContactManagerInternal(cm, workUnit, patchCount, touching, shapeInteraction, bucketId);
|
|
}
|
|
else
|
|
{
|
|
mFallbackForUnsupportedCMs->registerContactManager(cm, shapeInteraction, touching, patchCount);
|
|
mGpuContactManagerBitMap[GPU_BUCKET_ID::eFallback].set(cm->getIndex());
|
|
mNbPairCount[GPU_BUCKET_ID::eFallback]++;
|
|
}
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::unregisterContactManager(PxsContactManager* cm)
|
|
{
|
|
mTotalNbPairs--;
|
|
|
|
if (mGpuContactManagerBitMap[0].test(cm->getIndex()))
|
|
{
|
|
mFallbackForUnsupportedCMs->unregisterContactManagerFallback(cm, mContactManagerOutputs.begin());
|
|
mGpuContactManagerBitMap[0].reset(cm->getIndex());
|
|
mNbPairCount[0]--;
|
|
}
|
|
else
|
|
{
|
|
for (PxU32 i = GPU_BUCKET_ID::eConvex; i < GPU_BUCKET_ID::eCount; ++i)
|
|
{
|
|
if (mGpuContactManagerBitMap[i].test(cm->getIndex()))
|
|
{
|
|
mGpuNarrowphaseCore->unregisterContactManager(cm, i);
|
|
mGpuContactManagerBitMap[i].reset(cm->getIndex());
|
|
mNbPairCount[i]--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::refreshContactManager(PxsContactManager* cm)
|
|
{
|
|
PxcNpWorkUnit& workUnit = cm->getWorkUnit();
|
|
PxgContactManagerInput input;
|
|
input.shapeRef0 = mGpuNarrowphaseCore->getShapeIndex(*workUnit.getShapeCore0());
|
|
input.shapeRef1 = mGpuNarrowphaseCore->getShapeIndex(*workUnit.getShapeCore1());
|
|
input.transformCacheRef0 = workUnit.mTransformCache0;
|
|
input.transformCacheRef1 = workUnit.mTransformCache1;
|
|
|
|
if (mGpuContactManagerBitMap[0].test(cm->getIndex()))
|
|
{
|
|
mFallbackForUnsupportedCMs->refreshContactManagerFallback(cm, mContactManagerOutputs.begin());
|
|
}
|
|
else
|
|
{
|
|
PxU32 offset = 0;
|
|
for (PxU32 i = GPU_BUCKET_ID::eConvex; i < GPU_BUCKET_ID::eCount; ++i)
|
|
{
|
|
offset += mRecordedGpuPairCount[i - 1];
|
|
if (mGpuContactManagerBitMap[i].test(cm->getIndex()))
|
|
{
|
|
mGpuNarrowphaseCore->refreshContactManager(cm, mContactManagerOutputs.begin() + offset, input, i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PxsContactManagerOutput& PxgNphaseImplementationContext::getNewContactManagerOutput(PxU32 npId)
|
|
{
|
|
PX_ASSERT(npId & PxsContactManagerBase::NEW_CONTACT_MANAGER_MASK);
|
|
|
|
PxU32 bucketId = PxsContactManagerBase::computeBucketIndexFromId(npId);
|
|
|
|
for (PxU32 i = GPU_BUCKET_ID::eConvex; i < GPU_BUCKET_ID::eTriangleTriangle; ++i)
|
|
{
|
|
PxgNewContactManagers& gpuManagers = mGpuNarrowphaseCore->getNewContactManagers(GPU_BUCKET_ID::Enum(i));
|
|
if(gpuManagers.mBucketId == bucketId)
|
|
return gpuManagers.mGpuOutputContactManagers[PxsContactManagerBase::computeIndexFromId(npId & (~PxsContactManagerBase::NEW_CONTACT_MANAGER_MASK))];
|
|
}
|
|
|
|
return mFallbackForUnsupportedCMs->getNewContactManagerOutput(npId);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::registerShape(const PxNodeIndex& nodeIndex, const PxsShapeCore& shapeCore, const PxU32 transformCacheID, PxActor* actor, const bool isFemCloth)
|
|
{
|
|
mGpuNarrowphaseCore->registerShape(nodeIndex, shapeCore, transformCacheID, isFemCloth, actor);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::updateShapeMaterial(const PxsShapeCore& shapeCore)
|
|
{
|
|
mGpuNarrowphaseCore->updateShapeMaterial(shapeCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::unregisterShape(const PxsShapeCore& shapeCore, const PxU32 transformCacheID, const bool isFemCloth)
|
|
{
|
|
mGpuNarrowphaseCore->unregisterShape(shapeCore, transformCacheID, isFemCloth);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::registerAggregate(const PxU32 transformCacheID)
|
|
{
|
|
mGpuNarrowphaseCore->registerAggregate(transformCacheID);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::registerMaterial(const PxsMaterialCore& materialCore)
|
|
{
|
|
mGpuNarrowphaseCore->registerMaterial(materialCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::updateMaterial(const PxsMaterialCore& materialCore)
|
|
{
|
|
mGpuNarrowphaseCore->updateMaterial(materialCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::unregisterMaterial(const PxsMaterialCore& materialCore)
|
|
{
|
|
mGpuNarrowphaseCore->unregisterMaterial(materialCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::registerMaterial(const PxsDeformableSurfaceMaterialCore& materialCore)
|
|
{
|
|
mGpuNarrowphaseCore->registerFEMMaterial(materialCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::updateMaterial(const PxsDeformableSurfaceMaterialCore& materialCore)
|
|
{
|
|
mGpuNarrowphaseCore->updateFEMMaterial(materialCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::unregisterMaterial(const PxsDeformableSurfaceMaterialCore& materialCore)
|
|
{
|
|
mGpuNarrowphaseCore->unregisterFEMMaterial(materialCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::registerMaterial(const PxsDeformableVolumeMaterialCore& materialCore)
|
|
{
|
|
mGpuNarrowphaseCore->registerFEMMaterial(materialCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::updateMaterial(const PxsDeformableVolumeMaterialCore& materialCore)
|
|
{
|
|
mGpuNarrowphaseCore->updateFEMMaterial(materialCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::unregisterMaterial(const PxsDeformableVolumeMaterialCore& materialCore)
|
|
{
|
|
mGpuNarrowphaseCore->unregisterFEMMaterial(materialCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::registerMaterial(const PxsPBDMaterialCore& materialCore)
|
|
{
|
|
mGpuNarrowphaseCore->registerParticleMaterial(materialCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::updateMaterial(const PxsPBDMaterialCore& materialCore)
|
|
{
|
|
mGpuNarrowphaseCore->updateParticleMaterial(materialCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::unregisterMaterial(const PxsPBDMaterialCore& materialCore)
|
|
{
|
|
mGpuNarrowphaseCore->unregisterParticleMaterial(materialCore);
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::startNarrowPhaseTasks()
|
|
{
|
|
PxU32 numContactManagers = 0;
|
|
for (PxU32 i = 0; i < GPU_BUCKET_ID::eCount; ++i)
|
|
{
|
|
numContactManagers += mGpuNarrowphaseCore->mContactManagers[i]->mContactManagers.mCpuContactManagerMapping.size();
|
|
}
|
|
|
|
if(numContactManagers > 0)
|
|
{
|
|
mGpuNarrowphaseCore->pushBuffer();
|
|
}
|
|
}
|
|
|
|
PxReal PxgNphaseImplementationContext::getToleranceLength()
|
|
{
|
|
return mContext.getToleranceLength();
|
|
}
|
|
|
|
PxsContactManagerOutputIterator PxgNphaseImplementationContext::getContactManagerOutputs()
|
|
{
|
|
PxU32 offsets[GPU_BUCKET_ID::eCount * 2];
|
|
|
|
PxU32 count = 0;
|
|
for (PxU32 i = 0; i < GPU_BUCKET_ID::eCount; ++i)
|
|
{
|
|
offsets[i] = count;
|
|
count += mRecordedGpuPairCount[i];
|
|
}
|
|
|
|
//Remove fallback pairs from the GPU indexing
|
|
offsets[GPU_BUCKET_ID::eCount] = count - mRecordedGpuPairCount[0];
|
|
|
|
count = 0;
|
|
for (PxU32 i = 1; i < GPU_BUCKET_ID::eCount; ++i)
|
|
{
|
|
offsets[GPU_BUCKET_ID::eCount+i] = count;
|
|
count += mRecordedGpuPairCount[i];
|
|
}
|
|
|
|
|
|
return PxsContactManagerOutputIterator(offsets, GPU_BUCKET_ID::eCount * 2, mContactManagerOutputs.begin());
|
|
}
|
|
|
|
void PxgNphaseImplementationContext::acquireContext() { mGpuNarrowphaseCore->acquireContext(); }
|
|
void PxgNphaseImplementationContext::releaseContext() { mGpuNarrowphaseCore->releaseContext(); }
|