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,599 @@
// 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 "PxvConfig.h"
#include "PxcContactCache.h"
#include "PxsRigidBody.h"
#include "PxsContactManager.h"
#include "PxsContext.h"
#include "PxPhysXConfig.h"
#include "foundation/PxBitMap.h"
#include "CmFlushPool.h"
#include "PxsMaterialManager.h"
#include "PxSceneDesc.h"
#include "PxsCCD.h"
#include "PxvGeometry.h"
#include "PxvManager.h"
#include "PxsSimpleIslandManager.h"
#if PX_SUPPORT_GPU_PHYSX
#include "PxPhysXGpu.h"
#endif
#include "PxcNpContactPrepShared.h"
#include "PxcNpCache.h"
using namespace physx;
PxsContext::PxsContext(const PxSceneDesc& desc, PxTaskManager* taskManager, Cm::FlushPool& taskPool, PxCudaContextManager* cudaContextManager, PxU32 poolSlabSize, PxU64 contextID) :
mNpThreadContextPool (this),
mContactManagerPool ("mContactManagerPool", poolSlabSize),
mManifoldPool ("mManifoldPool", poolSlabSize),
mSphereManifoldPool ("mSphereManifoldPool", poolSlabSize),
mContactModifyCallback (NULL),
mNpImplementationContext (NULL),
mNpFallbackImplementationContext(NULL),
mTaskManager (taskManager),
mTaskPool (taskPool),
mCudaContextManager (cudaContextManager),
mPCM (desc.flags & PxSceneFlag::eENABLE_PCM),
mContactCache (false),
mCreateAveragePoint (desc.flags & PxSceneFlag::eENABLE_AVERAGE_POINT),
mContextID (contextID)
{
clearManagerTouchEvents();
mVisualizationCullingBox.setEmpty();
PxMemZero(mVisualizationParams, sizeof(PxReal) * PxVisualizationParameter::eNUM_VALUES);
mNpMemBlockPool.init(desc.nbContactDataBlocks, desc.maxNbContactDataBlocks);
}
PxsContext::~PxsContext()
{
PX_DELETE(mTransformCache);
mContactManagerPool.destroy(); //manually destroy the contact manager pool, otherwise pool deletion order is random and we can get into trouble with references into other pools needed during destruction.
}
// =========================== Create methods
namespace physx
{
const bool gEnablePCMCaching[][PxGeometryType::eGEOMETRY_COUNT] =
{
//eSPHERE,
{
false, //eSPHERE
false, //ePLANE
false, //eCAPSULE
false, //eBOX
false, //eCONVEX
true, //eCONVEXMESH
false, //ePARTICLESYSTEM
true, //eSOFTBODY,
true, //eTRIANGLEMESH
true, //eHEIGHTFIELD
true, //eCUSTOM
},
//ePLANE
{
false, //eSPHERE
false, //ePLANE
true, //eCAPSULE
true, //eBOX
false, //eCONVEX
true, //eCONVEXMESH
false, //ePARTICLESYSTEM
true, //eSOFTBODY,
false, //eTRIANGLEMESH
false, //eHEIGHTFIELD
true, //eCUSTOM
},
//eCAPSULE,
{
false, //eSPHERE
true, //ePLANE
false, //eCAPSULE
true, //eBOX
false, //eCONVEX
true, //eCONVEXMESH
false, //ePARTICLESYSTEM
true, //eSOFTBODY,
true, //eTRIANGLEMESH
true, //eHEIGHTFIELD
true, //eCUSTOM
},
//eBOX,
{
false, //eSPHERE
true, //ePLANE
true, //eCAPSULE
true, //eBOX
false, //eCONVEX
true, //eCONVEXMESH
false, //ePARTICLESYSTEM
true, //eSOFTBODY,
true, //eTRIANGLEMESH
true, //eHEIGHTFIELD
true, //eCUSTOM
},
//eCONVEX,
{
false, //eSPHERE
false, //ePLANE
false, //eCAPSULE
false, //eBOX
false, //eCONVEX
false, //eCONVEXMESH
false, //ePARTICLESYSTEM
false, //eSOFTBODY,
false, //eTRIANGLEMESH
false, //eHEIGHTFIELD
false, //eCUSTOM
},
//eCONVEXMESH,
{
true, //eSPHERE
true, //ePLANE
true, //eCAPSULE
true, //eBOX
false, //eCONVEX
true, //eCONVEXMESH
false, //ePARTICLESYSTEM
true, //eSOFTBODY,
true, //eTRIANGLEMESH
true, //eHEIGHTFIELD
true, //eCUSTOM
},
//ePARTICLESYSTEM
{
false, //eSPHERE
false, //ePLANE
false, //eCAPSULE
false, //eBOX
false, //eCONVEX
false, //eCONVEXMESH
false, //ePARTICLESYSTEM
false, //eSOFTBODY,
false, //eTRIANGLEMESH
false, //eHEIGHTFIELD
false, //eCUSTOM
},
//eSOFTBODY
{
false, //eSPHERE
false, //ePLANE
false, //eCAPSULE
false, //eBOX
false, //eCONVEX
false, //eCONVEXMESH
false, //ePARTICLESYSTEM
false, //eSOFTBODY,
false, //eTRIANGLEMESH
false, //eHEIGHTFIELD
false, //eCUSTOM
},
//eTRIANGLEMESH,
{
true, //eSPHERE
false, //ePLANE
true, //eCAPSULE
true, //eBOX
false, //eCONVEX
true, //eCONVEXMESH
false, //ePARTICLESYSTEM
true, //eSOFTBODY,
false, //eTRIANGLEMESH
false, //eHEIGHTFIELD
true, //eCUSTOM
},
//eHEIGHTFIELD,
{
true, //eSPHERE
false, //ePLANE
true, //eCAPSULE
true, //eBOX
false, //eCONVEX
true, //eCONVEXMESH
false, //ePARTICLESYSTEM
true, //eSOFTBODY,
false, //eTRIANGLEMESH
false, //eHEIGHTFIELD
true, //eCUSTOM
},
//eCUSTOM,
{
true, //eSPHERE
true, //ePLANE
true, //eCAPSULE
true, //eBOX
false, //eCONVEX
true, //eCONVEXMESH
false, //ePARTICLESYSTEM
false, //eSOFTBODY,
true, //eTRIANGLEMESH
true, //eHEIGHTFIELD
true, //eCUSTOM
}
};
PX_COMPILE_TIME_ASSERT(sizeof(gEnablePCMCaching) / sizeof(gEnablePCMCaching[0]) == PxGeometryType::eGEOMETRY_COUNT);
}
void PxsContext::createTransformCache(PxVirtualAllocatorCallback& allocatorCallback)
{
mTransformCache = PX_NEW(PxsTransformCache)(allocatorCallback);
}
PxsContactManager* PxsContext::createContactManager(PxsContactManager* contactManager, bool useCCD)
{
PxsContactManager* cm = contactManager? contactManager : mContactManagerPool.get();
if(cm)
{
cm->getWorkUnit().clearCachedState();
if(!contactManager)
setActiveContactManager(cm, useCCD);
}
else
{
PX_WARN_ONCE("Reached limit of contact pairs.");
}
return cm;
}
void PxsContext::createCache(Gu::Cache& cache, PxGeometryType::Enum geomType0, PxGeometryType::Enum geomType1)
{
if(mPCM)
{
if(gEnablePCMCaching[geomType0][geomType1])
{
if(geomType0 <= PxGeometryType::eCONVEXMESH && geomType1 <= PxGeometryType::eCONVEXMESH)
{
if(geomType0 == PxGeometryType::eSPHERE || geomType1 == PxGeometryType::eSPHERE)
{
Gu::PersistentContactManifold* manifold = mSphereManifoldPool.allocate();
PX_PLACEMENT_NEW(manifold, Gu::SpherePersistentContactManifold());
cache.setManifold(manifold);
}
else
{
Gu::PersistentContactManifold* manifold = mManifoldPool.allocate();
PX_PLACEMENT_NEW(manifold, Gu::LargePersistentContactManifold());
cache.setManifold(manifold);
}
cache.getManifold().clearManifold();
}
else
{
//ML: raised 1 to indicate the manifold is multiManifold which is for contact gen in mesh/height field
//cache.manifold = 1;
cache.setMultiManifold(NULL);
}
}
else
{
//cache.manifold = 0;
cache.mCachedData = NULL;
cache.mManifoldFlags = 0;
}
}
}
void PxsContext::destroyContactManager(PxsContactManager* cm)
{
const PxU32 idx = cm->getIndex();
if(cm->getCCD())
mActiveContactManagersWithCCD.growAndReset(idx);
//mActiveContactManager.growAndReset(idx);
mContactManagerTouchEvent.growAndReset(idx);
mContactManagerPool.put(cm);
}
void PxsContext::destroyCache(Gu::Cache& cache)
{
if(cache.isManifold())
{
if(!cache.isMultiManifold())
{
Gu::PersistentContactManifold& manifold = cache.getManifold();
if(manifold.mCapacity == GU_SPHERE_MANIFOLD_CACHE_SIZE)
mSphereManifoldPool.deallocate(static_cast<Gu::SpherePersistentContactManifold*>(&manifold));
else
mManifoldPool.deallocate(static_cast<Gu::LargePersistentContactManifold*>(&manifold));
}
cache.mCachedData = NULL;
cache.mManifoldFlags = 0;
}
}
void PxsContext::setScratchBlock(void* addr, PxU32 size)
{
mScratchAllocator.setBlock(addr, size);
}
void PxsContext::shiftOrigin(const PxVec3& shift)
{
// transform cache
mTransformCache->shiftTransforms(-shift);
#if 0
if (getContactCacheFlag())
{
//Iterate all active contact managers
PxBitMap::Iterator it(mActiveContactManager);
PxU32 index = it.getNext();
while(index != PxBitMap::Iterator::DONE)
{
PxsContactManager* cm = mContactManagerPool.findByIndexFast(index);
PxcNpWorkUnit& npwUnit = cm->getWorkUnit();
// contact cache
if(!npwUnit.pairCache.isManifold())
{
PxU8* contactCachePtr = npwUnit.pairCache.mCachedData;
if (contactCachePtr)
{
PxcLocalContactsCache* lcc;
PxU8* contacts = PxcNpCacheRead(npwUnit.pairCache, lcc);
#if PX_DEBUG
PxcLocalContactsCache testCache;
PxU32 testBytes;
const PxU8* testPtr = PxcNpCacheRead2(npwUnit.pairCache, testCache, testBytes);
#endif
lcc->mTransform0.p -= shift;
lcc->mTransform1.p -= shift;
const PxU32 nbContacts = lcc->mNbCachedContacts;
const bool sameNormal = lcc->mSameNormal;
const bool useFaceIndices = lcc->mUseFaceIndices;
for(PxU32 i=0; i < nbContacts; i++)
{
if (i != nbContacts-1)
PxPrefetchLine(contacts, 128);
if(!i || !sameNormal)
contacts += sizeof(PxVec3);
PxVec3* cachedPoint = reinterpret_cast<PxVec3*>(contacts);
*cachedPoint -= shift;
contacts += sizeof(PxVec3);
contacts += sizeof(PxReal);
if(useFaceIndices)
contacts += 2 * sizeof(PxU32);
}
#if PX_DEBUG
PX_ASSERT(contacts == (testPtr + testBytes));
#endif
}
}
index = it.getNext();
}
}
#endif
// adjust visualization culling box
if(!mVisualizationCullingBox.isEmpty())
{
mVisualizationCullingBox.minimum -= shift;
mVisualizationCullingBox.maximum -= shift;
}
}
void PxsContext::swapStreams()
{
mNpMemBlockPool.swapNpCacheStreams();
}
void PxsContext::mergeCMDiscreteUpdateResults(PxBaseTask* /*continuation*/)
{
PX_PROFILE_ZONE("Sim.narrowPhaseMerge", mContextID);
mNpImplementationContext->appendContactManagers();
//Note: the iterator extracts all the items and returns them to the cache on destruction(for thread safety).
PxcThreadCoherentCacheIterator<PxcNpThreadContext, PxcNpContext> threadContextIt(mNpThreadContextPool);
for(PxcNpThreadContext* threadContext = threadContextIt.getNext(); threadContext; threadContext = threadContextIt.getNext())
{
mCMTouchEventCount[PXS_LOST_TOUCH_COUNT] += threadContext->getLocalLostTouchCount();
mCMTouchEventCount[PXS_NEW_TOUCH_COUNT] += threadContext->getLocalNewTouchCount();
#if PX_ENABLE_SIM_STATS
for(PxU32 i=0;i<PxGeometryType::eGEOMETRY_COUNT;i++)
{
#if PX_DEBUG
for(PxU32 j=0; j<i; j++)
PX_ASSERT(!threadContext->mDiscreteContactPairs[i][j]);
#endif
for(PxU32 j=i; j<PxGeometryType::eGEOMETRY_COUNT; j++)
{
const PxU32 nb = threadContext->mDiscreteContactPairs[i][j];
const PxU32 nbModified = threadContext->mModifiedContactPairs[i][j];
mSimStats.mNbDiscreteContactPairs[i][j] += nb;
mSimStats.mNbModifiedContactPairs[i][j] += nbModified;
mSimStats.mNbDiscreteContactPairsTotal += nb;
}
}
mSimStats.mNbDiscreteContactPairsWithCacheHits += threadContext->mNbDiscreteContactPairsWithCacheHits;
mSimStats.mNbDiscreteContactPairsWithContacts += threadContext->mNbDiscreteContactPairsWithContacts;
mSimStats.mTotalCompressedContactSize += threadContext->mCompressedCacheSize;
//KS - this data is not available yet
//mSimStats.mTotalConstraintSize += threadContext->mConstraintSize;
threadContext->clearStats();
#else
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
#endif
mContactManagerTouchEvent.combineInPlace<PxBitMap::OR>(threadContext->getLocalChangeTouch());
//mContactManagerPatchChangeEvent.combineInPlace<PxBitMap::OR>(threadContext->getLocalPatchChangeMap());
mMaxPatches = PxMax(mMaxPatches, threadContext->mMaxPatches);
threadContext->mMaxPatches = 0;
}
}
void PxsContext::updateContactManager(PxReal dt, bool hasContactDistanceChanged, PxBaseTask* continuation, PxBaseTask* firstPassContinuation,
Cm::FanoutTask* updateBoundAndShapeTask)
{
PX_ASSERT(mNpImplementationContext);
return mNpImplementationContext->updateContactManager(dt, hasContactDistanceChanged, continuation,
firstPassContinuation, updateBoundAndShapeTask);
}
void PxsContext::secondPassUpdateContactManager(PxReal dt, PxBaseTask* continuation)
{
PX_ASSERT(mNpImplementationContext);
mNpImplementationContext->secondPassUpdateContactManager(dt, continuation);
}
void PxsContext::fetchUpdateContactManager()
{
PX_ASSERT(mNpImplementationContext);
mNpImplementationContext->fetchUpdateContactManager();
mergeCMDiscreteUpdateResults(NULL);
}
void PxsContext::resetThreadContexts()
{
//Note: the iterator extracts all the items and returns them to the cache on destruction(for thread safety).
PxcThreadCoherentCacheIterator<PxcNpThreadContext, PxcNpContext> threadContextIt(mNpThreadContextPool);
PxcNpThreadContext* threadContext = threadContextIt.getNext();
while(threadContext != NULL)
{
threadContext->reset(mContactManagerTouchEvent.size());
threadContext = threadContextIt.getNext();
}
}
bool PxsContext::getManagerTouchEventCount(PxU32* newTouch, PxU32* lostTouch, PxU32* ccdTouch) const
{
if(newTouch)
*newTouch = mCMTouchEventCount[PXS_NEW_TOUCH_COUNT];
if(lostTouch)
*lostTouch = mCMTouchEventCount[PXS_LOST_TOUCH_COUNT];
if(ccdTouch)
*ccdTouch = mCMTouchEventCount[PXS_CCD_RETOUCH_COUNT];
return true;
}
void PxsContext::fillManagerTouchEvents(PxvContactManagerTouchEvent* newTouch, PxU32& newTouchCount,
PxvContactManagerTouchEvent* lostTouch, PxU32& lostTouchCount,
PxvContactManagerTouchEvent* ccdTouch, PxU32& ccdTouchCount)
{
PX_PROFILE_ZONE("PxsContext::fillManagerTouchEvents", mContextID);
const PxvContactManagerTouchEvent* newTouchStart = newTouch;
const PxvContactManagerTouchEvent* lostTouchStart = lostTouch;
const PxvContactManagerTouchEvent* ccdTouchStart = ccdTouch;
const PxvContactManagerTouchEvent* newTouchEnd = newTouch + newTouchCount;
const PxvContactManagerTouchEvent* lostTouchEnd = lostTouch + lostTouchCount;
const PxvContactManagerTouchEvent* ccdTouchEnd = ccdTouch + ccdTouchCount;
PX_UNUSED(newTouchEnd);
PX_UNUSED(lostTouchEnd);
PX_UNUSED(ccdTouchEnd);
const PxU32* bits = mContactManagerTouchEvent.getWords();
if(bits)
{
// PT: ### bitmap iterator pattern
const PxU32 lastSetBit = mContactManagerTouchEvent.findLast();
for(PxU32 w = 0; w <= lastSetBit >> 5; ++w)
{
for(PxU32 b = bits[w]; b; b &= b-1)
{
const PxU32 index = PxU32(w<<5|PxLowestSetBit(b));
PxsContactManager* cm = mContactManagerPool.findByIndexFast(index);
if(cm->getTouchStatus())
{
if(!cm->getHasCCDRetouch())
{
PX_ASSERT(newTouch < newTouchEnd);
newTouch->setCMTouchEventUserData(cm->getShapeInteraction());
newTouch++;
}
else
{
PX_ASSERT(ccdTouch);
PX_ASSERT(ccdTouch < ccdTouchEnd);
ccdTouch->setCMTouchEventUserData(cm->getShapeInteraction());
cm->clearCCDRetouch();
ccdTouch++;
}
}
else
{
PX_ASSERT(lostTouch < lostTouchEnd);
lostTouch->setCMTouchEventUserData(cm->getShapeInteraction());
lostTouch++;
}
}
}
}
newTouchCount = PxU32(newTouch - newTouchStart);
lostTouchCount = PxU32(lostTouch - lostTouchStart);
ccdTouchCount = PxU32(ccdTouch - ccdTouchStart);
}
void PxsContext::beginUpdate()
{
#if PX_ENABLE_SIM_STATS
mSimStats.clearAll();
#else
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
#endif
}