feat(physics): wire physx sdk into build
This commit is contained in:
50
engine/third_party/physx/source/lowlevel/common/include/collision/PxcContactMethodImpl.h
vendored
Normal file
50
engine/third_party/physx/source/lowlevel/common/include/collision/PxcContactMethodImpl.h
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// 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 PXC_CONTACT_METHOD_IMPL_H
|
||||
#define PXC_CONTACT_METHOD_IMPL_H
|
||||
|
||||
#include "GuContactMethodImpl.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
/*!
|
||||
Method prototype for contact generation routines
|
||||
*/
|
||||
typedef bool (*PxcContactMethod) (GU_CONTACT_METHOD_ARGS);
|
||||
|
||||
// Matrix of types
|
||||
extern PxcContactMethod g_ContactMethodTable[][PxGeometryType::eGEOMETRY_COUNT];
|
||||
extern const bool g_CanUseContactCache[][PxGeometryType::eGEOMETRY_COUNT];
|
||||
extern PxcContactMethod g_PCMContactMethodTable[][PxGeometryType::eGEOMETRY_COUNT];
|
||||
|
||||
extern const bool gEnablePCMCaching[][PxGeometryType::eGEOMETRY_COUNT];
|
||||
}
|
||||
|
||||
#endif
|
||||
154
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcConstraintBlockStream.h
vendored
Normal file
154
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcConstraintBlockStream.h
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
// 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 PXC_CONSTRAINT_BLOCK_POOL_H
|
||||
#define PXC_CONSTRAINT_BLOCK_POOL_H
|
||||
|
||||
#include "PxvConfig.h"
|
||||
#include "foundation/PxArray.h"
|
||||
#include "foundation/PxMutex.h"
|
||||
#include "PxcNpMemBlockPool.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxsConstraintBlockManager
|
||||
{
|
||||
public:
|
||||
PxsConstraintBlockManager(PxcNpMemBlockPool & blockPool):
|
||||
mBlockPool(blockPool)
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void reset()
|
||||
{
|
||||
mBlockPool.releaseConstraintBlocks(mTrackingArray);
|
||||
}
|
||||
|
||||
PxcNpMemBlockArray mTrackingArray;
|
||||
PxcNpMemBlockPool& mBlockPool;
|
||||
|
||||
private:
|
||||
PxsConstraintBlockManager& operator=(const PxsConstraintBlockManager&);
|
||||
};
|
||||
|
||||
class PxcConstraintBlockStream
|
||||
{
|
||||
PX_NOCOPY(PxcConstraintBlockStream)
|
||||
public:
|
||||
PxcConstraintBlockStream(PxcNpMemBlockPool & blockPool) :
|
||||
mBlockPool (blockPool),
|
||||
mBlock (NULL),
|
||||
mUsed (0)
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxU8* reserve(PxU32 size, PxsConstraintBlockManager& manager)
|
||||
{
|
||||
size = (size+15)&~15;
|
||||
if(size>PxcNpMemBlock::SIZE)
|
||||
return mBlockPool.acquireExceptionalConstraintMemory(size);
|
||||
|
||||
if(mBlock == NULL || size+mUsed>PxcNpMemBlock::SIZE)
|
||||
{
|
||||
mBlock = mBlockPool.acquireConstraintBlock(manager.mTrackingArray);
|
||||
PX_ASSERT(0==mBlock || mBlock->data == reinterpret_cast<PxU8*>(mBlock));
|
||||
mUsed = size;
|
||||
return reinterpret_cast<PxU8*>(mBlock);
|
||||
}
|
||||
PX_ASSERT(mBlock && mBlock->data == reinterpret_cast<PxU8*>(mBlock));
|
||||
PxU8* PX_RESTRICT result = mBlock->data+mUsed;
|
||||
mUsed += size;
|
||||
return result;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void reset()
|
||||
{
|
||||
mBlock = NULL;
|
||||
mUsed = 0;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxcNpMemBlockPool& getMemBlockPool() { return mBlockPool; }
|
||||
|
||||
private:
|
||||
PxcNpMemBlockPool& mBlockPool;
|
||||
PxcNpMemBlock* mBlock; // current constraint block
|
||||
PxU32 mUsed; // number of bytes used in constraint block
|
||||
//Tracking peak allocations
|
||||
PxU32 mPeakUsed;
|
||||
};
|
||||
|
||||
class PxcContactBlockStream
|
||||
{
|
||||
PX_NOCOPY(PxcContactBlockStream)
|
||||
public:
|
||||
PxcContactBlockStream(PxcNpMemBlockPool & blockPool):
|
||||
mBlockPool(blockPool),
|
||||
mBlock(NULL),
|
||||
mUsed(0)
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxU8* reserve(PxU32 size)
|
||||
{
|
||||
size = (size+15)&~15;
|
||||
|
||||
if(size>PxcNpMemBlock::SIZE)
|
||||
return mBlockPool.acquireExceptionalConstraintMemory(size);
|
||||
|
||||
PX_ASSERT(size <= PxcNpMemBlock::SIZE);
|
||||
|
||||
if(mBlock == NULL || size+mUsed>PxcNpMemBlock::SIZE)
|
||||
{
|
||||
mBlock = mBlockPool.acquireContactBlock();
|
||||
PX_ASSERT(0==mBlock || mBlock->data == reinterpret_cast<PxU8*>(mBlock));
|
||||
mUsed = size;
|
||||
return reinterpret_cast<PxU8*>(mBlock);
|
||||
}
|
||||
PX_ASSERT(mBlock && mBlock->data == reinterpret_cast<PxU8*>(mBlock));
|
||||
PxU8* PX_RESTRICT result = mBlock->data+mUsed;
|
||||
mUsed += size;
|
||||
return result;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void reset()
|
||||
{
|
||||
mBlock = NULL;
|
||||
mUsed = 0;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxcNpMemBlockPool& getMemBlockPool() { return mBlockPool; }
|
||||
|
||||
private:
|
||||
PxcNpMemBlockPool& mBlockPool;
|
||||
PxcNpMemBlock* mBlock; // current constraint block
|
||||
PxU32 mUsed; // number of bytes used in constraint block
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
65
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcContactCache.h
vendored
Normal file
65
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcContactCache.h
vendored
Normal 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 PXC_CONTACT_CACHE_H
|
||||
#define PXC_CONTACT_CACHE_H
|
||||
|
||||
#include "foundation/PxTransform.h"
|
||||
#include "PxvConfig.h"
|
||||
#include "PxcContactMethodImpl.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxcNpThreadContext;
|
||||
|
||||
bool PxcCacheLocalContacts( PxcNpThreadContext& context, Gu::Cache& pairContactCache,
|
||||
const PxTransform32& tm0, const PxTransform32& tm1,
|
||||
const PxcContactMethod conMethod,
|
||||
const PxGeometry& shape0, const PxGeometry& shape1);
|
||||
|
||||
struct PxcLocalContactsCache
|
||||
{
|
||||
PxTransform mTransform0;
|
||||
PxTransform mTransform1;
|
||||
PxU16 mNbCachedContacts;
|
||||
bool mUseFaceIndices;
|
||||
bool mSameNormal;
|
||||
|
||||
PX_FORCE_INLINE void operator = (const PxcLocalContactsCache& other)
|
||||
{
|
||||
mTransform0 = other.mTransform0;
|
||||
mTransform1 = other.mTransform1;
|
||||
mNbCachedContacts = other.mNbCachedContacts;
|
||||
mUseFaceIndices = other.mUseFaceIndices;
|
||||
mSameNormal = other.mSameNormal;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PXC_CONTACT_CACHE_H
|
||||
65
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcMaterialMethodImpl.h
vendored
Normal file
65
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcMaterialMethodImpl.h
vendored
Normal 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 PXC_MATERIAL_METHOD_H
|
||||
#define PXC_MATERIAL_METHOD_H
|
||||
|
||||
#include "geometry/PxGeometry.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxsShapeCore;
|
||||
struct PxsMaterialInfo;
|
||||
class PxContactBuffer;
|
||||
|
||||
#define MATERIAL_METHOD_ARGS \
|
||||
const PxsShapeCore* shape0, \
|
||||
const PxsShapeCore* shape1, \
|
||||
const PxContactBuffer& contactBuffer, \
|
||||
PxsMaterialInfo* materialInfo
|
||||
|
||||
#define SINGLE_MATERIAL_METHOD_ARGS \
|
||||
const PxsShapeCore* shape, \
|
||||
PxU32 index, \
|
||||
const PxContactBuffer& contactBuffer, \
|
||||
PxsMaterialInfo* materialInfo
|
||||
|
||||
/*!
|
||||
Method prototype for fetch material routines
|
||||
*/
|
||||
typedef void (*PxcGetMaterialMethod) (MATERIAL_METHOD_ARGS);
|
||||
|
||||
typedef void (*PxcGetSingleMaterialMethod) (SINGLE_MATERIAL_METHOD_ARGS);
|
||||
|
||||
extern PxcGetMaterialMethod g_GetMaterialMethodTable[][PxGeometryType::eGEOMETRY_COUNT];
|
||||
|
||||
extern PxcGetSingleMaterialMethod g_GetSingleMaterialMethodTable[PxGeometryType::eGEOMETRY_COUNT];
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
49
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpBatch.h
vendored
Normal file
49
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpBatch.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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 PXC_NP_BATCH_H
|
||||
#define PXC_NP_BATCH_H
|
||||
|
||||
#include "PxvConfig.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxcNpWorkUnit;
|
||||
class PxcNpThreadContext;
|
||||
struct PxsContactManagerOutput;
|
||||
|
||||
namespace Gu
|
||||
{
|
||||
struct Cache;
|
||||
}
|
||||
|
||||
void PxcDiscreteNarrowPhase(PxcNpThreadContext& context, const PxcNpWorkUnit& cmInput, Gu::Cache& cache, PxsContactManagerOutput& output, PxU64 contextID);
|
||||
void PxcDiscreteNarrowPhasePCM(PxcNpThreadContext& context, const PxcNpWorkUnit& cmInput, Gu::Cache& cache, PxsContactManagerOutput& output, PxU64 contextID);
|
||||
}
|
||||
|
||||
#endif
|
||||
132
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpCache.h
vendored
Normal file
132
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpCache.h
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
// 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 PXC_NP_CACHE_H
|
||||
#define PXC_NP_CACHE_H
|
||||
|
||||
#include "foundation/PxMemory.h"
|
||||
#include "foundation/PxIntrinsics.h"
|
||||
#include "foundation/PxPool.h"
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#include "foundation/PxUtilities.h"
|
||||
|
||||
#include "PxcNpCacheStreamPair.h"
|
||||
|
||||
#include "GuContactMethodImpl.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
PX_FORCE_INLINE void PxcNpCacheReserve(PxcNpCacheStreamPair& streams, Gu::Cache& cache, PxU32 bytes)
|
||||
{
|
||||
bool sizeTooLarge;
|
||||
PxU8* ls = streams.reserve(bytes, sizeTooLarge);
|
||||
cache.mCachedData = ls;
|
||||
|
||||
if(sizeTooLarge)
|
||||
{
|
||||
// PT: TODO: consider changing the error message, it will silently become obsolete if we change the value of PxcNpMemBlock::SIZE.
|
||||
// On the other hand the PxSceneDesc::maxNbContactDataBlocks also hardcodes "16K data blocks" so this isn't urgent.
|
||||
PX_WARN_ONCE(
|
||||
"Attempting to allocate more than 16K of contact data for a single contact pair in narrowphase. "
|
||||
"Either accept dropped contacts or simplify collision geometry.");
|
||||
}
|
||||
else if(ls==NULL)
|
||||
{
|
||||
PX_WARN_ONCE(
|
||||
"Reached limit set by PxSceneDesc::maxNbContactDataBlocks - ran out of buffer space for narrow phase. "
|
||||
"Either accept dropped contacts or increase buffer size allocated for narrow phase by increasing PxSceneDesc::maxNbContactDataBlocks.");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PxcNpCacheWrite(PxcNpCacheStreamPair& streams,
|
||||
Gu::Cache& cache,
|
||||
const T& payload,
|
||||
PxU32 bytes,
|
||||
const PxU8* data)
|
||||
{
|
||||
PxU8* ls = PxcNpCacheWriteInitiate(streams, cache, payload, bytes);
|
||||
|
||||
if (ls == NULL)
|
||||
return;
|
||||
|
||||
PxcNpCacheWriteFinalize(ls, payload, bytes, data);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
PxU8* PxcNpCacheWriteInitiate(PxcNpCacheStreamPair& streams, Gu::Cache& cache, const T& payload, PxU32 bytes)
|
||||
{
|
||||
const PxU32 payloadSize = (sizeof(payload)+3)&~3;
|
||||
cache.mCachedSize = PxTo16((payloadSize + 4 + bytes + 0xF)&~0xF);
|
||||
|
||||
PxcNpCacheReserve(streams, cache, cache.mCachedSize);
|
||||
|
||||
return cache.mCachedData;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PX_FORCE_INLINE void PxcNpCacheWriteFinalize(PxU8* ls, const T& payload, PxU32 bytes, const PxU8* data)
|
||||
{
|
||||
const PxU32 payloadSize = (sizeof(payload)+3)&~3;
|
||||
*reinterpret_cast<T*>(ls) = payload;
|
||||
*reinterpret_cast<PxU32*>(ls+payloadSize) = bytes;
|
||||
if(data)
|
||||
PxMemCopy(ls+payloadSize+sizeof(PxU32), data, bytes);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PX_FORCE_INLINE PxU8* PxcNpCacheRead(Gu::Cache& cache, T*& payload)
|
||||
{
|
||||
PxU8* ls = cache.mCachedData;
|
||||
payload = reinterpret_cast<T*>(ls);
|
||||
const PxU32 payloadSize = (sizeof(T)+3)&~3;
|
||||
return reinterpret_cast<PxU8*>(ls+payloadSize+sizeof(PxU32));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const PxU8* PxcNpCacheRead2(Gu::Cache& cache, T& payload, PxU32& bytes)
|
||||
{
|
||||
const PxU8* ls = cache.mCachedData;
|
||||
if(ls==NULL)
|
||||
{
|
||||
bytes = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const PxU32 payloadSize = (sizeof(payload)+3)&~3;
|
||||
payload = *reinterpret_cast<const T*>(ls);
|
||||
bytes = *reinterpret_cast<const PxU32*>(ls+payloadSize);
|
||||
PX_ASSERT(cache.mCachedSize == ((payloadSize + 4 + bytes+0xF)&~0xF));
|
||||
return reinterpret_cast<const PxU8*>(ls+payloadSize+sizeof(PxU32));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
58
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpCacheStreamPair.h
vendored
Normal file
58
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpCacheStreamPair.h
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// 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 PXC_NP_CACHE_STREAM_PAIR_H
|
||||
#define PXC_NP_CACHE_STREAM_PAIR_H
|
||||
|
||||
#include "foundation/PxSimpleTypes.h"
|
||||
#include "PxvConfig.h"
|
||||
#include "PxcNpMemBlockPool.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxcNpCacheStreamPair
|
||||
{
|
||||
PX_NOCOPY(PxcNpCacheStreamPair)
|
||||
public:
|
||||
PxcNpCacheStreamPair(PxcNpMemBlockPool& blockPool);
|
||||
|
||||
// reserve can fail and return null.
|
||||
PxU8* reserve(PxU32 byteCount, bool& sizeTooLarge);
|
||||
PX_FORCE_INLINE void reset()
|
||||
{
|
||||
mBlock = NULL;
|
||||
mUsed = 0;
|
||||
}
|
||||
private:
|
||||
PxcNpMemBlockPool& mBlockPool;
|
||||
PxcNpMemBlock* mBlock;
|
||||
PxU32 mUsed;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
60
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpContactPrepShared.h
vendored
Normal file
60
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpContactPrepShared.h
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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 PXC_NP_CONTACT_PREP_SHARED_H
|
||||
#define PXC_NP_CONTACT_PREP_SHARED_H
|
||||
|
||||
#include "foundation/PxSimpleTypes.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxcNpThreadContext;
|
||||
struct PxsMaterialInfo;
|
||||
class PxsMaterialManager;
|
||||
class PxsConstraintBlockManager;
|
||||
class PxcConstraintBlockStream;
|
||||
struct PxContactPoint;
|
||||
struct PxcDataStreamPool;
|
||||
|
||||
PX_FORCE_INLINE PxU32 computeAlignedSize(PxU32 size)
|
||||
{
|
||||
return (size + 0xf) & 0xfffffff0;
|
||||
}
|
||||
|
||||
static const PxReal PXC_SAME_NORMAL = 0.999f; //Around 6 degrees
|
||||
|
||||
PxU32 writeCompressedContact(const PxContactPoint* const PX_RESTRICT contactPoints, const PxU32 numContactPoints, PxcNpThreadContext* threadContext,
|
||||
PxU16& writtenContactCount, PxU8*& outContactPatches, PxU8*& outContactPoints, PxU16& compressedContactSize, PxReal*& contactForces, PxU32 contactForceByteSize,
|
||||
PxU8*& outFrictionPatches, PxcDataStreamPool* frictionPatchesStreamPool,
|
||||
const PxsMaterialManager* materialManager, bool hasModifiableContacts, bool forceNoResponse, const PxsMaterialInfo* PX_RESTRICT pMaterial, PxU8& numPatches,
|
||||
PxU32 additionalHeaderSize = 0, PxsConstraintBlockManager* manager = NULL, PxcConstraintBlockStream* blockStream = NULL, bool insertAveragePoint = false,
|
||||
PxcDataStreamPool* pool = NULL, PxcDataStreamPool* patchStreamPool = NULL, PxcDataStreamPool* forcePool = NULL, const bool isMeshType = false);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
117
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpMemBlockPool.h
vendored
Normal file
117
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpMemBlockPool.h
vendored
Normal 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 PXC_NP_MEM_BLOCK_POOL_H
|
||||
#define PXC_NP_MEM_BLOCK_POOL_H
|
||||
|
||||
#include "PxvConfig.h"
|
||||
#include "foundation/PxArray.h"
|
||||
#include "foundation/PxMutex.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxcScratchAllocator;
|
||||
|
||||
struct PxcNpMemBlock
|
||||
{
|
||||
enum
|
||||
{
|
||||
SIZE = 16384
|
||||
};
|
||||
PxU8 data[SIZE];
|
||||
};
|
||||
|
||||
typedef PxArray<PxcNpMemBlock*> PxcNpMemBlockArray;
|
||||
|
||||
class PxcNpMemBlockPool
|
||||
{
|
||||
PX_NOCOPY(PxcNpMemBlockPool)
|
||||
public:
|
||||
PxcNpMemBlockPool(PxcScratchAllocator& allocator);
|
||||
~PxcNpMemBlockPool();
|
||||
|
||||
void init(PxU32 initial16KDataBlocks, PxU32 maxBlocks);
|
||||
void flush();
|
||||
void setBlockCount(PxU32 count);
|
||||
PxU32 getUsedBlockCount() const;
|
||||
PxU32 getMaxUsedBlockCount() const;
|
||||
PxU32 getPeakConstraintBlockCount() const;
|
||||
void releaseUnusedBlocks();
|
||||
|
||||
PxcNpMemBlock* acquireConstraintBlock();
|
||||
PxcNpMemBlock* acquireConstraintBlock(PxcNpMemBlockArray& memBlocks);
|
||||
PxcNpMemBlock* acquireContactBlock();
|
||||
PxcNpMemBlock* acquireFrictionBlock();
|
||||
PxcNpMemBlock* acquireNpCacheBlock();
|
||||
|
||||
PxU8* acquireExceptionalConstraintMemory(PxU32 size);
|
||||
|
||||
void acquireConstraintMemory();
|
||||
void releaseConstraintMemory();
|
||||
void releaseConstraintBlocks(PxcNpMemBlockArray& memBlocks);
|
||||
void releaseContacts();
|
||||
void swapFrictionStreams();
|
||||
void swapNpCacheStreams();
|
||||
|
||||
void flushUnused();
|
||||
|
||||
private:
|
||||
|
||||
PxMutex mLock;
|
||||
PxcNpMemBlockArray mConstraints;
|
||||
PxcNpMemBlockArray mContacts[2];
|
||||
PxcNpMemBlockArray mFriction[2];
|
||||
PxcNpMemBlockArray mNpCache[2];
|
||||
PxcNpMemBlockArray mScratchBlocks;
|
||||
PxArray<PxU8*> mExceptionalConstraints;
|
||||
|
||||
PxcNpMemBlockArray mUnused;
|
||||
|
||||
PxU32 mNpCacheActiveStream;
|
||||
PxU32 mFrictionActiveStream;
|
||||
PxU32 mCCDCacheActiveStream;
|
||||
PxU32 mContactIndex;
|
||||
PxU32 mAllocatedBlocks;
|
||||
PxU32 mMaxBlocks;
|
||||
PxU32 mInitialBlocks;
|
||||
PxU32 mUsedBlocks;
|
||||
PxU32 mMaxUsedBlocks;
|
||||
PxcNpMemBlock* mScratchBlockAddr;
|
||||
PxU32 mNbScratchBlocks;
|
||||
PxcScratchAllocator& mScratchAllocator;
|
||||
|
||||
PxU32 mPeakConstraintAllocations;
|
||||
PxU32 mConstraintAllocations;
|
||||
|
||||
PxcNpMemBlock* acquire(PxcNpMemBlockArray& trackingArray, PxU32* allocationCount = NULL, PxU32* peakAllocationCount = NULL, bool isScratchAllocation = false);
|
||||
void release(PxcNpMemBlockArray& deadArray, PxU32* allocationCount = NULL);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
200
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpThreadContext.h
vendored
Normal file
200
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpThreadContext.h
vendored
Normal 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 PXC_NP_THREAD_CONTEXT_H
|
||||
#define PXC_NP_THREAD_CONTEXT_H
|
||||
|
||||
#include "geometry/PxGeometry.h"
|
||||
#include "geomutils/PxContactBuffer.h"
|
||||
#include "common/PxRenderOutput.h"
|
||||
|
||||
#include "CmRenderBuffer.h"
|
||||
|
||||
#include "PxvConfig.h"
|
||||
#include "CmScaling.h"
|
||||
#include "PxcNpCacheStreamPair.h"
|
||||
#include "PxcConstraintBlockStream.h"
|
||||
#include "PxcThreadCoherentCache.h"
|
||||
#include "PxcScratchAllocator.h"
|
||||
#include "foundation/PxBitMap.h"
|
||||
#include "../pcm/GuPersistentContactManifold.h"
|
||||
#include "../contact/GuContactMethodImpl.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
class PxsTransformCache;
|
||||
class PxsMaterialManager;
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
class BodySim;
|
||||
}
|
||||
|
||||
/*!
|
||||
Per-thread context used by contact generation routines.
|
||||
*/
|
||||
|
||||
struct PxcDataStreamPool
|
||||
{
|
||||
PxU8* mDataStream;
|
||||
PxI32 mSharedDataIndex;
|
||||
PxU32 mDataStreamSize;
|
||||
PxU32 mSharedDataIndexGPU;
|
||||
|
||||
bool isOverflown() const
|
||||
{
|
||||
//FD: my expectaton is that reading those variables is atomic, shared indices are non-decreasing,
|
||||
//so we can only get a false overflow alert because of concurrency issues, which is not a big deal as it means
|
||||
//it did overflow a bit later
|
||||
return (mSharedDataIndex + mSharedDataIndexGPU) > mDataStreamSize;
|
||||
}
|
||||
};
|
||||
|
||||
struct PxcNpContext
|
||||
{
|
||||
private:
|
||||
PX_NOCOPY(PxcNpContext)
|
||||
public:
|
||||
|
||||
PxcNpContext() :
|
||||
mNpMemBlockPool (mScratchAllocator),
|
||||
mMeshContactMargin (0.0f),
|
||||
mToleranceLength (0.0f),
|
||||
mContactStreamPool (NULL),
|
||||
mPatchStreamPool (NULL),
|
||||
mForceAndIndiceStreamPool(NULL),
|
||||
mFrictionPatchStreamPool(NULL),
|
||||
mMaterialManager (NULL)
|
||||
{
|
||||
}
|
||||
|
||||
PxcScratchAllocator mScratchAllocator;
|
||||
PxcNpMemBlockPool mNpMemBlockPool;
|
||||
PxReal mMeshContactMargin;
|
||||
PxReal mToleranceLength;
|
||||
Cm::RenderBuffer mRenderBuffer;
|
||||
PxcDataStreamPool* mContactStreamPool;
|
||||
PxcDataStreamPool* mPatchStreamPool;
|
||||
PxcDataStreamPool* mForceAndIndiceStreamPool;
|
||||
PxcDataStreamPool* mFrictionPatchStreamPool;
|
||||
PxsMaterialManager* mMaterialManager;
|
||||
|
||||
PX_FORCE_INLINE PxReal getToleranceLength() const { return mToleranceLength; }
|
||||
PX_FORCE_INLINE void setToleranceLength(PxReal x) { mToleranceLength = x; }
|
||||
PX_FORCE_INLINE PxReal getMeshContactMargin() const { return mMeshContactMargin; }
|
||||
PX_FORCE_INLINE void setMeshContactMargin(PxReal x) { mMeshContactMargin = x; }
|
||||
|
||||
PX_FORCE_INLINE PxcNpMemBlockPool& getNpMemBlockPool() { return mNpMemBlockPool; }
|
||||
PX_FORCE_INLINE const PxcNpMemBlockPool& getNpMemBlockPool() const { return mNpMemBlockPool; }
|
||||
PX_FORCE_INLINE void setMaterialManager(PxsMaterialManager* m){ mMaterialManager = m; }
|
||||
PX_FORCE_INLINE PxsMaterialManager* getMaterialManager() const { return mMaterialManager; }
|
||||
};
|
||||
|
||||
class PxcNpThreadContext : public PxcThreadCoherentCache<PxcNpThreadContext, PxcNpContext>::EntryBase
|
||||
{
|
||||
PX_NOCOPY(PxcNpThreadContext)
|
||||
public:
|
||||
PxcNpThreadContext(PxcNpContext* params);
|
||||
~PxcNpThreadContext();
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
void clearStats();
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
|
||||
PX_FORCE_INLINE void addLocalNewTouchCount(PxU32 newTouchCMCount) { mLocalNewTouchCount += newTouchCMCount; }
|
||||
PX_FORCE_INLINE void addLocalLostTouchCount(PxU32 lostTouchCMCount) { mLocalLostTouchCount += lostTouchCMCount; }
|
||||
PX_FORCE_INLINE PxU32 getLocalNewTouchCount() const { return mLocalNewTouchCount; }
|
||||
PX_FORCE_INLINE PxU32 getLocalLostTouchCount() const { return mLocalLostTouchCount; }
|
||||
|
||||
PX_FORCE_INLINE PxBitMap& getLocalChangeTouch() { return mLocalChangeTouch; }
|
||||
|
||||
void reset(PxU32 cmCount);
|
||||
// debugging
|
||||
PxRenderOutput mRenderOutput;
|
||||
|
||||
// dsequeira: Need to think about this block pool allocation a bit more. Ideally we'd be
|
||||
// taking blocks from a single pool, except that we want to be able to selectively reclaim
|
||||
// blocks if the user needs to defragment, depending on which artifacts they're willing
|
||||
// to tolerate, such that the blocks we don't reclaim are contiguous.
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
PxU32 mDiscreteContactPairs [PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT];
|
||||
PxU32 mModifiedContactPairs [PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT];
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
PxcContactBlockStream mContactBlockStream; // constraint block pool
|
||||
PxcNpCacheStreamPair mNpCacheStreamPair; // narrow phase pairwise data cache
|
||||
|
||||
// Everything below here is scratch state. Most of it can even overlap.
|
||||
|
||||
// temporary contact buffer
|
||||
PxContactBuffer mContactBuffer;
|
||||
|
||||
PX_ALIGN(16, Gu::MultiplePersistentContactManifold mTempManifold);
|
||||
|
||||
Gu::NarrowPhaseParams mNarrowPhaseParams;
|
||||
|
||||
// DS: this stuff got moved here from the PxcNpPairContext. As Pierre says:
|
||||
////////// PT: those members shouldn't be there in the end, it's not necessary
|
||||
PxsTransformCache* mTransformCache;
|
||||
const PxReal* mContactDistances;
|
||||
bool mPCM;
|
||||
bool mContactCache;
|
||||
bool mCreateAveragePoint; // flag to enforce whether we create average points
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
PxU32 mCompressedCacheSize;
|
||||
PxU32 mNbDiscreteContactPairsWithCacheHits;
|
||||
PxU32 mNbDiscreteContactPairsWithContacts;
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
PxReal mDt; // AP: still needed for ccd
|
||||
PxU32 mCCDPass;
|
||||
PxU32 mCCDFaceIndex;
|
||||
|
||||
PxU32 mMaxPatches;
|
||||
|
||||
PxcDataStreamPool* mContactStreamPool;
|
||||
PxcDataStreamPool* mPatchStreamPool;
|
||||
PxcDataStreamPool* mForceAndIndiceStreamPool; //this stream is used to store the force buffer and triangle index if we are performing mesh/heightfield contact gen
|
||||
PxcDataStreamPool* mFrictionPatchStreamPool;
|
||||
PxsMaterialManager* mMaterialManager;
|
||||
|
||||
private:
|
||||
// change touch handling.
|
||||
PxBitMap mLocalChangeTouch;
|
||||
PxU32 mLocalNewTouchCount;
|
||||
PxU32 mLocalLostTouchCount;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
211
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpWorkUnit.h
vendored
Normal file
211
engine/third_party/physx/source/lowlevel/common/include/pipeline/PxcNpWorkUnit.h
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
// 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 PXC_NP_WORK_UNIT_H
|
||||
#define PXC_NP_WORK_UNIT_H
|
||||
|
||||
#include "PxConstraintDesc.h"
|
||||
#include "PxvGeometry.h"
|
||||
|
||||
// PT: the shapeCore structs are 16-bytes aligned by design so the low 4 bits of their pointers are available.
|
||||
// We can store the geom types there since they fit. An alternative would be simply to read the types from
|
||||
// shapeCore->mGeometry.getType() but that is one more indirection/cache miss. We might be using other shapeCore
|
||||
// data everywhere we need the type so that might be irrelevant and could be revisited.
|
||||
PX_COMPILE_TIME_ASSERT(physx::PxGeometryType::eGEOMETRY_COUNT<16);
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxsRigidCore;
|
||||
struct PxsShapeCore;
|
||||
|
||||
namespace IG
|
||||
{
|
||||
typedef PxU32 EdgeIndex;
|
||||
}
|
||||
|
||||
struct PxcNpWorkUnitFlag
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eOUTPUT_CONTACTS = 1 << 0,
|
||||
eOUTPUT_CONSTRAINTS = 1 << 1,
|
||||
eDISABLE_STRONG_FRICTION = 1 << 2,
|
||||
eARTICULATION_BODY0 = 1 << 3,
|
||||
eARTICULATION_BODY1 = 1 << 4,
|
||||
eDYNAMIC_BODY0 = 1 << 5,
|
||||
eDYNAMIC_BODY1 = 1 << 6,
|
||||
eSOFT_BODY = 1 << 7,
|
||||
eMODIFIABLE_CONTACT = 1 << 8,
|
||||
eFORCE_THRESHOLD = 1 << 9,
|
||||
eDETECT_DISCRETE_CONTACT = 1 << 10,
|
||||
eHAS_KINEMATIC_ACTOR = 1 << 11,
|
||||
eDISABLE_RESPONSE = 1 << 12,
|
||||
eDETECT_CCD_CONTACTS = 1 << 13,
|
||||
eDOMINANCE_0 = 1 << 14,
|
||||
eDOMINANCE_1 = 1 << 15,
|
||||
};
|
||||
};
|
||||
|
||||
struct PxcNpWorkUnitStatusFlag
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eHAS_NO_TOUCH = (1 << 0),
|
||||
eHAS_TOUCH = (1 << 1),
|
||||
//eHAS_SOLVER_CONSTRAINTS = (1 << 2),
|
||||
eREQUEST_CONSTRAINTS = (1 << 3),
|
||||
eHAS_CCD_RETOUCH = (1 << 4), // Marks pairs that are touching at a CCD pass and were touching at discrete collision or at a previous CCD pass already
|
||||
// but we can not tell whether they lost contact in a pass before. We send them as pure eNOTIFY_TOUCH_CCD events to the
|
||||
// contact report callback if requested.
|
||||
eDIRTY_MANAGER = (1 << 5),
|
||||
eREFRESHED_WITH_TOUCH = (1 << 6),
|
||||
eTOUCH_KNOWN = eHAS_NO_TOUCH | eHAS_TOUCH // The touch status is known (if narrowphase never ran for a pair then no flag will be set)
|
||||
};
|
||||
};
|
||||
|
||||
struct PxcNpWorkUnit
|
||||
{
|
||||
const PxsRigidCore* mRigidCore0; // INPUT //8
|
||||
const PxsRigidCore* mRigidCore1; // INPUT //16
|
||||
|
||||
private:
|
||||
const void* mShapeCoreAndType0; // INPUT //24
|
||||
const void* mShapeCoreAndType1; // INPUT //32
|
||||
public:
|
||||
|
||||
PxU8* mCCDContacts; // OUTPUT //40
|
||||
PxU8* mFrictionDataPtr; // INOUT //48
|
||||
|
||||
PxU16 mFlags; // INPUT //50
|
||||
PxU8 mFrictionPatchCount; // INOUT //51
|
||||
PxU8 mStatusFlags; // OUTPUT (see PxcNpWorkUnitStatusFlag) //52
|
||||
|
||||
PxReal mRestDistance; // INPUT //56
|
||||
|
||||
PxU32 mTransformCache0; // //60
|
||||
PxU32 mTransformCache1; // //64
|
||||
|
||||
IG::EdgeIndex mEdgeIndex; //inout the island gen edge index //68
|
||||
PxU32 mNpIndex; //INPUT //72
|
||||
|
||||
PxReal mTorsionalPatchRadius; //76
|
||||
PxReal mMinTorsionalPatchRadius; //80
|
||||
PxReal mOffsetSlop; //84
|
||||
//88 pading
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PX_FORCE_INLINE const void* encode(const PxsShapeCore* shapeCore)
|
||||
{
|
||||
const PxU64 type = PxU64(shapeCore->mGeometry.getType());
|
||||
PxU64 data = PxU64(shapeCore);
|
||||
PX_ASSERT(!(data & 15));
|
||||
data |= type;
|
||||
return reinterpret_cast<const void*>(data);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setShapeCore0(const PxsShapeCore* shapeCore)
|
||||
{
|
||||
mShapeCoreAndType0 = encode(shapeCore);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setShapeCore1(const PxsShapeCore* shapeCore)
|
||||
{
|
||||
mShapeCoreAndType1 = encode(shapeCore);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE const PxsShapeCore* getShapeCore0() const
|
||||
{
|
||||
return reinterpret_cast<const PxsShapeCore*>(PxU64(mShapeCoreAndType0) & ~15);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE const PxsShapeCore* getShapeCore1() const
|
||||
{
|
||||
return reinterpret_cast<const PxsShapeCore*>(PxU64(mShapeCoreAndType1) & ~15);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxGeometryType::Enum getGeomType0() const
|
||||
{
|
||||
return PxGeometryType::Enum(PxU64(mShapeCoreAndType0) & 15);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxGeometryType::Enum getGeomType1() const
|
||||
{
|
||||
return PxGeometryType::Enum(PxU64(mShapeCoreAndType1) & 15);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PX_FORCE_INLINE PxU8 getDominance0() const
|
||||
{
|
||||
return (mFlags & PxcNpWorkUnitFlag::eDOMINANCE_0) ? 0 : 1;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setDominance0(PxU8 v)
|
||||
{
|
||||
if(v==0)
|
||||
mFlags |= PxcNpWorkUnitFlag::eDOMINANCE_0;
|
||||
else
|
||||
mFlags &= ~PxcNpWorkUnitFlag::eDOMINANCE_0;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxU8 getDominance1() const
|
||||
{
|
||||
return (mFlags & PxcNpWorkUnitFlag::eDOMINANCE_1) ? 0 : 1;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setDominance1(PxU8 v)
|
||||
{
|
||||
if(v==0)
|
||||
mFlags |= PxcNpWorkUnitFlag::eDOMINANCE_1;
|
||||
else
|
||||
mFlags &= ~PxcNpWorkUnitFlag::eDOMINANCE_1;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setInvMassScaleFromDominance(PxConstraintInvMassScale& invMassScales) const
|
||||
{
|
||||
const PxReal dominance0 = getDominance0() ? 1.0f : 0.0f;
|
||||
const PxReal dominance1 = getDominance1() ? 1.0f : 0.0f;
|
||||
|
||||
invMassScales.linear0 = invMassScales.angular0 = dominance0;
|
||||
invMassScales.linear1 = invMassScales.angular1 = dominance1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PX_FORCE_INLINE void clearCachedState()
|
||||
{
|
||||
mFrictionDataPtr = NULL;
|
||||
mFrictionPatchCount = 0;
|
||||
mCCDContacts = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
137
engine/third_party/physx/source/lowlevel/common/include/utils/PxcScratchAllocator.h
vendored
Normal file
137
engine/third_party/physx/source/lowlevel/common/include/utils/PxcScratchAllocator.h
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef PXC_SCRATCH_ALLOCATOR_H
|
||||
#define PXC_SCRATCH_ALLOCATOR_H
|
||||
|
||||
#include "foundation/PxAssert.h"
|
||||
#include "PxvConfig.h"
|
||||
#include "foundation/PxMutex.h"
|
||||
#include "foundation/PxArray.h"
|
||||
#include "foundation/PxAllocator.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxcScratchAllocator : public PxUserAllocated
|
||||
{
|
||||
PX_NOCOPY(PxcScratchAllocator)
|
||||
public:
|
||||
PxcScratchAllocator() : mStack("PxcScratchAllocator"), mStart(NULL), mSize(0)
|
||||
{
|
||||
mStack.reserve(64);
|
||||
mStack.pushBack(0);
|
||||
}
|
||||
|
||||
void setBlock(void* addr, PxU32 size)
|
||||
{
|
||||
PX_ASSERT(!(size&15));
|
||||
|
||||
// if the stack is not empty then some scratch memory was not freed on the previous frame. That's
|
||||
// likely indicative of a problem, because when the scratch block is too small the memory will have
|
||||
// come from the heap
|
||||
|
||||
PX_ASSERT(mStack.size()==1);
|
||||
mStack.popBack();
|
||||
|
||||
mStart = reinterpret_cast<PxU8*>(addr);
|
||||
mSize = size;
|
||||
mStack.pushBack(mStart + size);
|
||||
}
|
||||
|
||||
void* allocAll(PxU32& size)
|
||||
{
|
||||
PxMutex::ScopedLock lock(mLock);
|
||||
PX_ASSERT(mStack.size()>0);
|
||||
size = PxU32(mStack.back()-mStart);
|
||||
|
||||
if(size==0)
|
||||
return NULL;
|
||||
|
||||
mStack.pushBack(mStart);
|
||||
return mStart;
|
||||
}
|
||||
|
||||
void* alloc(PxU32 requestedSize, bool fallBackToHeap = false)
|
||||
{
|
||||
requestedSize = (requestedSize+15)&~15;
|
||||
|
||||
PxMutex::ScopedLock lock(mLock);
|
||||
PX_ASSERT(mStack.size()>=1);
|
||||
|
||||
PxU8* top = mStack.back();
|
||||
|
||||
if(top - mStart >= ptrdiff_t(requestedSize))
|
||||
{
|
||||
PxU8* addr = top - requestedSize;
|
||||
mStack.pushBack(addr);
|
||||
return addr;
|
||||
}
|
||||
|
||||
if(!fallBackToHeap)
|
||||
return NULL;
|
||||
|
||||
return PX_ALLOC(requestedSize, "Scratch Block Fallback");
|
||||
}
|
||||
|
||||
void free(void* addr)
|
||||
{
|
||||
PX_ASSERT(addr!=NULL);
|
||||
if(!isScratchAddr(addr))
|
||||
{
|
||||
PX_FREE(addr);
|
||||
return;
|
||||
}
|
||||
|
||||
PxMutex::ScopedLock lock(mLock);
|
||||
PX_ASSERT(mStack.size()>1);
|
||||
|
||||
PxU32 i=mStack.size()-1;
|
||||
while(mStack[i]<addr)
|
||||
i--;
|
||||
|
||||
PX_ASSERT(mStack[i]==addr);
|
||||
mStack.remove(i);
|
||||
}
|
||||
|
||||
bool isScratchAddr(void* addr) const
|
||||
{
|
||||
PxU8* a = reinterpret_cast<PxU8*>(addr);
|
||||
return a>= mStart && a<mStart+mSize;
|
||||
}
|
||||
|
||||
private:
|
||||
PxMutex mLock;
|
||||
PxArray<PxU8*> mStack;
|
||||
PxU8* mStart;
|
||||
PxU32 mSize;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
148
engine/third_party/physx/source/lowlevel/common/include/utils/PxcThreadCoherentCache.h
vendored
Normal file
148
engine/third_party/physx/source/lowlevel/common/include/utils/PxcThreadCoherentCache.h
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
// 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 PXC_THREAD_COHERENT_CACHE_H
|
||||
#define PXC_THREAD_COHERENT_CACHE_H
|
||||
|
||||
#include "foundation/PxMutex.h"
|
||||
#include "foundation/PxAllocator.h"
|
||||
#include "foundation/PxSList.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
class PxsContext;
|
||||
/*!
|
||||
Controls a pool of large objects which must be thread safe.
|
||||
Tries to return the object most recently used by the thread(for better cache coherancy).
|
||||
Assumes the object has a default contructor.
|
||||
|
||||
(Note the semantics are different to a pool because we dont want to construct/destroy each time
|
||||
an object is requested, which may be expensive).
|
||||
|
||||
TODO: add thread coherancy.
|
||||
*/
|
||||
template<class T, class Params>
|
||||
class PxcThreadCoherentCache : public PxAlignedAllocator<16, PxReflectionAllocator<T> >
|
||||
{
|
||||
typedef PxAlignedAllocator<16, PxReflectionAllocator<T> > Allocator;
|
||||
PX_NOCOPY(PxcThreadCoherentCache)
|
||||
public:
|
||||
|
||||
typedef PxSListEntry EntryBase;
|
||||
|
||||
PX_INLINE PxcThreadCoherentCache(Params* params, const Allocator& alloc = Allocator()) : Allocator(alloc), mParams(params)
|
||||
{
|
||||
}
|
||||
|
||||
PX_INLINE ~PxcThreadCoherentCache()
|
||||
{
|
||||
T* np = static_cast<T*>(root.pop());
|
||||
|
||||
while(np!=NULL)
|
||||
{
|
||||
np->~T();
|
||||
Allocator::deallocate(np);
|
||||
np = static_cast<T*>(root.pop());
|
||||
}
|
||||
}
|
||||
|
||||
PX_INLINE T* get()
|
||||
{
|
||||
T* rv = static_cast<T*>(root.pop());
|
||||
if(rv==NULL)
|
||||
{
|
||||
rv = reinterpret_cast<T*>(Allocator::allocate(sizeof(T), PX_FL));
|
||||
PX_PLACEMENT_NEW(rv, T(mParams));
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PX_INLINE void put(T* item)
|
||||
{
|
||||
root.push(*item);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
PxSList root;
|
||||
Params* mParams;
|
||||
|
||||
template<class T2, class P2>
|
||||
friend class PxcThreadCoherentCacheIterator;
|
||||
};
|
||||
|
||||
/*!
|
||||
Used to iterate over all objects controlled by the cache.
|
||||
|
||||
Note: The iterator flushes the cache(extracts all items on construction and adds them back on
|
||||
destruction so we can iterate the list in a safe manner).
|
||||
*/
|
||||
template<class T, class Params>
|
||||
class PxcThreadCoherentCacheIterator
|
||||
{
|
||||
public:
|
||||
PxcThreadCoherentCacheIterator(PxcThreadCoherentCache<T, Params>& cache) : mCache(cache)
|
||||
{
|
||||
mNext = cache.root.flush();
|
||||
mFirst = mNext;
|
||||
}
|
||||
~PxcThreadCoherentCacheIterator()
|
||||
{
|
||||
PxSListEntry* np = mFirst;
|
||||
while(np != NULL)
|
||||
{
|
||||
PxSListEntry* npNext = np->next();
|
||||
mCache.root.push(*np);
|
||||
np = npNext;
|
||||
}
|
||||
}
|
||||
|
||||
PX_INLINE T* getNext()
|
||||
{
|
||||
if(mNext == NULL)
|
||||
return NULL;
|
||||
|
||||
T* rv = static_cast<T*>(mNext);
|
||||
mNext = mNext->next();
|
||||
|
||||
return rv;
|
||||
}
|
||||
private:
|
||||
|
||||
PxcThreadCoherentCacheIterator<T, Params>& operator=(const PxcThreadCoherentCacheIterator<T, Params>&);
|
||||
PxcThreadCoherentCache<T, Params> &mCache;
|
||||
PxSListEntry* mNext;
|
||||
PxSListEntry* mFirst;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
484
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcContactCache.cpp
vendored
Normal file
484
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcContactCache.cpp
vendored
Normal file
@@ -0,0 +1,484 @@
|
||||
// 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 "PxcContactCache.h"
|
||||
#include "PxcNpThreadContext.h"
|
||||
#include "foundation/PxUtilities.h"
|
||||
#include "PxcNpCache.h"
|
||||
#include "CmMatrix34.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
using namespace Cm;
|
||||
|
||||
//#define ENABLE_CONTACT_CACHE_STATS
|
||||
|
||||
#ifdef ENABLE_CONTACT_CACHE_STATS
|
||||
static PxU32 gNbCalls;
|
||||
static PxU32 gNbHits;
|
||||
#endif
|
||||
|
||||
void PxcClearContactCacheStats()
|
||||
{
|
||||
#ifdef ENABLE_CONTACT_CACHE_STATS
|
||||
gNbCalls = 0;
|
||||
gNbHits = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void PxcDisplayContactCacheStats()
|
||||
{
|
||||
#ifdef ENABLE_CONTACT_CACHE_STATS
|
||||
pxPrintf("%d|%d (%f)\n", gNbHits, gNbCalls, gNbCalls ? float(gNbHits)/float(gNbCalls) : 0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace physx
|
||||
{
|
||||
const bool g_CanUseContactCache[][PxGeometryType::eGEOMETRY_COUNT] =
|
||||
{
|
||||
//PxGeometryType::eSPHERE
|
||||
{
|
||||
false, //PxcContactSphereSphere
|
||||
false, //PxcContactSpherePlane
|
||||
true, //PxcContactSphereCapsule
|
||||
false, //PxcContactSphereBox
|
||||
false, //PxConvexCoreGeometry
|
||||
true, //PxcContactSphereConvex
|
||||
false, //ParticleSystem
|
||||
true, //SoftBody
|
||||
true, //PxcContactSphereMesh
|
||||
true, //PxcContactSphereHeightField
|
||||
false, //PxcContactGeometryCustomGeometry
|
||||
},
|
||||
|
||||
//PxGeometryType::ePLANE
|
||||
{
|
||||
false, //-
|
||||
false, //PxcInvalidContactPair
|
||||
true, //PxcContactPlaneCapsule
|
||||
true, //PxcContactPlaneBox
|
||||
false, //PxConvexCoreGeometry
|
||||
true, //PxcContactPlaneConvex
|
||||
false, //ParticleSystem
|
||||
true, //SoftBody
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcContactGeometryCustomGeometry
|
||||
},
|
||||
|
||||
//PxGeometryType::eCAPSULE
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
true, //PxcContactCapsuleCapsule
|
||||
true, //PxcContactCapsuleBox
|
||||
false, //PxConvexCoreGeometry
|
||||
true, //PxcContactCapsuleConvex
|
||||
false, //ParticleSystem
|
||||
true, //SoftBody
|
||||
true, //PxcContactCapsuleMesh
|
||||
true, //PxcContactCapsuleHeightField
|
||||
false, //PxcContactGeometryCustomGeometry
|
||||
},
|
||||
|
||||
//PxGeometryType::eBOX
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
true, //PxcContactBoxBox
|
||||
false, //PxConvexCoreGeometry
|
||||
true, //PxcContactBoxConvex
|
||||
false, //ParticleSystem
|
||||
true, //SoftBody
|
||||
true, //PxcContactBoxMesh
|
||||
true, //PxcContactBoxHeightField
|
||||
false, //PxcContactGeometryCustomGeometry
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXCORE
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //PxConvexCoreGeometry
|
||||
false, //PxcContactBoxConvex
|
||||
false, //ParticleSystem
|
||||
false, //SoftBody
|
||||
false, //PxcContactBoxMesh
|
||||
false, //PxcContactBoxHeightField
|
||||
false, //PxcContactGeometryCustomGeometry
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXMESH
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
true, //PxcContactConvexConvex
|
||||
false, //-
|
||||
true, //-
|
||||
true, //PxcContactConvexMesh2
|
||||
true, //PxcContactConvexHeightField
|
||||
false, //PxcContactGeometryCustomGeometry
|
||||
},
|
||||
|
||||
//PxGeometryType::ePARTICLESYSTEM
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
},
|
||||
|
||||
//PxGeometryType::eTETRAHEDRONMESH
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
},
|
||||
|
||||
//PxGeometryType::eTRIANGLEMESH
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
true, //-
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
},
|
||||
|
||||
//PxGeometryType::eHEIGHTFIELD
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
true, //-
|
||||
false, //-
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
},
|
||||
|
||||
//PxGeometryType::eCUSTOM
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
true, //-
|
||||
false, //-
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
},
|
||||
};
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(g_CanUseContactCache) / sizeof(g_CanUseContactCache[0]) == PxGeometryType::eGEOMETRY_COUNT);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void updateContact( PxContactPoint& dst, const PxcLocalContactsCache& contactsData,
|
||||
const PxMat34& world0, const PxMat34& world1,
|
||||
const PxVec3& point, const PxVec3& normal, float separation)
|
||||
{
|
||||
const PxVec3 tmp0 = contactsData.mTransform0.transformInv(point);
|
||||
const PxVec3 worldpt0 = world0.transform(tmp0);
|
||||
|
||||
const PxVec3 tmp1 = contactsData.mTransform1.transformInv(point);
|
||||
const PxVec3 worldpt1 = world1.transform(tmp1);
|
||||
|
||||
const PxVec3 motion = worldpt0 - worldpt1;
|
||||
dst.normal = normal;
|
||||
dst.point = (worldpt0 + worldpt1)*0.5f;
|
||||
//dst.point = point;
|
||||
dst.separation = separation + motion.dot(normal);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void prefetchData128(PxU8* PX_RESTRICT ptr, PxU32 size)
|
||||
{
|
||||
// PT: always prefetch the cache line containing our address (which unfortunately won't be aligned to 128 most of the time)
|
||||
PxPrefetchLine(ptr, 0);
|
||||
// PT: compute start offset of our data within its cache line
|
||||
const PxU32 startOffset = PxU32(size_t(ptr)&127);
|
||||
// PT: prefetch next cache line if needed
|
||||
if(startOffset+size>128)
|
||||
PxPrefetchLine(ptr+128, 0);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxU8* outputToCache(PxU8* PX_RESTRICT bytes, const PxVec3& v)
|
||||
{
|
||||
*reinterpret_cast<PxVec3*>(bytes) = v;
|
||||
return bytes + sizeof(PxVec3);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxU8* outputToCache(PxU8* PX_RESTRICT bytes, PxReal v)
|
||||
{
|
||||
*reinterpret_cast<PxReal*>(bytes) = v;
|
||||
return bytes + sizeof(PxReal);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxU8* outputToCache(PxU8* PX_RESTRICT bytes, PxU32 v)
|
||||
{
|
||||
*reinterpret_cast<PxU32*>(bytes) = v;
|
||||
return bytes + sizeof(PxU32);
|
||||
}
|
||||
|
||||
//PxU32 gContactCache_NbCalls = 0;
|
||||
//PxU32 gContactCache_NbHits = 0;
|
||||
|
||||
static PX_FORCE_INLINE PxReal maxComponentDeltaPos(const PxTransform& t0, const PxTransform& t1)
|
||||
{
|
||||
PxReal delta = PxAbs(t0.p.x - t1.p.x);
|
||||
delta = PxMax(delta, PxAbs(t0.p.y - t1.p.y));
|
||||
delta = PxMax(delta, PxAbs(t0.p.z - t1.p.z));
|
||||
return delta;
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxReal maxComponentDeltaRot(const PxTransform& t0, const PxTransform& t1)
|
||||
{
|
||||
PxReal delta = PxAbs(t0.q.x - t1.q.x);
|
||||
delta = PxMax(delta, PxAbs(t0.q.y - t1.q.y));
|
||||
delta = PxMax(delta, PxAbs(t0.q.z - t1.q.z));
|
||||
delta = PxMax(delta, PxAbs(t0.q.w - t1.q.w));
|
||||
return delta;
|
||||
}
|
||||
|
||||
bool physx::PxcCacheLocalContacts( PxcNpThreadContext& context, Cache& pairContactCache,
|
||||
const PxTransform32& tm0, const PxTransform32& tm1,
|
||||
const PxcContactMethod conMethod,
|
||||
const PxGeometry& shape0, const PxGeometry& shape1)
|
||||
{
|
||||
const NarrowPhaseParams& params = context.mNarrowPhaseParams;
|
||||
|
||||
// gContactCache_NbCalls++;
|
||||
|
||||
if(pairContactCache.mCachedData)
|
||||
prefetchData128(pairContactCache.mCachedData, pairContactCache.mCachedSize);
|
||||
|
||||
PxContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
contactBuffer.reset();
|
||||
|
||||
PxcLocalContactsCache contactsData;
|
||||
PxU32 nbCachedBytes;
|
||||
const PxU8* cachedBytes = PxcNpCacheRead2(pairContactCache, contactsData, nbCachedBytes);
|
||||
|
||||
pairContactCache.mCachedData = NULL;
|
||||
pairContactCache.mCachedSize = 0;
|
||||
|
||||
#ifdef ENABLE_CONTACT_CACHE_STATS
|
||||
gNbCalls++;
|
||||
#endif
|
||||
|
||||
const PxU32 payloadSize = (sizeof(PxcLocalContactsCache)+3)&~3;
|
||||
|
||||
if(cachedBytes)
|
||||
{
|
||||
// PT: we used to store the relative TM but it's better to save memory and recompute it
|
||||
const PxTransform t0to1 = tm1.transformInv(tm0);
|
||||
const PxTransform relTM = contactsData.mTransform1.transformInv(contactsData.mTransform0);
|
||||
|
||||
const PxReal epsilon = 0.01f;
|
||||
if( maxComponentDeltaPos(t0to1, relTM)<epsilon*params.mToleranceLength
|
||||
&& maxComponentDeltaRot(t0to1, relTM)<epsilon)
|
||||
{
|
||||
// gContactCache_NbHits++;
|
||||
const PxU32 nbContacts = contactsData.mNbCachedContacts;
|
||||
|
||||
PxU8* ls = PxcNpCacheWriteInitiate(context.mNpCacheStreamPair, pairContactCache, contactsData, nbCachedBytes);
|
||||
prefetchData128(ls, (payloadSize + 4 + nbCachedBytes + 0xF)&~0xF);
|
||||
|
||||
contactBuffer.count = nbContacts;
|
||||
if(nbContacts)
|
||||
{
|
||||
PxContactPoint* PX_RESTRICT dst = contactBuffer.contacts;
|
||||
|
||||
const Matrix34FromTransform world1(tm1);
|
||||
const Matrix34FromTransform world0(tm0);
|
||||
|
||||
const bool sameNormal = contactsData.mSameNormal;
|
||||
|
||||
const PxU8* contacts = reinterpret_cast<const PxU8*>(cachedBytes);
|
||||
const PxVec3* normal0 = NULL;
|
||||
for(PxU32 i=0;i<nbContacts;i++)
|
||||
{
|
||||
if(i!=nbContacts-1)
|
||||
PxPrefetchLine(contacts, 128);
|
||||
|
||||
const PxVec3* cachedNormal;
|
||||
if(!i || !sameNormal)
|
||||
{
|
||||
cachedNormal = reinterpret_cast<const PxVec3*>(contacts); contacts += sizeof(PxVec3);
|
||||
normal0 = cachedNormal;
|
||||
}
|
||||
else
|
||||
{
|
||||
cachedNormal = normal0;
|
||||
}
|
||||
|
||||
const PxVec3* cachedPoint = reinterpret_cast<const PxVec3*>(contacts); contacts += sizeof(PxVec3);
|
||||
const PxReal* cachedPD = reinterpret_cast<const PxReal*>(contacts); contacts += sizeof(PxReal);
|
||||
|
||||
updateContact(*dst, contactsData, world0, world1, *cachedPoint, *cachedNormal, *cachedPD);
|
||||
|
||||
if(contactsData.mUseFaceIndices)
|
||||
{
|
||||
const PxU32* cachedIndex1 = reinterpret_cast<const PxU32*>(contacts); contacts += sizeof(PxU32);
|
||||
|
||||
dst->internalFaceIndex1 = *cachedIndex1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst->internalFaceIndex1 = PXC_CONTACT_NO_FACE_INDEX;
|
||||
}
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
if(ls)
|
||||
PxcNpCacheWriteFinalize(ls, contactsData, nbCachedBytes, cachedBytes);
|
||||
#ifdef ENABLE_CONTACT_CACHE_STATS
|
||||
gNbHits++;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// PT: if we reach this point we cached the contacts but we couldn't use them next frame
|
||||
// => waste of time and memory
|
||||
}
|
||||
}
|
||||
|
||||
conMethod(shape0, shape1, tm0, tm1, params, pairContactCache, context.mContactBuffer, &context.mRenderOutput);
|
||||
|
||||
//if(contactBuffer.count)
|
||||
{
|
||||
contactsData.mTransform0 = tm0;
|
||||
contactsData.mTransform1 = tm1;
|
||||
|
||||
PxU32 nbBytes = 0;
|
||||
const PxU8* bytes = NULL;
|
||||
const PxU32 count = contactBuffer.count;
|
||||
if(count)
|
||||
{
|
||||
const bool useFaceIndices = contactBuffer.contacts[0].internalFaceIndex1!=PXC_CONTACT_NO_FACE_INDEX;
|
||||
contactsData.mNbCachedContacts = PxTo16(count);
|
||||
contactsData.mUseFaceIndices = useFaceIndices;
|
||||
|
||||
const PxContactPoint* PX_RESTRICT srcContacts = contactBuffer.contacts;
|
||||
// PT: this loop should not be here. We should output the contacts directly compressed, as we used to.
|
||||
bool sameNormal = true;
|
||||
{
|
||||
const PxVec3 normal0 = srcContacts->normal;
|
||||
for(PxU32 i=1;i<count;i++)
|
||||
{
|
||||
if(srcContacts[i].normal!=normal0)
|
||||
{
|
||||
sameNormal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
contactsData.mSameNormal = sameNormal;
|
||||
|
||||
if(!sameNormal)
|
||||
{
|
||||
const PxU32 sizeof_CachedContactPoint = sizeof(PxVec3) + sizeof(PxVec3) + sizeof(PxReal);
|
||||
const PxU32 sizeof_CachedContactPointAndFaceIndices = sizeof_CachedContactPoint + sizeof(PxU32);
|
||||
const PxU32 sizeOfItem = useFaceIndices ? sizeof_CachedContactPointAndFaceIndices : sizeof_CachedContactPoint;
|
||||
nbBytes = count * sizeOfItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU32 sizeof_CachedContactPoint = sizeof(PxVec3) + sizeof(PxReal);
|
||||
const PxU32 sizeof_CachedContactPointAndFaceIndices = sizeof_CachedContactPoint + sizeof(PxU32);
|
||||
const PxU32 sizeOfItem = useFaceIndices ? sizeof_CachedContactPointAndFaceIndices : sizeof_CachedContactPoint;
|
||||
nbBytes = sizeof(PxVec3) + count * sizeOfItem;
|
||||
}
|
||||
PxU8* ls = PxcNpCacheWriteInitiate(context.mNpCacheStreamPair, pairContactCache, contactsData, nbBytes);
|
||||
if(ls)
|
||||
{
|
||||
*reinterpret_cast<PxcLocalContactsCache*>(ls) = contactsData;
|
||||
*reinterpret_cast<PxU32*>(ls+payloadSize) = nbBytes;
|
||||
bytes = ls+payloadSize+sizeof(PxU32);
|
||||
PxU8* dest = const_cast<PxU8*>(bytes);
|
||||
for(PxU32 i=0;i<count;i++)
|
||||
{
|
||||
if(!i || !sameNormal)
|
||||
dest = outputToCache(dest, srcContacts[i].normal);
|
||||
dest = outputToCache(dest, srcContacts[i].point);
|
||||
dest = outputToCache(dest, srcContacts[i].separation);
|
||||
if(useFaceIndices)
|
||||
{
|
||||
dest = outputToCache(dest, srcContacts[i].internalFaceIndex1);
|
||||
}
|
||||
}
|
||||
PX_ASSERT(size_t(dest) - size_t(bytes)==nbBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
contactsData.mNbCachedContacts = 0;
|
||||
PxcNpCacheWrite(context.mNpCacheStreamPair, pairContactCache, contactsData, 0, bytes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
contactsData.mNbCachedContacts = 0;
|
||||
contactsData.mUseFaceIndices = false;
|
||||
contactsData.mSameNormal = false;
|
||||
PxcNpCacheWrite(context.mNpCacheStreamPair, pairContactCache, contactsData, nbBytes, bytes);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
443
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcContactMethodImpl.cpp
vendored
Normal file
443
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcContactMethodImpl.cpp
vendored
Normal file
@@ -0,0 +1,443 @@
|
||||
// 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 "geometry/PxGeometry.h"
|
||||
#include "PxcContactMethodImpl.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
#define ARGS shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput
|
||||
|
||||
static bool PxcInvalidContactPair (GU_CONTACT_METHOD_ARGS_UNUSED) { return false; }
|
||||
|
||||
// PT: IMPORTANT: do NOT remove the indirection! Using the Gu functions directly in the table produces massive perf problems.
|
||||
static bool PxcContactSphereSphere (GU_CONTACT_METHOD_ARGS) { return contactSphereSphere(ARGS); }
|
||||
static bool PxcContactSphereCapsule (GU_CONTACT_METHOD_ARGS) { return contactSphereCapsule(ARGS); }
|
||||
static bool PxcContactSphereBox (GU_CONTACT_METHOD_ARGS) { return contactSphereBox(ARGS); }
|
||||
static bool PxcContactSpherePlane (GU_CONTACT_METHOD_ARGS) { return contactSpherePlane(ARGS); }
|
||||
static bool PxcContactSphereConvex (GU_CONTACT_METHOD_ARGS) { return contactCapsuleConvex(ARGS); }
|
||||
static bool PxcContactSphereMesh (GU_CONTACT_METHOD_ARGS) { return contactSphereMesh(ARGS); }
|
||||
static bool PxcContactSphereHeightField (GU_CONTACT_METHOD_ARGS) { return contactSphereHeightfield(ARGS); }
|
||||
static bool PxcContactPlaneBox (GU_CONTACT_METHOD_ARGS) { return contactPlaneBox(ARGS); }
|
||||
static bool PxcContactPlaneCapsule (GU_CONTACT_METHOD_ARGS) { return contactPlaneCapsule(ARGS); }
|
||||
static bool PxcContactPlaneConvexCore (GU_CONTACT_METHOD_ARGS) { return contactPlaneConvexCore(ARGS); }
|
||||
static bool PxcContactPlaneConvex (GU_CONTACT_METHOD_ARGS) { return contactPlaneConvex(ARGS); }
|
||||
static bool PxcContactPlaneMesh (GU_CONTACT_METHOD_ARGS) { return contactPlaneMesh(ARGS); }
|
||||
static bool PxcContactCapsuleCapsule (GU_CONTACT_METHOD_ARGS) { return contactCapsuleCapsule(ARGS); }
|
||||
static bool PxcContactCapsuleBox (GU_CONTACT_METHOD_ARGS) { return contactCapsuleBox(ARGS); }
|
||||
static bool PxcContactCapsuleConvex (GU_CONTACT_METHOD_ARGS) { return contactCapsuleConvex(ARGS); }
|
||||
static bool PxcContactCapsuleMesh (GU_CONTACT_METHOD_ARGS) { return contactCapsuleMesh(ARGS); }
|
||||
static bool PxcContactCapsuleHeightField (GU_CONTACT_METHOD_ARGS) { return contactCapsuleHeightfield(ARGS); }
|
||||
static bool PxcContactBoxBox (GU_CONTACT_METHOD_ARGS) { return contactBoxBox(ARGS); }
|
||||
static bool PxcContactBoxConvex (GU_CONTACT_METHOD_ARGS) { return contactBoxConvex(ARGS); }
|
||||
static bool PxcContactBoxMesh (GU_CONTACT_METHOD_ARGS) { return contactBoxMesh(ARGS); }
|
||||
static bool PxcContactBoxHeightField (GU_CONTACT_METHOD_ARGS) { return contactBoxHeightfield(ARGS); }
|
||||
static bool PxcContactConvexCoreConvex (GU_CONTACT_METHOD_ARGS) { return contactConvexCoreConvex(ARGS); }
|
||||
static bool PxcContactConvexConvex (GU_CONTACT_METHOD_ARGS) { return contactConvexConvex(ARGS); }
|
||||
static bool PxcContactConvexCoreTrimesh (GU_CONTACT_METHOD_ARGS) { return contactConvexCoreTrimesh(ARGS); }
|
||||
static bool PxcContactConvexCoreHeightfield (GU_CONTACT_METHOD_ARGS) { return contactConvexCoreHeightfield(ARGS); }
|
||||
static bool PxcContactConvexMesh (GU_CONTACT_METHOD_ARGS) { return contactConvexMesh(ARGS); }
|
||||
static bool PxcContactConvexHeightField (GU_CONTACT_METHOD_ARGS) { return contactConvexHeightfield(ARGS); }
|
||||
static bool PxcContactMeshMesh (GU_CONTACT_METHOD_ARGS) { return contactMeshMesh(ARGS); }
|
||||
static bool PxcContactGeometryCustomGeometry (GU_CONTACT_METHOD_ARGS) { return contactGeometryCustomGeometry(ARGS); }
|
||||
|
||||
static bool PxcPCMContactSphereSphere (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereSphere(ARGS); }
|
||||
static bool PxcPCMContactSpherePlane (GU_CONTACT_METHOD_ARGS) { return pcmContactSpherePlane(ARGS); }
|
||||
static bool PxcPCMContactSphereBox (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereBox(ARGS); }
|
||||
static bool PxcPCMContactSphereCapsule (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereCapsule(ARGS); }
|
||||
static bool PxcPCMContactSphereConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereConvex(ARGS); }
|
||||
static bool PxcPCMContactSphereMesh (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereMesh(ARGS); }
|
||||
static bool PxcPCMContactSphereHeightField (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereHeightField(ARGS); }
|
||||
static bool PxcPCMContactPlaneCapsule (GU_CONTACT_METHOD_ARGS) { return pcmContactPlaneCapsule(ARGS); }
|
||||
static bool PxcPCMContactPlaneBox (GU_CONTACT_METHOD_ARGS) { return pcmContactPlaneBox(ARGS); }
|
||||
static bool PxcPCMContactPlaneConvexCore (GU_CONTACT_METHOD_ARGS) { return contactPlaneConvexCore(ARGS); }
|
||||
static bool PxcPCMContactPlaneConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactPlaneConvex(ARGS); }
|
||||
static bool PxcPCMContactPlaneMesh (GU_CONTACT_METHOD_ARGS) { return contactPlaneMesh(ARGS); }
|
||||
static bool PxcPCMContactCapsuleCapsule (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleCapsule(ARGS); }
|
||||
static bool PxcPCMContactCapsuleBox (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleBox(ARGS); }
|
||||
static bool PxcPCMContactCapsuleConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleConvex(ARGS); }
|
||||
static bool PxcPCMContactCapsuleMesh (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleMesh(ARGS); }
|
||||
static bool PxcPCMContactCapsuleHeightField (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleHeightField(ARGS); }
|
||||
static bool PxcPCMContactBoxBox (GU_CONTACT_METHOD_ARGS) { return pcmContactBoxBox(ARGS); }
|
||||
static bool PxcPCMContactBoxConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactBoxConvex(ARGS); }
|
||||
static bool PxcPCMContactBoxMesh (GU_CONTACT_METHOD_ARGS) { return pcmContactBoxMesh(ARGS); }
|
||||
static bool PxcPCMContactBoxHeightField (GU_CONTACT_METHOD_ARGS) { return pcmContactBoxHeightField(ARGS); }
|
||||
static bool PxcPCMContactConvexCoreConvex (GU_CONTACT_METHOD_ARGS) { return contactConvexCoreConvex(ARGS); }
|
||||
static bool PxcPCMContactConvexConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactConvexConvex(ARGS); }
|
||||
static bool PxcPCMContactConvexCoreTrimesh (GU_CONTACT_METHOD_ARGS) { return contactConvexCoreTrimesh(ARGS); }
|
||||
static bool PxcPCMContactConvexCoreHeightfield (GU_CONTACT_METHOD_ARGS) { return contactConvexCoreHeightfield(ARGS); }
|
||||
static bool PxcPCMContactConvexMesh (GU_CONTACT_METHOD_ARGS) { return pcmContactConvexMesh(ARGS); }
|
||||
static bool PxcPCMContactConvexHeightField (GU_CONTACT_METHOD_ARGS) { return pcmContactConvexHeightField(ARGS); }
|
||||
static bool PxcPCMContactMeshMesh (GU_CONTACT_METHOD_ARGS) { return contactMeshMesh(ARGS); }
|
||||
static bool PxcPCMContactGeometryCustomGeometry (GU_CONTACT_METHOD_ARGS) { return pcmContactGeometryCustomGeometry(ARGS); }
|
||||
|
||||
#undef ARGS
|
||||
|
||||
namespace physx
|
||||
{
|
||||
//Table of contact methods for different shape-type combinations
|
||||
PxcContactMethod g_ContactMethodTable[][PxGeometryType::eGEOMETRY_COUNT] =
|
||||
{
|
||||
//PxGeometryType::eSPHERE
|
||||
{
|
||||
PxcContactSphereSphere, //PxGeometryType::eSPHERE
|
||||
PxcContactSpherePlane, //PxGeometryType::ePLANE
|
||||
PxcContactSphereCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcContactSphereBox, //PxGeometryType::eBOX
|
||||
PxcContactConvexCoreConvex, //PxGeometryType::eCONVEXCORE
|
||||
PxcContactSphereConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcContactSphereMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcContactSphereHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcContactGeometryCustomGeometry, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::ePLANE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
PxcInvalidContactPair, //PxGeometryType::ePLANE
|
||||
PxcContactPlaneCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcContactPlaneBox, //PxGeometryType::eBOX
|
||||
PxcContactPlaneConvexCore, //PxGeometryType::eCONVEXCORE
|
||||
PxcContactPlaneConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcContactPlaneMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcContactGeometryCustomGeometry, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eCAPSULE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
PxcContactCapsuleCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcContactCapsuleBox, //PxGeometryType::eBOX
|
||||
PxcContactConvexCoreConvex, //PxGeometryType::eCONVEXCORE
|
||||
PxcContactCapsuleConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcContactCapsuleMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcContactCapsuleHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcContactGeometryCustomGeometry, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eBOX
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
PxcContactBoxBox, //PxGeometryType::eBOX
|
||||
PxcContactConvexCoreConvex, //PxGeometryType::eCONVEXCORE
|
||||
PxcContactBoxConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcContactBoxMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcContactBoxHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcContactGeometryCustomGeometry, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXCORE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
PxcContactConvexCoreConvex, //PxGeometryType::eCONVEXCORE
|
||||
PxcContactConvexCoreConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcContactConvexCoreTrimesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcContactConvexCoreHeightfield,//PxGeometryType::eHEIGHTFIELD
|
||||
PxcInvalidContactPair, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
PxcContactConvexConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcContactConvexMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcContactConvexHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcContactGeometryCustomGeometry, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::ePARTICLESYSTEM
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcInvalidContactPair, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eTETRAHEDRONMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcInvalidContactPair, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eTRIANGLEMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::ePARTICLESYSTEM
|
||||
0, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcContactMeshMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcContactGeometryCustomGeometry, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eHEIGHTFIELD
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::ePARTICLESYSTEM
|
||||
0, //PxGeometryType::eTETRAHEDRONMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcContactGeometryCustomGeometry, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eCUSTOM
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::ePARTICLESYSTEM
|
||||
0, //PxGeometryType::eTETRAHEDRONMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
0, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcContactGeometryCustomGeometry, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
};
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(g_ContactMethodTable) / sizeof(g_ContactMethodTable[0]) == PxGeometryType::eGEOMETRY_COUNT);
|
||||
|
||||
//Table of contact methods for different shape-type combinations
|
||||
PxcContactMethod g_PCMContactMethodTable[][PxGeometryType::eGEOMETRY_COUNT] =
|
||||
{
|
||||
//PxGeometryType::eSPHERE
|
||||
{
|
||||
PxcPCMContactSphereSphere, //PxGeometryType::eSPHERE
|
||||
PxcPCMContactSpherePlane, //PxGeometryType::ePLANE
|
||||
PxcPCMContactSphereCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcPCMContactSphereBox, //PxGeometryType::eBOX
|
||||
PxcPCMContactConvexCoreConvex, //PxGeometryType::eCONVEXCORE
|
||||
PxcPCMContactSphereConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcPCMContactSphereMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcPCMContactSphereHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcPCMContactGeometryCustomGeometry, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::ePLANE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
PxcInvalidContactPair, //PxGeometryType::ePLANE
|
||||
PxcPCMContactPlaneCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcPCMContactPlaneBox, //PxGeometryType::eBOX
|
||||
PxcPCMContactPlaneConvexCore, //PxGeometryType::eCONVEXCORE
|
||||
PxcPCMContactPlaneConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcPCMContactPlaneMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcPCMContactGeometryCustomGeometry,//PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eCAPSULE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
PxcPCMContactCapsuleCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcPCMContactCapsuleBox, //PxGeometryType::eBOX
|
||||
PxcPCMContactConvexCoreConvex, //PxGeometryType::eCONVEXCORE
|
||||
PxcPCMContactCapsuleConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcPCMContactCapsuleMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcPCMContactCapsuleHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcPCMContactGeometryCustomGeometry, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eBOX
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
PxcPCMContactBoxBox, //PxGeometryType::eBOX
|
||||
PxcPCMContactConvexCoreConvex, //PxGeometryType::eCONVEXCORE
|
||||
PxcPCMContactBoxConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcPCMContactBoxMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcPCMContactBoxHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcPCMContactGeometryCustomGeometry, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXCORE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
PxcPCMContactConvexCoreConvex, //PxGeometryType::eCONVEXCORE
|
||||
PxcPCMContactConvexCoreConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcPCMContactConvexCoreTrimesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcPCMContactConvexCoreHeightfield, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcInvalidContactPair, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
PxcPCMContactConvexConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcPCMContactConvexMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcPCMContactConvexHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcPCMContactGeometryCustomGeometry, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::ePARTICLESYSTEM
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcInvalidContactPair, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eTETRAHEDRONMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcInvalidContactPair, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcInvalidContactPair, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eTRIANGLEMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::ePARTICLESYSTEM
|
||||
0, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcPCMContactMeshMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcPCMContactGeometryCustomGeometry,//PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eHEIGHTFIELD
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::ePARTICLESYSTEM
|
||||
0, //PxGeometryType::eTETRAHEDRONMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcPCMContactGeometryCustomGeometry,//PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eCUSTOM
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::ePARTICLESYSTEM
|
||||
0, //PxGeometryType::eTETRAHEDRONMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
0, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcPCMContactGeometryCustomGeometry,//PxGeometryType::eCUSTOM
|
||||
},
|
||||
};
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(g_PCMContactMethodTable) / sizeof(g_PCMContactMethodTable[0]) == PxGeometryType::eGEOMETRY_COUNT);
|
||||
|
||||
}
|
||||
444
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcMaterialMethodImpl.cpp
vendored
Normal file
444
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcMaterialMethodImpl.cpp
vendored
Normal file
@@ -0,0 +1,444 @@
|
||||
// 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 "PxcMaterialMethodImpl.h"
|
||||
#include "PxvGeometry.h"
|
||||
#include "PxcNpThreadContext.h"
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "GuTriangleMesh.h"
|
||||
#include "GuHeightField.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
// PT: moved these functions to same file for improving code locality and easily reusing code (calling smaller functions from larger ones, see below)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void PxcGetMaterialShape(const PxsShapeCore* shape, const PxU32 index, const PxContactBuffer& contactBuffer, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
const PxU16 materialIndex = shape->mMaterialIndex;
|
||||
const PxU32 count = contactBuffer.count;
|
||||
PX_ASSERT(index==0 || index==1);
|
||||
for(PxU32 i=0; i<count; i++)
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = materialIndex;
|
||||
}
|
||||
|
||||
static void PxcGetMaterialShapeShape(const PxsShapeCore* shape0, const PxsShapeCore* shape1, const PxContactBuffer& contactBuffer, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
const PxU16 materialIndex0 = shape0->mMaterialIndex;
|
||||
const PxU16 materialIndex1 = shape1->mMaterialIndex;
|
||||
const PxU32 count = contactBuffer.count;
|
||||
for(PxU32 i=0; i<count; i++)
|
||||
{
|
||||
materialInfo[i].mMaterialIndex0 = materialIndex0;
|
||||
materialInfo[i].mMaterialIndex1 = materialIndex1;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PX_FORCE_INLINE const PxU16* getMaterialIndicesLL(const PxTriangleMeshGeometry& meshGeom)
|
||||
{
|
||||
return static_cast<const Gu::TriangleMesh*>(meshGeom.triangleMesh)->getMaterials();
|
||||
}
|
||||
|
||||
static void PxcGetMaterialMesh(const PxsShapeCore* shape, const PxU32 index, const PxContactBuffer& contactBuffer, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
PX_ASSERT(index == 0 || index == 1);
|
||||
const PxTriangleMeshGeometryLL& shapeMesh = shape->mGeometry.get<const PxTriangleMeshGeometryLL>();
|
||||
if(shapeMesh.materialsLL.numIndices <= 1)
|
||||
{
|
||||
PxcGetMaterialShape(shape, index, contactBuffer, materialInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU32 count = contactBuffer.count;
|
||||
const PxU16* eaMaterialIndices = getMaterialIndicesLL(shapeMesh);
|
||||
const PxU16* indices = shapeMesh.materialsLL.indices;
|
||||
for(PxU32 i=0; i<count; i++)
|
||||
{
|
||||
const PxContactPoint& contact = contactBuffer.contacts[i];
|
||||
const PxU32 localMaterialIndex = eaMaterialIndices ? eaMaterialIndices[contact.internalFaceIndex1] : 0;//shapeMesh.triangleMesh->getTriangleMaterialIndex(contact.featureIndex1);
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = indices[localMaterialIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PxcGetMaterialShapeMesh(const PxsShapeCore* shape0, const PxsShapeCore* shape1, const PxContactBuffer& contactBuffer, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
const PxTriangleMeshGeometryLL& shapeMesh = shape1->mGeometry.get<const PxTriangleMeshGeometryLL>();
|
||||
if(shapeMesh.materialsLL.numIndices <= 1)
|
||||
{
|
||||
PxcGetMaterialShapeShape(shape0, shape1, contactBuffer, materialInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU32 count = contactBuffer.count;
|
||||
const PxU16* eaMaterialIndices = getMaterialIndicesLL(shapeMesh);
|
||||
const PxU16* indices = shapeMesh.materialsLL.indices;
|
||||
const PxU16 materialIndex0 = shape0->mMaterialIndex;
|
||||
for(PxU32 i=0; i<count; i++)
|
||||
{
|
||||
const PxContactPoint& contact = contactBuffer.contacts[i];
|
||||
materialInfo[i].mMaterialIndex0 = materialIndex0;
|
||||
|
||||
const PxU32 localMaterialIndex = eaMaterialIndices ? eaMaterialIndices[contact.internalFaceIndex1] : 0;//shapeMesh.triangleMesh->getTriangleMaterialIndex(contact.featureIndex1);
|
||||
materialInfo[i].mMaterialIndex1 = indices[localMaterialIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PxcGetMaterialSoftBodyMesh(const PxsShapeCore* shape0, const PxsShapeCore* shape1, const PxContactBuffer& contactBuffer, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
// PT: TODO: check this, it reads shape0 and labels it shapeMesh1? It's otherwise the same code as PxcGetMaterialShapeMesh ?
|
||||
const PxTriangleMeshGeometryLL& shapeMesh1 = shape0->mGeometry.get<const PxTriangleMeshGeometryLL>();
|
||||
if (shapeMesh1.materialsLL.numIndices <= 1)
|
||||
{
|
||||
PxcGetMaterialShapeShape(shape0, shape1, contactBuffer, materialInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU32 count = contactBuffer.count;
|
||||
const PxU16* eaMaterialIndices = getMaterialIndicesLL(shapeMesh1);
|
||||
const PxU16* indices = shapeMesh1.materialsLL.indices;
|
||||
const PxU16 materialIndex0 = shape0->mMaterialIndex;
|
||||
for (PxU32 i = 0; i<count; i++)
|
||||
{
|
||||
const PxContactPoint& contact = contactBuffer.contacts[i];
|
||||
materialInfo[i].mMaterialIndex0 = materialIndex0;
|
||||
|
||||
const PxU32 localMaterialIndex = eaMaterialIndices ? eaMaterialIndices[contact.internalFaceIndex1] : 0;//shapeMesh.triangleMesh->getTriangleMaterialIndex(contact.featureIndex1);
|
||||
//contact.featureIndex1 = shapeMesh.materials.indices[localMaterialIndex];
|
||||
materialInfo[i].mMaterialIndex1 = indices[localMaterialIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PxU32 getMaterialIndex(const Gu::HeightFieldData* hfData, PxU32 triangleIndex)
|
||||
{
|
||||
const PxU32 sampleIndex = triangleIndex >> 1;
|
||||
const bool isFirstTriangle = (triangleIndex & 0x1) == 0;
|
||||
|
||||
//get sample
|
||||
const PxHeightFieldSample* hf = &hfData->samples[sampleIndex];
|
||||
return isFirstTriangle ? hf->materialIndex0 : hf->materialIndex1;
|
||||
}
|
||||
|
||||
static void PxcGetMaterialHeightField(const PxsShapeCore* shape, const PxU32 index, const PxContactBuffer& contactBuffer, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
PX_ASSERT(index == 0 || index == 1);
|
||||
const PxHeightFieldGeometryLL& hfGeom = shape->mGeometry.get<const PxHeightFieldGeometryLL>();
|
||||
if(hfGeom.materialsLL.numIndices <= 1)
|
||||
{
|
||||
PxcGetMaterialShape(shape, index, contactBuffer, materialInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU32 count = contactBuffer.count;
|
||||
const PxU16* materialIndices = hfGeom.materialsLL.indices;
|
||||
|
||||
const Gu::HeightFieldData* hf = &static_cast<const Gu::HeightField*>(hfGeom.heightField)->getData();
|
||||
|
||||
for(PxU32 i=0; i<count; i++)
|
||||
{
|
||||
const PxContactPoint& contact = contactBuffer.contacts[i];
|
||||
const PxU32 localMaterialIndex = getMaterialIndex(hf, contact.internalFaceIndex1);
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = materialIndices[localMaterialIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PxcGetMaterialShapeHeightField(const PxsShapeCore* shape0, const PxsShapeCore* shape1, const PxContactBuffer& contactBuffer, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
const PxHeightFieldGeometryLL& hfGeom = shape1->mGeometry.get<const PxHeightFieldGeometryLL>();
|
||||
if(hfGeom.materialsLL.numIndices <= 1)
|
||||
{
|
||||
PxcGetMaterialShapeShape(shape0, shape1, contactBuffer, materialInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU32 count = contactBuffer.count;
|
||||
const PxU16* materialIndices = hfGeom.materialsLL.indices;
|
||||
|
||||
const Gu::HeightFieldData* hf = &static_cast<const Gu::HeightField*>(hfGeom.heightField)->getData();
|
||||
|
||||
for(PxU32 i=0; i<count; i++)
|
||||
{
|
||||
const PxContactPoint& contact = contactBuffer.contacts[i];
|
||||
materialInfo[i].mMaterialIndex0 = shape0->mMaterialIndex;
|
||||
//contact.featureIndex0 = shape0->materialIndex;
|
||||
const PxU32 localMaterialIndex = getMaterialIndex(hf, contact.internalFaceIndex1);
|
||||
//contact.featureIndex1 = materialIndices[localMaterialIndex];
|
||||
PX_ASSERT(localMaterialIndex<hfGeom.materialsLL.numIndices);
|
||||
materialInfo[i].mMaterialIndex1 = materialIndices[localMaterialIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void PxcGetMaterialSoftBodyHeightField(const PxsShapeCore* shape0, const PxsShapeCore* shape1, const PxContactBuffer& contactBuffer, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
const PxHeightFieldGeometryLL& hfGeom = shape1->mGeometry.get<const PxHeightFieldGeometryLL>();
|
||||
if (hfGeom.materialsLL.numIndices <= 1)
|
||||
{
|
||||
PxcGetMaterialShapeShape(shape0, shape1, contactBuffer, materialInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU32 count = contactBuffer.count;
|
||||
const PxU16* materialIndices = hfGeom.materialsLL.indices;
|
||||
|
||||
const Gu::HeightFieldData* hf = &static_cast<const Gu::HeightField*>(hfGeom.heightField)->getData();
|
||||
|
||||
for(PxU32 i=0; i<count; i++)
|
||||
{
|
||||
const PxContactPoint& contact = contactBuffer.contacts[i];
|
||||
materialInfo[i].mMaterialIndex0 = shape0->mMaterialIndex;
|
||||
//contact.featureIndex0 = shape0->materialIndex;
|
||||
const PxU32 localMaterialIndex = getMaterialIndex(hf, contact.internalFaceIndex1);
|
||||
//contact.featureIndex1 = materialIndices[localMaterialIndex];
|
||||
PX_ASSERT(localMaterialIndex<hfGeom.materialsLL.numIndices);
|
||||
materialInfo[i].mMaterialIndex1 = materialIndices[localMaterialIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void PxcGetMaterialSoftBody(const PxsShapeCore* shape, const PxU32 index, const PxContactBuffer& contactBuffer, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
PX_ASSERT(index == 1);
|
||||
PX_UNUSED(index);
|
||||
PxcGetMaterialShape(shape, index, contactBuffer, materialInfo);
|
||||
}
|
||||
|
||||
static void PxcGetMaterialShapeSoftBody(const PxsShapeCore* shape0, const PxsShapeCore* shape1, const PxContactBuffer& contactBuffer, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
PxcGetMaterialShapeShape(shape0, shape1, contactBuffer, materialInfo);
|
||||
}
|
||||
|
||||
static void PxcGetMaterialSoftBodySoftBody(const PxsShapeCore* shape0, const PxsShapeCore* shape1, const PxContactBuffer& contactBuffer, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
PxcGetMaterialShapeShape(shape0, shape1, contactBuffer, materialInfo);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace physx
|
||||
{
|
||||
PxcGetSingleMaterialMethod g_GetSingleMaterialMethodTable[] =
|
||||
{
|
||||
PxcGetMaterialShape, //PxGeometryType::eSPHERE
|
||||
PxcGetMaterialShape, //PxGeometryType::ePLANE
|
||||
PxcGetMaterialShape, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShape, //PxGeometryType::eCONVEXCORE
|
||||
PxcGetMaterialShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialSoftBody, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcGetMaterialSoftBody, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcGetMaterialMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcGetMaterialShape, //PxGeometryType::eCUSTOM
|
||||
};
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(g_GetSingleMaterialMethodTable) / sizeof(g_GetSingleMaterialMethodTable[0]) == PxGeometryType::eGEOMETRY_COUNT);
|
||||
|
||||
//Table of contact methods for different shape-type combinations
|
||||
PxcGetMaterialMethod g_GetMaterialMethodTable[][PxGeometryType::eGEOMETRY_COUNT] =
|
||||
{
|
||||
|
||||
//PxGeometryType::eSPHERE
|
||||
{
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eSPHERE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::ePLANE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXCORE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeSoftBody, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcGetMaterialShapeSoftBody, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::ePLANE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXCORE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeSoftBody, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcGetMaterialShapeSoftBody, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
0, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eCAPSULE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXCORE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeSoftBody, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcGetMaterialShapeSoftBody, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eBOX
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXCORE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeSoftBody, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcGetMaterialShapeSoftBody, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEX
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXCORE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeSoftBody, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcGetMaterialShapeSoftBody, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeSoftBody, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcGetMaterialShapeSoftBody, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::ePARTICLESYSTEM
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialSoftBodySoftBody, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcGetMaterialSoftBodySoftBody, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcGetMaterialSoftBodyMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialSoftBodyHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eTETRAHEDRONMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::ePARTICLESYSTEM
|
||||
PxcGetMaterialSoftBodySoftBody, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcGetMaterialSoftBodyMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialSoftBodyHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eTRIANGLEMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::ePARTICLESYSTEM
|
||||
0, //PxGeometryType::eTETRAHEDRONMESH
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eTRIANGLEMESH // mesh-mesh via SDF (single material)
|
||||
0, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eHEIGHTFIELD
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::ePARTICLESYSTEM
|
||||
0, //PxGeometryType::eTETRAHEDRONMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
0, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
//PxGeometryType::eCUSTOM
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXCORE
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::ePARTICLESYSTEM
|
||||
0, //PxGeometryType::eTETRAHEDRONMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
0, //PxGeometryType::eHEIGHTFIELD
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCUSTOM
|
||||
},
|
||||
|
||||
};
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(g_GetMaterialMethodTable) / sizeof(g_GetMaterialMethodTable[0]) == PxGeometryType::eGEOMETRY_COUNT);
|
||||
|
||||
}
|
||||
512
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcNpBatch.cpp
vendored
Normal file
512
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcNpBatch.cpp
vendored
Normal file
@@ -0,0 +1,512 @@
|
||||
// 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 "PxcNpBatch.h"
|
||||
#include "PxcNpCache.h"
|
||||
#include "common/PxProfileZone.h"
|
||||
#include "PxcNpWorkUnit.h"
|
||||
#include "PxcContactCache.h"
|
||||
#include "PxcNpContactPrepShared.h"
|
||||
#include "PxvGeometry.h"
|
||||
#include "CmTask.h"
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "PxsTransformCache.h"
|
||||
#include "PxsContactManagerState.h"
|
||||
#include "PxcNpThreadContext.h"
|
||||
#include "PxcMaterialMethodImpl.h"
|
||||
|
||||
// PT: use this define to enable detailed analysis of the NP functions.
|
||||
//#define LOCAL_PROFILE_ZONE(x, y) PX_PROFILE_ZONE(x, y)
|
||||
#define LOCAL_PROFILE_ZONE(x, y)
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(PxsCachedTransform)==sizeof(PxTransform32));
|
||||
|
||||
static void startContacts(PxsContactManagerOutput& output, PxcNpThreadContext& context)
|
||||
{
|
||||
context.mContactBuffer.reset();
|
||||
|
||||
output.contactForces = NULL;
|
||||
output.contactPatches = NULL;
|
||||
output.contactPoints = NULL;
|
||||
output.frictionPatches = NULL;
|
||||
output.nbContacts = 0;
|
||||
output.nbPatches = 0;
|
||||
output.statusFlag = 0;
|
||||
}
|
||||
|
||||
static void flipContacts(PxcNpThreadContext& threadContext, PxsMaterialInfo* PX_RESTRICT materialInfo)
|
||||
{
|
||||
PxContactBuffer& buffer = threadContext.mContactBuffer;
|
||||
for(PxU32 i=0; i<buffer.count; ++i)
|
||||
{
|
||||
PxContactPoint& contactPoint = buffer.contacts[i];
|
||||
contactPoint.normal = -contactPoint.normal;
|
||||
PxSwap(materialInfo[i].mMaterialIndex0, materialInfo[i].mMaterialIndex1);
|
||||
}
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void updateDiscreteContactStats(PxcNpThreadContext& context, PxGeometryType::Enum type0, PxGeometryType::Enum type1)
|
||||
{
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
PX_ASSERT(type0<=type1);
|
||||
context.mDiscreteContactPairs[type0][type1]++;
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
PX_UNUSED(context);
|
||||
PX_UNUSED(type0);
|
||||
PX_UNUSED(type1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool copyBuffers(PxsContactManagerOutput& cmOutput, Gu::Cache& cache, PxcNpThreadContext& context, const bool useContactCache, const bool isMeshType)
|
||||
{
|
||||
bool ret = false;
|
||||
//Copy the contact stream from previous buffer to current buffer...
|
||||
PxU32 oldSize = sizeof(PxContact) * cmOutput.nbContacts + sizeof(PxContactPatch)*cmOutput.nbPatches;
|
||||
if(oldSize)
|
||||
{
|
||||
ret = true;
|
||||
PxU8* oldPatches = cmOutput.contactPatches;
|
||||
PxU8* oldContacts = cmOutput.contactPoints;
|
||||
PxReal* oldForces = cmOutput.contactForces;
|
||||
PxU8* oldFriction = cmOutput.frictionPatches;
|
||||
|
||||
PxU32 forceSize = cmOutput.nbContacts * sizeof(PxReal);
|
||||
if(isMeshType)
|
||||
forceSize += cmOutput.nbContacts * sizeof(PxU32);
|
||||
|
||||
PxU32 frictionSize = oldFriction ? sizeof(PxFrictionPatch) * cmOutput.nbPatches : 0;
|
||||
|
||||
PxU8* PX_RESTRICT contactPatches = NULL;
|
||||
PxU8* PX_RESTRICT contactPoints = NULL;
|
||||
|
||||
PxReal* forceBuffer = NULL;
|
||||
|
||||
PxU8* PX_RESTRICT frictionPatches = NULL;
|
||||
|
||||
bool isOverflown = false;
|
||||
|
||||
//ML: if we are using contactStreamPool, which means we are running the GPU codepath
|
||||
if(context.mContactStreamPool)
|
||||
{
|
||||
const PxU32 patchSize = cmOutput.nbPatches * sizeof(PxContactPatch);
|
||||
const PxU32 contactSize = cmOutput.nbContacts * sizeof(PxContact);
|
||||
|
||||
PxU32 index = PxU32(PxAtomicAdd(&context.mContactStreamPool->mSharedDataIndex, PxI32(contactSize)));
|
||||
|
||||
if(context.mContactStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Contact buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
contactPoints = context.mContactStreamPool->mDataStream + context.mContactStreamPool->mDataStreamSize - index;
|
||||
|
||||
const PxU32 patchIndex = PxU32(PxAtomicAdd(&context.mPatchStreamPool->mSharedDataIndex, PxI32(patchSize)));
|
||||
|
||||
if(context.mPatchStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Patch buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
contactPatches = context.mPatchStreamPool->mDataStream + context.mPatchStreamPool->mDataStreamSize - patchIndex;
|
||||
|
||||
if(forceSize)
|
||||
{
|
||||
index = PxU32(PxAtomicAdd(&context.mForceAndIndiceStreamPool->mSharedDataIndex, PxI32(forceSize)));
|
||||
|
||||
if(context.mForceAndIndiceStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Force buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
forceBuffer = reinterpret_cast<PxReal*>(context.mForceAndIndiceStreamPool->mDataStream + context.mForceAndIndiceStreamPool->mDataStreamSize - index);
|
||||
}
|
||||
|
||||
if (frictionSize)
|
||||
{
|
||||
const PxU32 frictionIndex = PxTo32(PxAtomicAdd(&context.mFrictionPatchStreamPool->mSharedDataIndex, PxI32(frictionSize)));
|
||||
|
||||
if (context.mFrictionPatchStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Friction patch buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
frictionPatches = context.mFrictionPatchStreamPool->mDataStream + context.mFrictionPatchStreamPool->mDataStreamSize - frictionIndex;
|
||||
}
|
||||
|
||||
if(isOverflown)
|
||||
{
|
||||
contactPatches = NULL;
|
||||
contactPoints = NULL;
|
||||
frictionPatches = NULL;
|
||||
forceBuffer = NULL;
|
||||
cmOutput.nbContacts = cmOutput.nbPatches = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PxMemCopy(contactPatches, oldPatches, patchSize);
|
||||
PxMemCopy(contactPoints, oldContacts, contactSize);
|
||||
if(isMeshType)
|
||||
PxMemCopy(forceBuffer + cmOutput.nbContacts, oldForces + cmOutput.nbContacts, sizeof(PxU32) * cmOutput.nbContacts);
|
||||
if (frictionSize)
|
||||
PxMemCopy(frictionPatches, oldFriction, frictionSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU32 alignedOldSize = computeAlignedSize(oldSize);
|
||||
|
||||
PxU8* data = context.mContactBlockStream.reserve(alignedOldSize + forceSize + frictionSize);
|
||||
if(forceSize)
|
||||
forceBuffer = reinterpret_cast<PxReal*>(data + alignedOldSize);
|
||||
|
||||
contactPatches = data;
|
||||
contactPoints = data + cmOutput.nbPatches * sizeof(PxContactPatch);
|
||||
|
||||
if (frictionSize)
|
||||
{
|
||||
frictionPatches = data + alignedOldSize + forceSize;
|
||||
PxMemCopy(frictionPatches, oldFriction, frictionSize);
|
||||
}
|
||||
|
||||
PxMemCopy(data, oldPatches, oldSize);
|
||||
|
||||
if(isMeshType)
|
||||
PxMemCopy(forceBuffer + cmOutput.nbContacts, oldForces + cmOutput.nbContacts, sizeof(PxU32) * cmOutput.nbContacts);
|
||||
}
|
||||
|
||||
if(forceSize)
|
||||
PxMemZero(forceBuffer, forceSize);
|
||||
|
||||
cmOutput.contactPatches = contactPatches;
|
||||
cmOutput.contactPoints = contactPoints;
|
||||
cmOutput.frictionPatches = frictionPatches;
|
||||
cmOutput.contactForces = forceBuffer;
|
||||
}
|
||||
|
||||
if(cache.mCachedSize)
|
||||
{
|
||||
if(cache.isMultiManifold())
|
||||
{
|
||||
PX_ASSERT((cache.mCachedSize & 0xF) == 0);
|
||||
|
||||
const PxU8* cachedData = cache.mCachedData;
|
||||
|
||||
PxcNpCacheReserve(context.mNpCacheStreamPair, cache, cache.mCachedSize);
|
||||
if (!cache.mCachedData)
|
||||
return false;
|
||||
|
||||
PX_ASSERT((reinterpret_cast<uintptr_t>(cache.mCachedData)& 0xF) == 0);
|
||||
|
||||
PxMemCopy(cache.mCachedData, cachedData, cache.mCachedSize);
|
||||
cache.setMultiManifold(cache.mCachedData);
|
||||
}
|
||||
else if(useContactCache)
|
||||
{
|
||||
//Copy cache information as well...
|
||||
const PxU8* cachedData = cache.mCachedData;
|
||||
|
||||
PxcNpCacheReserve(context.mNpCacheStreamPair, cache, computeAlignedSize(cache.mCachedSize));
|
||||
if (!cache.mCachedData)
|
||||
return false;
|
||||
|
||||
PxMemCopy(cache.mCachedData, cachedData, cache.mCachedSize);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ML: isMeshType is used in the GPU codepath. If the collision pair is mesh/heightfield vs primitives, we need to allocate enough memory for the mForceAndIndiceStreamPool in the threadContext.
|
||||
static bool finishContacts(const PxcNpWorkUnit& input, PxsContactManagerOutput& npOutput, PxcNpThreadContext& threadContext, PxsMaterialInfo* PX_RESTRICT pMaterials, const bool isMeshType, PxU64 contextID)
|
||||
{
|
||||
PX_UNUSED(contextID);
|
||||
LOCAL_PROFILE_ZONE("finishContacts", contextID);
|
||||
|
||||
PxContactBuffer& buffer = threadContext.mContactBuffer;
|
||||
|
||||
PX_ASSERT((npOutput.statusFlag & PxsContactManagerStatusFlag::eTOUCH_KNOWN) != PxsContactManagerStatusFlag::eTOUCH_KNOWN);
|
||||
PxU8 statusFlags = PxU16(npOutput.statusFlag & (~PxsContactManagerStatusFlag::eTOUCH_KNOWN));
|
||||
if(buffer.count)
|
||||
statusFlags |= PxsContactManagerStatusFlag::eHAS_TOUCH;
|
||||
else
|
||||
statusFlags |= PxsContactManagerStatusFlag::eHAS_NO_TOUCH;
|
||||
|
||||
npOutput.nbContacts = PxTo16(buffer.count);
|
||||
|
||||
if(!buffer.count)
|
||||
{
|
||||
npOutput.statusFlag = statusFlags;
|
||||
npOutput.nbContacts = 0;
|
||||
npOutput.nbPatches = 0;
|
||||
return true;
|
||||
}
|
||||
PX_ASSERT(buffer.count);
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
threadContext.mNbDiscreteContactPairsWithContacts++;
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
|
||||
npOutput.statusFlag = statusFlags;
|
||||
|
||||
PxU32 contactForceByteSize = buffer.count * sizeof(PxReal);
|
||||
|
||||
//Regardless of the flags, we need to now record the compressed contact stream
|
||||
|
||||
PxU16 compressedContactSize;
|
||||
|
||||
const bool createReports =
|
||||
input.mFlags & PxcNpWorkUnitFlag::eOUTPUT_CONTACTS
|
||||
|| (input.mFlags & PxcNpWorkUnitFlag::eFORCE_THRESHOLD);
|
||||
|
||||
if(!isMeshType && !createReports)
|
||||
contactForceByteSize = 0;
|
||||
|
||||
const bool res = writeCompressedContact(buffer.contacts, buffer.count, &threadContext, npOutput.nbContacts, npOutput.contactPatches, npOutput.contactPoints, compressedContactSize,
|
||||
reinterpret_cast<PxReal*&>(npOutput.contactForces), contactForceByteSize,
|
||||
npOutput.frictionPatches, threadContext.mFrictionPatchStreamPool,
|
||||
threadContext.mMaterialManager, ((input.mFlags & PxcNpWorkUnitFlag::eMODIFIABLE_CONTACT) != 0),
|
||||
false, pMaterials, npOutput.nbPatches, 0, NULL, NULL, threadContext.mCreateAveragePoint, threadContext.mContactStreamPool,
|
||||
threadContext.mPatchStreamPool, threadContext.mForceAndIndiceStreamPool, isMeshType) != 0;
|
||||
|
||||
//handle buffer overflow
|
||||
if(!npOutput.nbContacts)
|
||||
{
|
||||
PxU8 thisStatusFlags = PxU16(npOutput.statusFlag & (~PxsContactManagerStatusFlag::eTOUCH_KNOWN));
|
||||
thisStatusFlags |= PxsContactManagerStatusFlag::eHAS_NO_TOUCH;
|
||||
|
||||
npOutput.statusFlag = thisStatusFlags;
|
||||
npOutput.nbContacts = 0;
|
||||
npOutput.nbPatches = 0;
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
threadContext.mNbDiscreteContactPairsWithContacts--;
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<bool useContactCacheT>
|
||||
static PX_FORCE_INLINE bool checkContactsMustBeGenerated(PxcNpThreadContext& context, const PxcNpWorkUnit& input, Gu::Cache& cache, PxsContactManagerOutput& output,
|
||||
const PxsCachedTransform* cachedTransform0, const PxsCachedTransform* cachedTransform1,
|
||||
const bool flip, PxGeometryType::Enum type0, PxGeometryType::Enum type1)
|
||||
{
|
||||
PX_ASSERT(cachedTransform0->transform.isSane() && cachedTransform1->transform.isSane());
|
||||
|
||||
//ML : if user doesn't raise the eDETECT_DISCRETE_CONTACT, we should not generate contacts
|
||||
if(!(input.mFlags & PxcNpWorkUnitFlag::eDETECT_DISCRETE_CONTACT))
|
||||
return false;
|
||||
|
||||
if(!(output.statusFlag & PxcNpWorkUnitStatusFlag::eDIRTY_MANAGER) && !(input.mFlags & PxcNpWorkUnitFlag::eMODIFIABLE_CONTACT))
|
||||
{
|
||||
const PxU32 body0Dynamic = PxU32(input.mFlags & (PxcNpWorkUnitFlag::eDYNAMIC_BODY0 | PxcNpWorkUnitFlag::eARTICULATION_BODY0 | PxcNpWorkUnitFlag::eSOFT_BODY));
|
||||
const PxU32 body1Dynamic = PxU32(input.mFlags & (PxcNpWorkUnitFlag::eDYNAMIC_BODY1 | PxcNpWorkUnitFlag::eARTICULATION_BODY1 | PxcNpWorkUnitFlag::eSOFT_BODY));
|
||||
|
||||
const PxU32 active0 = PxU32(body0Dynamic && !cachedTransform0->isFrozen());
|
||||
const PxU32 active1 = PxU32(body1Dynamic && !cachedTransform1->isFrozen());
|
||||
|
||||
if(!(active0 || active1))
|
||||
{
|
||||
if(flip)
|
||||
PxSwap(type0, type1);
|
||||
|
||||
const bool useContactCache = useContactCacheT ? context.mContactCache && g_CanUseContactCache[type0][type1] : false;
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
if(output.nbContacts)
|
||||
context.mNbDiscreteContactPairsWithContacts++;
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
const bool isMeshType = type1 > PxGeometryType::eCONVEXMESH;
|
||||
copyBuffers(output, cache, context, useContactCache, isMeshType);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
output.statusFlag &= (~PxcNpWorkUnitStatusFlag::eDIRTY_MANAGER);
|
||||
|
||||
const PxReal contactDist0 = context.mContactDistances[input.mTransformCache0];
|
||||
const PxReal contactDist1 = context.mContactDistances[input.mTransformCache1];
|
||||
//context.mNarrowPhaseParams.mContactDistance = shape0->contactOffset + shape1->contactOffset;
|
||||
context.mNarrowPhaseParams.mContactDistance = contactDist0 + contactDist1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool useLegacyCodepath>
|
||||
static PX_FORCE_INLINE void discreteNarrowPhase(PxcNpThreadContext& context, const PxcNpWorkUnit& input, Gu::Cache& cache, PxsContactManagerOutput& output, PxU64 contextID)
|
||||
{
|
||||
PxGeometryType::Enum type0 = input.getGeomType0();
|
||||
PxGeometryType::Enum type1 = input.getGeomType1();
|
||||
|
||||
const bool flip = (type1<type0);
|
||||
|
||||
const PxsCachedTransform* cachedTransform0 = &context.mTransformCache->getTransformCache(input.mTransformCache0);
|
||||
const PxsCachedTransform* cachedTransform1 = &context.mTransformCache->getTransformCache(input.mTransformCache1);
|
||||
|
||||
if(!checkContactsMustBeGenerated<useLegacyCodepath>(context, input, cache, output, cachedTransform0, cachedTransform1, flip, type0, type1))
|
||||
return;
|
||||
|
||||
PxsShapeCore* shape0 = const_cast<PxsShapeCore*>(input.getShapeCore0());
|
||||
PxsShapeCore* shape1 = const_cast<PxsShapeCore*>(input.getShapeCore1());
|
||||
|
||||
if(flip)
|
||||
{
|
||||
PxSwap(type0, type1);
|
||||
PxSwap(shape0, shape1);
|
||||
PxSwap(cachedTransform0, cachedTransform1);
|
||||
}
|
||||
|
||||
PxsMaterialInfo materialInfo[PxContactBuffer::MAX_CONTACTS];
|
||||
|
||||
Gu::MultiplePersistentContactManifold& manifold = context.mTempManifold;
|
||||
bool isMultiManifold = false;
|
||||
|
||||
if(!useLegacyCodepath)
|
||||
{
|
||||
if(cache.isMultiManifold())
|
||||
{
|
||||
//We are using a multi-manifold. This is cached in a reduced npCache...
|
||||
isMultiManifold = true;
|
||||
manifold.fromBuffer(cache.mCachedData);
|
||||
cache.setMultiManifold(&manifold);
|
||||
}
|
||||
else if(cache.isManifold())
|
||||
{
|
||||
void* address = cache.mCachedData;
|
||||
PxPrefetch(address);
|
||||
PxPrefetch(address, 128);
|
||||
PxPrefetch(address, 256);
|
||||
}
|
||||
}
|
||||
|
||||
updateDiscreteContactStats(context, type0, type1);
|
||||
|
||||
startContacts(output, context);
|
||||
|
||||
const PxTransform32* tm0 = reinterpret_cast<const PxTransform32*>(cachedTransform0);
|
||||
const PxTransform32* tm1 = reinterpret_cast<const PxTransform32*>(cachedTransform1);
|
||||
PX_ASSERT(tm0->isSane() && tm1->isSane());
|
||||
|
||||
const PxGeometry& contactShape0 = shape0->mGeometry.getGeometry();
|
||||
const PxGeometry& contactShape1 = shape1->mGeometry.getGeometry();
|
||||
|
||||
if(useLegacyCodepath)
|
||||
{
|
||||
// PT: many cache misses here...
|
||||
|
||||
PxPrefetchLine(shape1, 0); // PT: at least get rid of L2s for shape1
|
||||
|
||||
const PxcContactMethod conMethod = g_ContactMethodTable[type0][type1];
|
||||
PX_ASSERT(conMethod);
|
||||
|
||||
const bool useContactCache = context.mContactCache && g_CanUseContactCache[type0][type1];
|
||||
if(useContactCache)
|
||||
{
|
||||
const bool status = PxcCacheLocalContacts(context, cache, *tm0, *tm1, conMethod, contactShape0, contactShape1);
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
if(status)
|
||||
context.mNbDiscreteContactPairsWithCacheHits++;
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
PX_UNUSED(status);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
LOCAL_PROFILE_ZONE("conMethod", contextID);
|
||||
conMethod(contactShape0, contactShape1, *tm0, *tm1, context.mNarrowPhaseParams, cache, context.mContactBuffer, &context.mRenderOutput);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOCAL_PROFILE_ZONE("conMethod", contextID);
|
||||
const PxcContactMethod conMethod = g_PCMContactMethodTable[type0][type1];
|
||||
PX_ASSERT(conMethod);
|
||||
|
||||
conMethod(contactShape0, contactShape1, *tm0, *tm1, context.mNarrowPhaseParams, cache, context.mContactBuffer, &context.mRenderOutput);
|
||||
}
|
||||
|
||||
if(context.mContactBuffer.count)
|
||||
{
|
||||
const PxcGetMaterialMethod materialMethod = g_GetMaterialMethodTable[type0][type1];
|
||||
if(materialMethod)
|
||||
{
|
||||
LOCAL_PROFILE_ZONE("materialMethod", contextID);
|
||||
materialMethod(shape0, shape1, context.mContactBuffer, materialInfo);
|
||||
}
|
||||
|
||||
if(flip)
|
||||
{
|
||||
LOCAL_PROFILE_ZONE("flipContacts", contextID);
|
||||
flipContacts(context, materialInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if(!useLegacyCodepath)
|
||||
{
|
||||
if(isMultiManifold)
|
||||
{
|
||||
//Store the manifold back...
|
||||
const PxU32 size = (sizeof(MultiPersistentManifoldHeader) +
|
||||
manifold.mNumManifolds * sizeof(SingleManifoldHeader) +
|
||||
manifold.mNumTotalContacts * sizeof(Gu::CachedMeshPersistentContact));
|
||||
|
||||
PxcNpCacheReserve(context.mNpCacheStreamPair, cache, size);
|
||||
|
||||
if (!cache.mCachedData)
|
||||
return;
|
||||
|
||||
PX_ASSERT((reinterpret_cast<uintptr_t>(cache.mCachedData)& 0xf) == 0);
|
||||
manifold.toBuffer(cache.mCachedData);
|
||||
cache.setMultiManifold(cache.mCachedData);
|
||||
cache.mCachedSize = PxTo16(size);
|
||||
}
|
||||
}
|
||||
|
||||
const bool isMeshType = type1 > PxGeometryType::eCONVEXMESH;
|
||||
finishContacts(input, output, context, materialInfo, isMeshType, contextID);
|
||||
}
|
||||
|
||||
void physx::PxcDiscreteNarrowPhase(PxcNpThreadContext& context, const PxcNpWorkUnit& input, Gu::Cache& cache, PxsContactManagerOutput& output, PxU64 contextID)
|
||||
{
|
||||
LOCAL_PROFILE_ZONE("PxcDiscreteNarrowPhase", contextID);
|
||||
discreteNarrowPhase<true>(context, input, cache, output, contextID);
|
||||
}
|
||||
|
||||
void physx::PxcDiscreteNarrowPhasePCM(PxcNpThreadContext& context, const PxcNpWorkUnit& input, Gu::Cache& cache, PxsContactManagerOutput& output, PxU64 contextID)
|
||||
{
|
||||
LOCAL_PROFILE_ZONE("PxcDiscreteNarrowPhasePCM", contextID);
|
||||
discreteNarrowPhase<false>(context, input, cache, output, contextID);
|
||||
}
|
||||
72
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcNpCacheStreamPair.cpp
vendored
Normal file
72
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcNpCacheStreamPair.cpp
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
// 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 "PxcNpCacheStreamPair.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "PxcNpMemBlockPool.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
PxcNpCacheStreamPair::PxcNpCacheStreamPair(PxcNpMemBlockPool& blockPool) :
|
||||
mBlockPool (blockPool),
|
||||
mBlock (NULL),
|
||||
mUsed (0)
|
||||
{
|
||||
}
|
||||
|
||||
// reserve can fail and return null. Read should never fail
|
||||
PxU8* PxcNpCacheStreamPair::reserve(PxU32 size, bool& sizeTooLarge)
|
||||
{
|
||||
size = (size+15)&~15;
|
||||
|
||||
if(size>PxcNpMemBlock::SIZE)
|
||||
{
|
||||
sizeTooLarge = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sizeTooLarge = false;
|
||||
|
||||
if(mBlock == NULL || mUsed + size > PxcNpMemBlock::SIZE)
|
||||
{
|
||||
mBlock = mBlockPool.acquireNpCacheBlock();
|
||||
mUsed = 0;
|
||||
}
|
||||
|
||||
PxU8* ptr;
|
||||
if(mBlock == NULL)
|
||||
ptr = NULL;
|
||||
else
|
||||
{
|
||||
ptr = mBlock->data + mUsed;
|
||||
mUsed += size;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
552
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcNpContactPrepShared.cpp
vendored
Normal file
552
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcNpContactPrepShared.cpp
vendored
Normal file
@@ -0,0 +1,552 @@
|
||||
// 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 "foundation/PxAlloca.h"
|
||||
#include "foundation/PxAtomic.h"
|
||||
#include "foundation/PxErrors.h"
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#include "foundation/PxVecMath.h"
|
||||
#include "geomutils/PxContactPoint.h"
|
||||
|
||||
#include "PxcNpContactPrepShared.h"
|
||||
#include "PxcNpThreadContext.h"
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "PxsMaterialCombiner.h"
|
||||
|
||||
#include "PxcNpContactPrepShared.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
using namespace aos;
|
||||
|
||||
static PX_FORCE_INLINE void copyContactPoint(PxContact* PX_RESTRICT point, const PxContactPoint* PX_RESTRICT cp)
|
||||
{
|
||||
// PT: TODO: consider moving "separation" right after "point" in both structures, to copy both at the same time.
|
||||
// point->contact = cp->point;
|
||||
const Vec4V contactV = V4LoadA(&cp->point.x); // PT: V4LoadA safe because 'point' is aligned.
|
||||
V4StoreU(contactV, &point->contact.x);
|
||||
|
||||
point->separation = cp->separation;
|
||||
}
|
||||
|
||||
void combineMaterials(const PxsMaterialManager* materialManager, PxU16 origMatIndex0, PxU16 origMatIndex1, PxReal& staticFriction, PxReal& dynamicFriction, PxReal& combinedRestitution, PxU32& materialFlags, PxReal& combinedDamping)
|
||||
{
|
||||
const PxsMaterialData& data0 = *materialManager->getMaterial(origMatIndex0);
|
||||
const PxsMaterialData& data1 = *materialManager->getMaterial(origMatIndex1);
|
||||
|
||||
PxsCombineMaterials(data0, data1, staticFriction, dynamicFriction, combinedRestitution, materialFlags, combinedDamping);
|
||||
}
|
||||
|
||||
struct StridePatch
|
||||
{
|
||||
PxU8 startIndex;
|
||||
PxU8 endIndex;
|
||||
PxU8 nextIndex;
|
||||
PxU8 totalCount;
|
||||
bool isRoot;
|
||||
};
|
||||
|
||||
PxU32 physx::writeCompressedContact(const PxContactPoint* const PX_RESTRICT contactPoints, const PxU32 numContactPoints, PxcNpThreadContext* threadContext,
|
||||
PxU16& writtenContactCount, PxU8*& outContactPatches, PxU8*& outContactPoints, PxU16& compressedContactSize, PxReal*& outContactForces, PxU32 contactForceByteSize,
|
||||
PxU8*& outFrictionPatches, PxcDataStreamPool* frictionPatchesStreamPool,
|
||||
const PxsMaterialManager* materialManager, bool hasModifiableContacts, bool forceNoResponse, const PxsMaterialInfo* PX_RESTRICT pMaterial, PxU8& numPatches,
|
||||
PxU32 additionalHeaderSize, PxsConstraintBlockManager* manager, PxcConstraintBlockStream* blockStream, bool insertAveragePoint,
|
||||
PxcDataStreamPool* contactStreamPool, PxcDataStreamPool* patchStreamPool, PxcDataStreamPool* forceStreamPool, const bool isMeshType)
|
||||
{
|
||||
if(numContactPoints == 0)
|
||||
{
|
||||
writtenContactCount = 0;
|
||||
outContactPatches = NULL;
|
||||
outContactPoints = NULL;
|
||||
outContactForces = NULL;
|
||||
compressedContactSize = 0;
|
||||
numPatches = 0;
|
||||
outFrictionPatches = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Calculate the size of the contact buffer...
|
||||
PX_ALLOCA(strPatches, StridePatch, numContactPoints);
|
||||
|
||||
StridePatch* stridePatches = &strPatches[0];
|
||||
|
||||
PxU32 numStrideHeaders = 1;
|
||||
PxU32 totalUniquePatches = 1;
|
||||
PxU32 totalContactPoints = numContactPoints;
|
||||
|
||||
PxU32 strideStart = 0;
|
||||
bool root = true;
|
||||
StridePatch* parentRootPatch = NULL;
|
||||
{
|
||||
const PxReal closeNormalThresh = PXC_SAME_NORMAL;
|
||||
//Go through and tag how many patches we have...
|
||||
PxVec3 normal = contactPoints[0].normal;
|
||||
PxU16 mat0 = pMaterial[0].mMaterialIndex0;
|
||||
PxU16 mat1 = pMaterial[0].mMaterialIndex1;
|
||||
|
||||
for(PxU32 a = 1; a < numContactPoints; ++a)
|
||||
{
|
||||
if(normal.dot(contactPoints[a].normal) < closeNormalThresh ||
|
||||
pMaterial[a].mMaterialIndex0 != mat0 || pMaterial[a].mMaterialIndex1 != mat1)
|
||||
{
|
||||
StridePatch& patch = stridePatches[numStrideHeaders-1];
|
||||
|
||||
patch.startIndex = PxU8(strideStart);
|
||||
patch.endIndex = PxU8(a);
|
||||
patch.nextIndex = 0xFF;
|
||||
patch.totalCount = PxU8(a - strideStart);
|
||||
patch.isRoot = root;
|
||||
if(parentRootPatch)
|
||||
parentRootPatch->totalCount += PxU8(a - strideStart);
|
||||
|
||||
root = true;
|
||||
parentRootPatch = NULL;
|
||||
for(PxU32 b = 1; b < numStrideHeaders; ++b)
|
||||
{
|
||||
StridePatch& thisPatch = stridePatches[b-1];
|
||||
if(thisPatch.isRoot)
|
||||
{
|
||||
PxU32 ind = thisPatch.startIndex;
|
||||
PxReal dp2 = contactPoints[a].normal.dot(contactPoints[ind].normal);
|
||||
if(dp2 >= closeNormalThresh && pMaterial[a].mMaterialIndex0 == pMaterial[ind].mMaterialIndex0 &&
|
||||
pMaterial[a].mMaterialIndex1 == pMaterial[ind].mMaterialIndex1)
|
||||
{
|
||||
PxU32 nextInd = b-1;
|
||||
while(stridePatches[nextInd].nextIndex != 0xFF)
|
||||
nextInd = stridePatches[nextInd].nextIndex;
|
||||
stridePatches[nextInd].nextIndex = PxU8(numStrideHeaders);
|
||||
root = false;
|
||||
parentRootPatch = &stridePatches[b-1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
normal = contactPoints[a].normal;
|
||||
|
||||
mat0 = pMaterial[a].mMaterialIndex0;
|
||||
mat1 = pMaterial[a].mMaterialIndex1;
|
||||
totalContactPoints = insertAveragePoint && (a - strideStart) > 1 ? totalContactPoints + 1 : totalContactPoints;
|
||||
strideStart = a;
|
||||
numStrideHeaders++;
|
||||
if(root)
|
||||
totalUniquePatches++;
|
||||
}
|
||||
}
|
||||
totalContactPoints = insertAveragePoint &&(numContactPoints - strideStart) > 1 ? totalContactPoints + 1 : totalContactPoints;
|
||||
contactForceByteSize = insertAveragePoint && contactForceByteSize != 0 ? contactForceByteSize + sizeof(PxF32) * (totalContactPoints - numContactPoints) : contactForceByteSize;
|
||||
}
|
||||
{
|
||||
StridePatch& patch = stridePatches[numStrideHeaders-1];
|
||||
patch.startIndex = PxU8(strideStart);
|
||||
patch.endIndex = PxU8(numContactPoints);
|
||||
patch.nextIndex = 0xFF;
|
||||
patch.totalCount = PxU8(numContactPoints - strideStart);
|
||||
patch.isRoot = root;
|
||||
if(parentRootPatch)
|
||||
parentRootPatch->totalCount += PxU8(numContactPoints - strideStart);
|
||||
}
|
||||
|
||||
numPatches = PxU8(totalUniquePatches);
|
||||
|
||||
//Calculate the number of patches/points required
|
||||
|
||||
const bool isModifiable = !forceNoResponse && hasModifiableContacts;
|
||||
const PxU32 patchHeaderSize = sizeof(PxContactPatch) * (isModifiable ? totalContactPoints : totalUniquePatches) + additionalHeaderSize;
|
||||
const PxU32 pointSize = totalContactPoints * (isModifiable ? sizeof(PxModifiableContact) : sizeof(PxContact));
|
||||
|
||||
const PxU32 requiredContactSize = pointSize;
|
||||
const PxU32 requiredPatchSize = patchHeaderSize;
|
||||
PxU32 totalRequiredSize;
|
||||
|
||||
PxU8* PX_RESTRICT contactData = NULL;
|
||||
PxU8* PX_RESTRICT patchData = NULL;
|
||||
PxReal* PX_RESTRICT forceData = NULL;
|
||||
PxU32* PX_RESTRICT triangleIndice = NULL;
|
||||
|
||||
// Calculate friction data size
|
||||
|
||||
const PxU32 frictionPatchesSize = numPatches * sizeof(PxFrictionPatch);
|
||||
|
||||
PxU8* PX_RESTRICT frictionPatchesData = NULL;
|
||||
|
||||
if(contactStreamPool && !isModifiable && additionalHeaderSize == 0) //If the contacts are modifiable, we **DON'T** allocate them in GPU pinned memory. This will be handled later when they're modified
|
||||
{
|
||||
bool isOverflown = false;
|
||||
|
||||
PxU32 contactIndex = PxU32(PxAtomicAdd(&contactStreamPool->mSharedDataIndex, PxI32(requiredContactSize)));
|
||||
|
||||
if (contactStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Contact buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
|
||||
contactData = contactStreamPool->mDataStream + contactStreamPool->mDataStreamSize - contactIndex;
|
||||
|
||||
const PxU32 patchIndex = PxU32(PxAtomicAdd(&patchStreamPool->mSharedDataIndex, PxI32(requiredPatchSize)));
|
||||
|
||||
if (patchStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Patch buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
|
||||
patchData = patchStreamPool->mDataStream + patchStreamPool->mDataStreamSize - patchIndex;
|
||||
|
||||
PxU32 frictionPatchesIndex = PxTo32(PxAtomicAdd(&frictionPatchesStreamPool->mSharedDataIndex, PxI32(frictionPatchesSize)));
|
||||
|
||||
if (frictionPatchesStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Friction patch buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
|
||||
frictionPatchesData = frictionPatchesStreamPool->mDataStream + frictionPatchesStreamPool->mDataStreamSize - frictionPatchesIndex;
|
||||
|
||||
if(contactForceByteSize)
|
||||
{
|
||||
contactForceByteSize = isMeshType ? contactForceByteSize * 2 : contactForceByteSize;
|
||||
contactIndex = PxU32(PxAtomicAdd(&forceStreamPool->mSharedDataIndex, PxI32(contactForceByteSize)));
|
||||
|
||||
if (forceStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Force buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
forceData = reinterpret_cast<PxReal*>(forceStreamPool->mDataStream + forceStreamPool->mDataStreamSize - contactIndex);
|
||||
if (isMeshType)
|
||||
triangleIndice = reinterpret_cast<PxU32*>(forceData + numContactPoints);
|
||||
}
|
||||
|
||||
totalRequiredSize = requiredContactSize + requiredPatchSize;
|
||||
|
||||
if (isOverflown)
|
||||
{
|
||||
patchData = NULL;
|
||||
contactData = NULL;
|
||||
forceData = NULL;
|
||||
triangleIndice = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU32 alignedRequiredSize = computeAlignedSize(requiredContactSize + requiredPatchSize);
|
||||
contactForceByteSize = (isMeshType ? contactForceByteSize * 2 : contactForceByteSize);
|
||||
const PxU32 totalSize = alignedRequiredSize + contactForceByteSize + frictionPatchesSize;
|
||||
PxU8* data = manager ? blockStream->reserve(totalSize, *manager) : threadContext->mContactBlockStream.reserve(totalSize);
|
||||
|
||||
if(data)
|
||||
{
|
||||
patchData = data;
|
||||
contactData = data + requiredPatchSize;
|
||||
|
||||
if(contactForceByteSize)
|
||||
{
|
||||
forceData = reinterpret_cast<PxReal*>((data + alignedRequiredSize));
|
||||
|
||||
if (isMeshType)
|
||||
triangleIndice = reinterpret_cast<PxU32*>(forceData + numContactPoints);
|
||||
|
||||
PxMemZero(forceData, contactForceByteSize);
|
||||
|
||||
if (frictionPatchesSize)
|
||||
{
|
||||
frictionPatchesData = data + alignedRequiredSize + contactForceByteSize;
|
||||
PxMemZero(frictionPatchesData, frictionPatchesSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
totalRequiredSize = alignedRequiredSize;
|
||||
}
|
||||
|
||||
if(patchData == NULL)
|
||||
{
|
||||
writtenContactCount = 0;
|
||||
outContactPatches = NULL;
|
||||
outContactPoints = NULL;
|
||||
outContactForces = NULL;
|
||||
compressedContactSize = 0;
|
||||
numPatches = 0;
|
||||
outFrictionPatches = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PxPrefetchLine(patchData);
|
||||
PxPrefetchLine(contactData);
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
if(threadContext)
|
||||
threadContext->mCompressedCacheSize += totalRequiredSize;
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
compressedContactSize = PxTo16(totalRequiredSize);
|
||||
|
||||
//PxU32 startIndex = 0;
|
||||
|
||||
//Extract first material
|
||||
PxU16 origMatIndex0 = pMaterial[0].mMaterialIndex0;
|
||||
PxU16 origMatIndex1 = pMaterial[0].mMaterialIndex1;
|
||||
|
||||
PxReal staticFriction, dynamicFriction, combinedRestitution, combinedDamping;
|
||||
PxU32 materialFlags;
|
||||
combineMaterials(materialManager, origMatIndex0, origMatIndex1, staticFriction, dynamicFriction, combinedRestitution, materialFlags, combinedDamping);
|
||||
|
||||
PxU8* PX_RESTRICT dataPlusOffset = patchData + additionalHeaderSize;
|
||||
PxContactPatch* PX_RESTRICT patches = reinterpret_cast<PxContactPatch*>(dataPlusOffset);
|
||||
PxU32* PX_RESTRICT faceIndice = triangleIndice;
|
||||
|
||||
outContactPatches = patchData;
|
||||
outContactPoints = contactData;
|
||||
outContactForces = forceData;
|
||||
|
||||
outFrictionPatches = frictionPatchesData;
|
||||
|
||||
struct Local
|
||||
{
|
||||
static PX_FORCE_INLINE void fillPatch(PxContactPatch* PX_RESTRICT patch, const StridePatch& rootPatch, const PxVec3& normal,
|
||||
PxU32 currentIndex, PxReal staticFriction_, PxReal dynamicFriction_, PxReal combinedRestitution_, PxReal combinedDamping_,
|
||||
PxU32 materialFlags_, PxU32 flags, PxU16 matIndex0, PxU16 matIndex1
|
||||
)
|
||||
{
|
||||
patch->mMassModification.linear0 = 1.0f;
|
||||
patch->mMassModification.linear1 = 1.0f;
|
||||
patch->mMassModification.angular0 = 1.0f;
|
||||
patch->mMassModification.angular1 = 1.0f;
|
||||
PX_ASSERT(PxAbs(normal.magnitude() - 1) < 1e-3f);
|
||||
patch->normal = normal;
|
||||
patch->restitution = combinedRestitution_;
|
||||
patch->dynamicFriction = dynamicFriction_;
|
||||
patch->staticFriction = staticFriction_;
|
||||
patch->damping = combinedDamping_;
|
||||
patch->startContactIndex = PxTo16(currentIndex);
|
||||
//KS - we could probably compress this further into the header but the complexity might not be worth it
|
||||
patch->nbContacts = rootPatch.totalCount;
|
||||
patch->materialFlags = PxU8(materialFlags_);
|
||||
patch->internalFlags = PxU8(flags);
|
||||
patch->materialIndex0 = matIndex0;
|
||||
patch->materialIndex1 = matIndex1;
|
||||
}
|
||||
};
|
||||
|
||||
if(isModifiable)
|
||||
{
|
||||
PxU32 flags = PxU32(isModifiable ? PxContactPatch::eMODIFIABLE : 0) |
|
||||
(forceNoResponse ? PxContactPatch::eFORCE_NO_RESPONSE : 0) |
|
||||
(isMeshType ? PxContactPatch::eHAS_FACE_INDICES : 0);
|
||||
|
||||
PxU32 currentIndex = 0;
|
||||
|
||||
PxModifiableContact* PX_RESTRICT point = reinterpret_cast<PxModifiableContact*>(contactData);
|
||||
|
||||
for(PxU32 a = 0; a < numStrideHeaders; ++a)
|
||||
{
|
||||
StridePatch& rootPatch = stridePatches[a];
|
||||
if(rootPatch.isRoot)
|
||||
{
|
||||
const PxU32 startIndex = rootPatch.startIndex;
|
||||
|
||||
const PxU16 matIndex0 = pMaterial[startIndex].mMaterialIndex0;
|
||||
const PxU16 matIndex1 = pMaterial[startIndex].mMaterialIndex1;
|
||||
if(matIndex0 != origMatIndex0 || matIndex1 != origMatIndex1)
|
||||
{
|
||||
combineMaterials(materialManager, matIndex0, matIndex1, staticFriction, dynamicFriction, combinedRestitution, materialFlags, combinedDamping);
|
||||
|
||||
origMatIndex0 = matIndex0;
|
||||
origMatIndex1 = matIndex1;
|
||||
}
|
||||
|
||||
PxContactPatch* PX_RESTRICT patch = patches++;
|
||||
Local::fillPatch(patch, rootPatch, contactPoints[startIndex].normal, currentIndex, staticFriction, dynamicFriction, combinedRestitution, combinedDamping, materialFlags, flags, matIndex0, matIndex1);
|
||||
|
||||
//const PxU32 endIndex = strideHeader[a];
|
||||
const PxU32 totalCountThisPatch = rootPatch.totalCount;
|
||||
if(insertAveragePoint && totalCountThisPatch > 1)
|
||||
{
|
||||
PxVec3 avgPt(0.0f);
|
||||
PxF32 avgPen(0.0f);
|
||||
PxF32 recipCount = 1.0f/(PxF32(rootPatch.totalCount));
|
||||
|
||||
PxU32 index = a;
|
||||
while(index != 0xFF)
|
||||
{
|
||||
StridePatch& p = stridePatches[index];
|
||||
for(PxU32 b = p.startIndex; b < p.endIndex; ++b)
|
||||
{
|
||||
avgPt += contactPoints[b].point;
|
||||
avgPen += contactPoints[b].separation;
|
||||
}
|
||||
index = p.nextIndex;
|
||||
}
|
||||
|
||||
if (faceIndice)
|
||||
{
|
||||
StridePatch& p = stridePatches[index];
|
||||
*faceIndice = contactPoints[p.startIndex].internalFaceIndex1;
|
||||
faceIndice++;
|
||||
}
|
||||
|
||||
patch->nbContacts++;
|
||||
point->contact = avgPt * recipCount;
|
||||
point->separation = avgPen * recipCount;
|
||||
point->normal = contactPoints[startIndex].normal;
|
||||
point->maxImpulse = PX_MAX_REAL;
|
||||
point->targetVelocity = PxVec3(0.0f);
|
||||
point->staticFriction = staticFriction;
|
||||
point->dynamicFriction = dynamicFriction;
|
||||
point->restitution = combinedRestitution;
|
||||
point->materialFlags = materialFlags;
|
||||
point->materialIndex0 = matIndex0;
|
||||
point->materialIndex1 = matIndex1;
|
||||
point++;
|
||||
currentIndex++;
|
||||
PxPrefetchLine(point, 128);
|
||||
}
|
||||
|
||||
PxU32 index = a;
|
||||
while(index != 0xFF)
|
||||
{
|
||||
StridePatch& p = stridePatches[index];
|
||||
|
||||
for(PxU32 b = p.startIndex; b < p.endIndex; ++b)
|
||||
{
|
||||
copyContactPoint(point, &contactPoints[b]);
|
||||
point->normal = contactPoints[b].normal;
|
||||
point->maxImpulse = PX_MAX_REAL;
|
||||
point->targetVelocity = PxVec3(0.0f);
|
||||
point->staticFriction = staticFriction;
|
||||
point->dynamicFriction = dynamicFriction;
|
||||
point->restitution = combinedRestitution;
|
||||
point->materialFlags = materialFlags;
|
||||
point->materialIndex0 = matIndex0;
|
||||
point->materialIndex1 = matIndex1;
|
||||
if (faceIndice)
|
||||
{
|
||||
*faceIndice = contactPoints[b].internalFaceIndex1;
|
||||
faceIndice++;
|
||||
}
|
||||
point++;
|
||||
currentIndex++;
|
||||
PxPrefetchLine(point, 128);
|
||||
}
|
||||
index = p.nextIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PxU32 flags = PxU32(isMeshType ? PxContactPatch::eHAS_FACE_INDICES : 0);
|
||||
|
||||
PxContact* PX_RESTRICT point = reinterpret_cast<PxContact*>(contactData);
|
||||
|
||||
PxU32 currentIndex = 0;
|
||||
{
|
||||
for(PxU32 a = 0; a < numStrideHeaders; ++a)
|
||||
{
|
||||
StridePatch& rootPatch = stridePatches[a];
|
||||
|
||||
if(rootPatch.isRoot)
|
||||
{
|
||||
const PxU32 startIndex = rootPatch.startIndex;
|
||||
|
||||
const PxU16 matIndex0 = pMaterial[startIndex].mMaterialIndex0;
|
||||
const PxU16 matIndex1 = pMaterial[startIndex].mMaterialIndex1;
|
||||
if(matIndex0 != origMatIndex0 || matIndex1 != origMatIndex1)
|
||||
{
|
||||
combineMaterials(materialManager, matIndex0, matIndex1, staticFriction, dynamicFriction, combinedRestitution, materialFlags, combinedDamping);
|
||||
|
||||
origMatIndex0 = matIndex0;
|
||||
origMatIndex1 = matIndex1;
|
||||
}
|
||||
|
||||
PxContactPatch* PX_RESTRICT patch = patches++;
|
||||
Local::fillPatch(patch, rootPatch, contactPoints[startIndex].normal, currentIndex, staticFriction, dynamicFriction, combinedRestitution, combinedDamping, materialFlags, flags, matIndex0, matIndex1);
|
||||
|
||||
if(insertAveragePoint && (rootPatch.totalCount) > 1)
|
||||
{
|
||||
patch->nbContacts++;
|
||||
PxVec3 avgPt(0.0f);
|
||||
PxF32 avgPen(0.0f);
|
||||
PxF32 recipCount = 1.0f/(PxF32(rootPatch.totalCount));
|
||||
PxU32 index = a;
|
||||
|
||||
while(index != 0xFF)
|
||||
{
|
||||
StridePatch& p = stridePatches[index];
|
||||
for(PxU32 b = p.startIndex; b < p.endIndex; ++b)
|
||||
{
|
||||
avgPt += contactPoints[b].point;
|
||||
avgPen += contactPoints[b].separation;
|
||||
}
|
||||
index = stridePatches[index].nextIndex;
|
||||
}
|
||||
|
||||
if (faceIndice)
|
||||
{
|
||||
StridePatch& p = stridePatches[index];
|
||||
*faceIndice = contactPoints[p.startIndex].internalFaceIndex1;
|
||||
faceIndice++;
|
||||
}
|
||||
point->contact = avgPt * recipCount;
|
||||
point->separation = avgPen * recipCount;
|
||||
|
||||
point++;
|
||||
currentIndex++;
|
||||
PxPrefetchLine(point, 128);
|
||||
}
|
||||
|
||||
PxU32 index = a;
|
||||
while(index != 0xFF)
|
||||
{
|
||||
StridePatch& p = stridePatches[index];
|
||||
for(PxU32 b = p.startIndex; b < p.endIndex; ++b)
|
||||
{
|
||||
copyContactPoint(point, &contactPoints[b]);
|
||||
if (faceIndice)
|
||||
{
|
||||
*faceIndice = contactPoints[b].internalFaceIndex1;
|
||||
faceIndice++;
|
||||
}
|
||||
point++;
|
||||
currentIndex++;
|
||||
PxPrefetchLine(point, 128);
|
||||
}
|
||||
index = stridePatches[index].nextIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writtenContactCount = PxTo16(totalContactPoints);
|
||||
|
||||
return totalRequiredSize;
|
||||
}
|
||||
346
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcNpMemBlockPool.cpp
vendored
Normal file
346
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcNpMemBlockPool.cpp
vendored
Normal file
@@ -0,0 +1,346 @@
|
||||
// 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 "foundation/PxPreprocessor.h"
|
||||
#include "foundation/PxMath.h"
|
||||
#include "PxcNpMemBlockPool.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "foundation/PxInlineArray.h"
|
||||
#include "PxcScratchAllocator.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
PxcNpMemBlockPool::PxcNpMemBlockPool(PxcScratchAllocator& allocator) :
|
||||
mConstraints("PxcNpMemBlockPool::mConstraints"),
|
||||
mExceptionalConstraints("PxcNpMemBlockPool::mExceptionalConstraints"),
|
||||
mNpCacheActiveStream(0),
|
||||
mFrictionActiveStream(0),
|
||||
mCCDCacheActiveStream(0),
|
||||
mContactIndex(0),
|
||||
mAllocatedBlocks(0),
|
||||
mMaxBlocks(0),
|
||||
mUsedBlocks(0),
|
||||
mMaxUsedBlocks(0),
|
||||
mScratchBlockAddr(0),
|
||||
mNbScratchBlocks(0),
|
||||
mScratchAllocator(allocator),
|
||||
mPeakConstraintAllocations(0),
|
||||
mConstraintAllocations(0)
|
||||
{
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::init(PxU32 initialBlockCount, PxU32 maxBlocks)
|
||||
{
|
||||
mMaxBlocks = maxBlocks;
|
||||
mInitialBlocks = initialBlockCount;
|
||||
|
||||
PxU32 reserve = PxMax<PxU32>(initialBlockCount, 64);
|
||||
|
||||
mConstraints.reserve(reserve);
|
||||
mExceptionalConstraints.reserve(16);
|
||||
|
||||
mFriction[0].reserve(reserve);
|
||||
mFriction[1].reserve(reserve);
|
||||
mNpCache[0].reserve(reserve);
|
||||
mNpCache[1].reserve(reserve);
|
||||
mUnused.reserve(reserve);
|
||||
|
||||
setBlockCount(initialBlockCount);
|
||||
}
|
||||
|
||||
PxU32 PxcNpMemBlockPool::getUsedBlockCount() const
|
||||
{
|
||||
return mUsedBlocks;
|
||||
}
|
||||
|
||||
PxU32 PxcNpMemBlockPool::getMaxUsedBlockCount() const
|
||||
{
|
||||
return mMaxUsedBlocks;
|
||||
}
|
||||
|
||||
PxU32 PxcNpMemBlockPool::getPeakConstraintBlockCount() const
|
||||
{
|
||||
return mPeakConstraintAllocations;
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::setBlockCount(PxU32 blockCount)
|
||||
{
|
||||
PxMutex::ScopedLock lock(mLock);
|
||||
PxU32 current = getUsedBlockCount();
|
||||
for(PxU32 i=current;i<blockCount;i++)
|
||||
{
|
||||
mUnused.pushBack(reinterpret_cast<PxcNpMemBlock *>(PX_ALLOC(PxcNpMemBlock::SIZE, "PxcNpMemBlock")));
|
||||
mAllocatedBlocks++;
|
||||
}
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::releaseUnusedBlocks()
|
||||
{
|
||||
PxMutex::ScopedLock lock(mLock);
|
||||
while(mUnused.size())
|
||||
{
|
||||
PxcNpMemBlock* ptr = mUnused.popBack();
|
||||
PX_FREE(ptr);
|
||||
mAllocatedBlocks--;
|
||||
}
|
||||
}
|
||||
|
||||
PxcNpMemBlockPool::~PxcNpMemBlockPool()
|
||||
{
|
||||
// swapping twice guarantees all blocks are released from the stream pairs
|
||||
swapFrictionStreams();
|
||||
swapFrictionStreams();
|
||||
|
||||
swapNpCacheStreams();
|
||||
swapNpCacheStreams();
|
||||
|
||||
releaseConstraintMemory();
|
||||
releaseContacts();
|
||||
releaseContacts();
|
||||
|
||||
PX_ASSERT(mUsedBlocks == 0);
|
||||
|
||||
flushUnused();
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::acquireConstraintMemory()
|
||||
{
|
||||
PxU32 size;
|
||||
void* addr = mScratchAllocator.allocAll(size);
|
||||
size = size&~(PxcNpMemBlock::SIZE-1);
|
||||
|
||||
PX_ASSERT(mScratchBlocks.size()==0);
|
||||
mScratchBlockAddr = reinterpret_cast<PxcNpMemBlock*>(addr);
|
||||
mNbScratchBlocks = size/PxcNpMemBlock::SIZE;
|
||||
|
||||
mScratchBlocks.resize(mNbScratchBlocks);
|
||||
for(PxU32 i=0;i<mNbScratchBlocks;i++)
|
||||
mScratchBlocks[i] = mScratchBlockAddr+i;
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::releaseConstraintMemory()
|
||||
{
|
||||
PxMutex::ScopedLock lock(mLock);
|
||||
|
||||
mPeakConstraintAllocations = mConstraintAllocations = 0;
|
||||
|
||||
while(mConstraints.size())
|
||||
{
|
||||
PxcNpMemBlock* block = mConstraints.popBack();
|
||||
if(mScratchAllocator.isScratchAddr(block))
|
||||
mScratchBlocks.pushBack(block);
|
||||
else
|
||||
{
|
||||
mUnused.pushBack(block);
|
||||
PX_ASSERT(mUsedBlocks>0);
|
||||
mUsedBlocks--;
|
||||
}
|
||||
}
|
||||
|
||||
for(PxU32 i=0;i<mExceptionalConstraints.size();i++)
|
||||
PX_FREE(mExceptionalConstraints[i]);
|
||||
mExceptionalConstraints.clear();
|
||||
|
||||
PX_ASSERT(mScratchBlocks.size()==mNbScratchBlocks); // check we released them all
|
||||
mScratchBlocks.clear();
|
||||
|
||||
if(mScratchBlockAddr)
|
||||
{
|
||||
mScratchAllocator.free(mScratchBlockAddr);
|
||||
mScratchBlockAddr = 0;
|
||||
mNbScratchBlocks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PxcNpMemBlock* PxcNpMemBlockPool::acquire(PxcNpMemBlockArray& trackingArray, PxU32* allocationCount, PxU32* peakAllocationCount, bool isScratchAllocation)
|
||||
{
|
||||
PxMutex::ScopedLock lock(mLock);
|
||||
if(allocationCount && peakAllocationCount)
|
||||
{
|
||||
*peakAllocationCount = PxMax(*allocationCount + 1, *peakAllocationCount);
|
||||
(*allocationCount)++;
|
||||
}
|
||||
|
||||
// this is a bit of hack - the logic would be better placed in acquireConstraintBlock, but then we'd have to grab the mutex
|
||||
// once there to check the scratch block array and once here if we fail - or, we'd need a larger refactor to separate out
|
||||
// locking and acquisition.
|
||||
|
||||
if(isScratchAllocation && mScratchBlocks.size()>0)
|
||||
{
|
||||
PxcNpMemBlock* block = mScratchBlocks.popBack();
|
||||
trackingArray.pushBack(block);
|
||||
return block;
|
||||
}
|
||||
|
||||
if(mUnused.size())
|
||||
{
|
||||
PxcNpMemBlock* block = mUnused.popBack();
|
||||
trackingArray.pushBack(block);
|
||||
mMaxUsedBlocks = PxMax<PxU32>(mUsedBlocks+1, mMaxUsedBlocks);
|
||||
mUsedBlocks++;
|
||||
return block;
|
||||
}
|
||||
|
||||
if(mAllocatedBlocks == mMaxBlocks)
|
||||
{
|
||||
#if PX_CHECKED
|
||||
PxGetFoundation().error(PxErrorCode::eDEBUG_WARNING, PX_FL,
|
||||
"Reached maximum number of allocated blocks so 16k block allocation will fail!");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if PX_CHECKED
|
||||
if(mInitialBlocks)
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eDEBUG_WARNING, PX_FL,
|
||||
"Number of required 16k memory blocks has exceeded the initial number of blocks. Allocator is being called. Consider increasing the number of pre-allocated 16k blocks.");
|
||||
}
|
||||
#endif
|
||||
|
||||
// increment here so that if we hit the limit in separate threads we won't overallocated
|
||||
mAllocatedBlocks++;
|
||||
|
||||
PxcNpMemBlock* block = reinterpret_cast<PxcNpMemBlock*>(PX_ALLOC(sizeof(PxcNpMemBlock), "PxcNpMemBlock"));
|
||||
|
||||
if(block)
|
||||
{
|
||||
trackingArray.pushBack(block);
|
||||
mMaxUsedBlocks = PxMax<PxU32>(mUsedBlocks+1, mMaxUsedBlocks);
|
||||
mUsedBlocks++;
|
||||
}
|
||||
else
|
||||
mAllocatedBlocks--;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
PxU8* PxcNpMemBlockPool::acquireExceptionalConstraintMemory(PxU32 size)
|
||||
{
|
||||
PxU8* memory = reinterpret_cast<PxU8*>(PX_ALLOC(size, "PxcNpExceptionalMemory"));
|
||||
if(memory)
|
||||
{
|
||||
PxMutex::ScopedLock lock(mLock);
|
||||
mExceptionalConstraints.pushBack(memory);
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::release(PxcNpMemBlockArray& deadArray, PxU32* allocationCount)
|
||||
{
|
||||
PxMutex::ScopedLock lock(mLock);
|
||||
PX_ASSERT(mUsedBlocks >= deadArray.size());
|
||||
mUsedBlocks -= deadArray.size();
|
||||
if(allocationCount)
|
||||
{
|
||||
*allocationCount -= deadArray.size();
|
||||
}
|
||||
while(deadArray.size())
|
||||
{
|
||||
PxcNpMemBlock* block = deadArray.popBack();
|
||||
for(PxU32 a = 0; a < mUnused.size(); ++a)
|
||||
{
|
||||
PX_ASSERT(mUnused[a] != block);
|
||||
}
|
||||
mUnused.pushBack(block);
|
||||
}
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::flushUnused()
|
||||
{
|
||||
while(mUnused.size())
|
||||
{
|
||||
PxcNpMemBlock* ptr = mUnused.popBack();
|
||||
PX_FREE(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
PxcNpMemBlock* PxcNpMemBlockPool::acquireConstraintBlock()
|
||||
{
|
||||
// we track the scratch blocks in the constraint block array, because the code in acquireMultipleConstraintBlocks
|
||||
// assumes that acquired blocks are listed there.
|
||||
|
||||
return acquire(mConstraints);
|
||||
}
|
||||
|
||||
PxcNpMemBlock* PxcNpMemBlockPool::acquireConstraintBlock(PxcNpMemBlockArray& memBlocks)
|
||||
{
|
||||
return acquire(memBlocks, &mConstraintAllocations, &mPeakConstraintAllocations, true);
|
||||
}
|
||||
|
||||
PxcNpMemBlock* PxcNpMemBlockPool::acquireContactBlock()
|
||||
{
|
||||
return acquire(mContacts[mContactIndex], NULL, NULL, true);
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::releaseConstraintBlocks(PxcNpMemBlockArray& memBlocks)
|
||||
{
|
||||
PxMutex::ScopedLock lock(mLock);
|
||||
|
||||
while(memBlocks.size())
|
||||
{
|
||||
PxcNpMemBlock* block = memBlocks.popBack();
|
||||
if(mScratchAllocator.isScratchAddr(block))
|
||||
mScratchBlocks.pushBack(block);
|
||||
else
|
||||
{
|
||||
mUnused.pushBack(block);
|
||||
PX_ASSERT(mUsedBlocks>0);
|
||||
mUsedBlocks--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::releaseContacts()
|
||||
{
|
||||
//releaseConstraintBlocks(mContacts);
|
||||
release(mContacts[1-mContactIndex]);
|
||||
mContactIndex = 1-mContactIndex;
|
||||
}
|
||||
|
||||
PxcNpMemBlock* PxcNpMemBlockPool::acquireFrictionBlock()
|
||||
{
|
||||
return acquire(mFriction[mFrictionActiveStream]);
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::swapFrictionStreams()
|
||||
{
|
||||
release(mFriction[1-mFrictionActiveStream]);
|
||||
mFrictionActiveStream = 1-mFrictionActiveStream;
|
||||
}
|
||||
|
||||
PxcNpMemBlock* PxcNpMemBlockPool::acquireNpCacheBlock()
|
||||
{
|
||||
return acquire(mNpCache[mNpCacheActiveStream]);
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::swapNpCacheStreams()
|
||||
{
|
||||
release(mNpCache[1-mNpCacheActiveStream]);
|
||||
mNpCacheActiveStream = 1-mNpCacheActiveStream;
|
||||
}
|
||||
91
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcNpThreadContext.cpp
vendored
Normal file
91
engine/third_party/physx/source/lowlevel/common/src/pipeline/PxcNpThreadContext.cpp
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// 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 "PxcConstraintBlockStream.h"
|
||||
#include "PxcNpThreadContext.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
PxcNpThreadContext::PxcNpThreadContext(PxcNpContext* params) :
|
||||
mRenderOutput (params->mRenderBuffer),
|
||||
mContactBlockStream (params->mNpMemBlockPool),
|
||||
mNpCacheStreamPair (params->mNpMemBlockPool),
|
||||
mNarrowPhaseParams (0.0f, params->mMeshContactMargin, params->mToleranceLength),
|
||||
mPCM (false),
|
||||
mContactCache (false),
|
||||
mCreateAveragePoint (false),
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
mCompressedCacheSize (0),
|
||||
mNbDiscreteContactPairsWithCacheHits(0),
|
||||
mNbDiscreteContactPairsWithContacts (0),
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
mMaxPatches (0),
|
||||
mContactStreamPool (params->mContactStreamPool),
|
||||
mPatchStreamPool (params->mPatchStreamPool),
|
||||
mForceAndIndiceStreamPool (params->mForceAndIndiceStreamPool),
|
||||
mFrictionPatchStreamPool (params->mFrictionPatchStreamPool),
|
||||
mMaterialManager (params->mMaterialManager),
|
||||
mLocalNewTouchCount (0),
|
||||
mLocalLostTouchCount (0)
|
||||
{
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
clearStats();
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
}
|
||||
|
||||
PxcNpThreadContext::~PxcNpThreadContext()
|
||||
{
|
||||
}
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
void PxcNpThreadContext::clearStats()
|
||||
{
|
||||
PxMemSet(mDiscreteContactPairs, 0, sizeof(mDiscreteContactPairs));
|
||||
PxMemSet(mModifiedContactPairs, 0, sizeof(mModifiedContactPairs));
|
||||
mCompressedCacheSize = 0;
|
||||
mNbDiscreteContactPairsWithCacheHits = 0;
|
||||
mNbDiscreteContactPairsWithContacts = 0;
|
||||
}
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
|
||||
void PxcNpThreadContext::reset(PxU32 cmCount)
|
||||
{
|
||||
mContactBlockStream.reset();
|
||||
mNpCacheStreamPair.reset();
|
||||
|
||||
mLocalChangeTouch.clear();
|
||||
mLocalChangeTouch.resize(cmCount);
|
||||
mLocalNewTouchCount = 0;
|
||||
mLocalLostTouchCount = 0;
|
||||
}
|
||||
Reference in New Issue
Block a user