Init
This commit is contained in:
@ -0,0 +1,87 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 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_CONTACTMETHODIMPL_H
|
||||
#define PXC_CONTACTMETHODIMPL_H
|
||||
|
||||
#include "GuGeometryUnion.h"
|
||||
#include "CmPhysXCommon.h"
|
||||
#include "GuContactMethodImpl.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Cm
|
||||
{
|
||||
class RenderOutput;
|
||||
}
|
||||
|
||||
namespace Gu
|
||||
{
|
||||
class ContactBuffer;
|
||||
struct Cache;
|
||||
struct NarrowPhaseParams;
|
||||
}
|
||||
|
||||
namespace Cm
|
||||
{
|
||||
class FastVertex2ShapeScaling;
|
||||
}
|
||||
|
||||
/*!\file
|
||||
This file contains forward declarations of all implemented contact methods.
|
||||
*/
|
||||
|
||||
|
||||
/*! Parameter list without names to avoid unused parameter warnings
|
||||
*/
|
||||
#define CONTACT_METHOD_ARGS_UNUSED \
|
||||
const Gu::GeometryUnion&, \
|
||||
const Gu::GeometryUnion&, \
|
||||
const PxTransform&, \
|
||||
const PxTransform&, \
|
||||
const Gu::NarrowPhaseParams&, \
|
||||
Gu::Cache&, \
|
||||
Gu::ContactBuffer&, \
|
||||
Cm::RenderOutput*
|
||||
|
||||
/*!
|
||||
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 bool gEnablePCMCaching[][PxGeometryType::eGEOMETRY_COUNT];
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,156 @@
|
||||
//
|
||||
// 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-2021 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_CONSTRAINTBLOCKPOOL_H
|
||||
#define PXC_CONSTRAINTBLOCKPOOL_H
|
||||
|
||||
#include "PxvConfig.h"
|
||||
#include "PsArray.h"
|
||||
#include "PsMutex.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
|
||||
@ -0,0 +1,66 @@
|
||||
//
|
||||
// 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-2021 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 PxTransform& tm0, const PxTransform& tm1,
|
||||
const PxcContactMethod conMethod,
|
||||
const Gu::GeometryUnion& shape0, const Gu::GeometryUnion& 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
|
||||
@ -0,0 +1,69 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 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_MATERIALMETHOD_H
|
||||
#define PXC_MATERIALMETHOD_H
|
||||
|
||||
#include "geometry/PxGeometry.h"
|
||||
#include "CmPhysXCommon.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
struct PxsShapeCore;
|
||||
struct PxsMaterialInfo;
|
||||
class PxcNpThreadContext;
|
||||
|
||||
#define MATERIAL_METHOD_ARGS \
|
||||
const PxsShapeCore* shape0, \
|
||||
const PxsShapeCore* shape1, \
|
||||
PxcNpThreadContext& pairContext, \
|
||||
PxsMaterialInfo* materialInfo
|
||||
|
||||
|
||||
#define SINGLE_MATERIAL_METHOD_ARGS \
|
||||
const PxsShapeCore* shape, \
|
||||
const PxU32 index, \
|
||||
PxcNpThreadContext& pairContext, \
|
||||
PxsMaterialInfo* materialInfo
|
||||
|
||||
/*!
|
||||
Method prototype for fetch material routines
|
||||
*/
|
||||
typedef bool (*PxcGetMaterialMethod) (MATERIAL_METHOD_ARGS);
|
||||
|
||||
typedef bool (*PxcGetSingleMaterialMethod) (SINGLE_MATERIAL_METHOD_ARGS);
|
||||
|
||||
extern PxcGetMaterialMethod g_GetMaterialMethodTable[][PxGeometryType::eGEOMETRY_COUNT];
|
||||
|
||||
extern PxcGetSingleMaterialMethod g_GetSingleMaterialMethodTable[PxGeometryType::eGEOMETRY_COUNT];
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
50
physx/source/lowlevel/common/include/pipeline/PxcNpBatch.h
Normal file
50
physx/source/lowlevel/common/include/pipeline/PxcNpBatch.h
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-2021 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);
|
||||
void PxcDiscreteNarrowPhasePCM(PxcNpThreadContext& context, const PxcNpWorkUnit& cmInput, Gu::Cache& cache, PxsContactManagerOutput& output);
|
||||
}
|
||||
|
||||
#endif
|
||||
154
physx/source/lowlevel/common/include/pipeline/PxcNpCache.h
Normal file
154
physx/source/lowlevel/common/include/pipeline/PxcNpCache.h
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-2021 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_NPCACHE_H
|
||||
#define PXC_NPCACHE_H
|
||||
|
||||
#include "foundation/PxMemory.h"
|
||||
|
||||
#include "PsIntrinsics.h"
|
||||
#include "PxcNpCacheStreamPair.h"
|
||||
|
||||
#include "PsPool.h"
|
||||
#include "PsFoundation.h"
|
||||
#include "GuContactMethodImpl.h"
|
||||
#include "PsUtilities.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
void PxcNpCacheWrite(PxcNpCacheStreamPair& streams,
|
||||
Gu::Cache& cache,
|
||||
const T& payload,
|
||||
PxU32 bytes,
|
||||
const PxU8* data)
|
||||
{
|
||||
const PxU32 payloadSize = (sizeof(payload)+3)&~3;
|
||||
cache.mCachedSize = Ps::to16((payloadSize + 4 + bytes + 0xF)&~0xF);
|
||||
|
||||
PxU8* ls = streams.reserve(cache.mCachedSize);
|
||||
cache.mCachedData = ls;
|
||||
if(ls==NULL || (reinterpret_cast<PxU8*>(-1))==ls)
|
||||
{
|
||||
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.");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
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.");
|
||||
cache.mCachedData = NULL;
|
||||
ls = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*reinterpret_cast<T*>(ls) = payload;
|
||||
*reinterpret_cast<PxU32*>(ls+payloadSize) = bytes;
|
||||
if(data)
|
||||
PxMemCopy(ls+payloadSize+sizeof(PxU32), data, bytes);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
PxU8* PxcNpCacheWriteInitiate(PxcNpCacheStreamPair& streams, Gu::Cache& cache, const T& payload, PxU32 bytes)
|
||||
{
|
||||
PX_UNUSED(payload);
|
||||
|
||||
const PxU32 payloadSize = (sizeof(payload)+3)&~3;
|
||||
cache.mCachedSize = Ps::to16((payloadSize + 4 + bytes + 0xF)&~0xF);
|
||||
|
||||
PxU8* ls = streams.reserve(cache.mCachedSize);
|
||||
cache.mCachedData = ls;
|
||||
if(NULL==ls || reinterpret_cast<PxU8*>(-1)==ls)
|
||||
{
|
||||
if(NULL==ls)
|
||||
{
|
||||
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.");
|
||||
}
|
||||
else
|
||||
{
|
||||
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.");
|
||||
cache.mCachedData = NULL;
|
||||
ls = NULL;
|
||||
}
|
||||
}
|
||||
return ls;
|
||||
}
|
||||
|
||||
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 // #ifndef PXC_NPCACHE_H
|
||||
@ -0,0 +1,63 @@
|
||||
//
|
||||
// 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-2021 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_NPCACHESTREAMPAIR_H
|
||||
#define PXC_NPCACHESTREAMPAIR_H
|
||||
|
||||
#include "foundation/PxSimpleTypes.h"
|
||||
#include "PxvConfig.h"
|
||||
#include "PxcNpMemBlockPool.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
static const PxU32 PXC_NPCACHE_BLOCK_SIZE = 16384;
|
||||
|
||||
|
||||
struct PxcNpCacheStreamPair
|
||||
{
|
||||
public:
|
||||
PxcNpCacheStreamPair(PxcNpMemBlockPool& blockPool);
|
||||
|
||||
// reserve can fail and return null.
|
||||
PxU8* reserve(PxU32 byteCount);
|
||||
void reset();
|
||||
private:
|
||||
PxcNpMemBlockPool& mBlockPool;
|
||||
PxcNpMemBlock* mBlock;
|
||||
PxU32 mUsed;
|
||||
private:
|
||||
PxcNpCacheStreamPair& operator=(const PxcNpCacheStreamPair&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,57 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 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_NPCONTACTPREPSHARED_H
|
||||
#define PXC_NPCONTACTPREPSHARED_H
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxcNpThreadContext;
|
||||
struct PxsMaterialInfo;
|
||||
class PxsMaterialManager;
|
||||
class PxsConstraintBlockManager;
|
||||
class PxcConstraintBlockStream;
|
||||
struct PxsContactManagerOutput;
|
||||
|
||||
namespace Gu
|
||||
{
|
||||
struct ContactPoint;
|
||||
}
|
||||
|
||||
static const PxReal PXC_SAME_NORMAL = 0.999f; //Around 6 degrees
|
||||
|
||||
PxU32 writeCompressedContact(const Gu::ContactPoint* const PX_RESTRICT contactPoints, const PxU32 numContactPoints, PxcNpThreadContext* threadContext,
|
||||
PxU8& writtenContactCount, PxU8*& outContactPatches, PxU8*& outContactPoints, PxU16& compressedContactSize, PxReal*& contactForces, PxU32 contactForceByteSize,
|
||||
const PxsMaterialManager* materialManager, bool hasModifiableContacts, bool forceNoResponse, 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
|
||||
@ -0,0 +1,119 @@
|
||||
//
|
||||
// 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-2021 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 "PsArray.h"
|
||||
#include "PxcScratchAllocator.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxcNpMemBlock
|
||||
{
|
||||
enum
|
||||
{
|
||||
SIZE = 16384
|
||||
};
|
||||
PxU8 data[SIZE];
|
||||
};
|
||||
|
||||
typedef Ps::Array<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:
|
||||
|
||||
|
||||
Ps::Mutex mLock;
|
||||
PxcNpMemBlockArray mConstraints;
|
||||
PxcNpMemBlockArray mContacts[2];
|
||||
PxcNpMemBlockArray mFriction[2];
|
||||
PxcNpMemBlockArray mNpCache[2];
|
||||
PxcNpMemBlockArray mScratchBlocks;
|
||||
Ps::Array<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
|
||||
@ -0,0 +1,212 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 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_NPTHREADCONTEXT_H
|
||||
#define PXC_NPTHREADCONTEXT_H
|
||||
|
||||
#include "geometry/PxGeometry.h"
|
||||
#include "geomutils/GuContactBuffer.h"
|
||||
|
||||
#include "PxvConfig.h"
|
||||
#include "CmScaling.h"
|
||||
#include "CmRenderOutput.h"
|
||||
#include "PxcNpCacheStreamPair.h"
|
||||
#include "PxcConstraintBlockStream.h"
|
||||
#include "PxcThreadCoherentCache.h"
|
||||
#include "CmBitMap.h"
|
||||
#include "../pcm/GuPersistentContactManifold.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),
|
||||
mCreateContactStream (false),
|
||||
mContactStreamPool (NULL),
|
||||
mPatchStreamPool (NULL),
|
||||
mForceAndIndiceStreamPool(NULL),
|
||||
mMaterialManager (NULL)
|
||||
{
|
||||
}
|
||||
|
||||
PxcScratchAllocator mScratchAllocator;
|
||||
PxcNpMemBlockPool mNpMemBlockPool;
|
||||
PxReal mMeshContactMargin;
|
||||
PxReal mToleranceLength;
|
||||
Cm::RenderBuffer mRenderBuffer;
|
||||
bool mCreateContactStream; // flag to enforce that contacts are stored persistently per workunit. Used for PVD.
|
||||
PxcDataStreamPool* mContactStreamPool;
|
||||
PxcDataStreamPool* mPatchStreamPool;
|
||||
PxcDataStreamPool* mForceAndIndiceStreamPool;
|
||||
PxcDataStreamPool* mConstraintWriteBackStreamPool;
|
||||
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 bool getCreateContactStream() { return mCreateContactStream; }
|
||||
|
||||
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; }
|
||||
|
||||
Cm::RenderOutput getRenderOutput() { return Cm::RenderOutput(mRenderBuffer); }
|
||||
};
|
||||
|
||||
class PxcNpThreadContext : public PxcThreadCoherentCache<PxcNpThreadContext, PxcNpContext>::EntryBase
|
||||
{
|
||||
PX_NOCOPY(PxcNpThreadContext)
|
||||
public:
|
||||
PxcNpThreadContext(PxcNpContext* params);
|
||||
~PxcNpThreadContext();
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
void clearStats();
|
||||
#endif
|
||||
|
||||
PX_FORCE_INLINE void setCreateContactStream(bool to) { mCreateContactStream = to; }
|
||||
|
||||
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 void addLocalFoundPatchCount(PxU32 foundPatchCount) { mLocalFoundPatchCount += foundPatchCount; }
|
||||
PX_FORCE_INLINE void addLocalLostPatchCount(PxU32 lostPatchCount) { mLocalLostPatchCount += lostPatchCount; }
|
||||
PX_FORCE_INLINE PxU32 getLocalFoundPatchCount() const { return mLocalFoundPatchCount; }
|
||||
PX_FORCE_INLINE PxU32 getLocalLostPatchCount() const { return mLocalLostPatchCount; }
|
||||
|
||||
PX_FORCE_INLINE Cm::BitMap& getLocalChangeTouch() { return mLocalChangeTouch; }
|
||||
|
||||
PX_FORCE_INLINE Cm::BitMap& getLocalPatchChangeMap() { return mLocalPatchCountChange; }
|
||||
|
||||
void reset(PxU32 cmCount);
|
||||
// debugging
|
||||
Cm::RenderOutput 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];
|
||||
#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
|
||||
Gu::ContactBuffer 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
|
||||
Ps::Array<Sc::BodySim*> mBodySimPool;
|
||||
PxsTransformCache* mTransformCache;
|
||||
PxReal* mContactDistance;
|
||||
bool mPCM;
|
||||
bool mContactCache;
|
||||
bool mCreateContactStream; // flag to enforce that contacts are stored persistently per workunit. Used for PVD.
|
||||
bool mCreateAveragePoint; // flag to enforce whether we create average points
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
PxU32 mCompressedCacheSize;
|
||||
PxU32 mNbDiscreteContactPairsWithCacheHits;
|
||||
PxU32 mNbDiscreteContactPairsWithContacts;
|
||||
#endif
|
||||
PxReal mDt; // AP: still needed for ccd
|
||||
PxU32 mCCDPass;
|
||||
PxU32 mCCDFaceIndex;
|
||||
|
||||
PxU32 mMaxPatches;
|
||||
//PxU32 mTotalContactCount;
|
||||
PxU32 mTotalCompressedCacheSize;
|
||||
//PxU32 mTotalPatchCount;
|
||||
|
||||
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* mConstraintWriteBackStreamPool;
|
||||
PxsMaterialManager* mMaterialManager;
|
||||
private:
|
||||
// change touch handling.
|
||||
Cm::BitMap mLocalChangeTouch;
|
||||
Cm::BitMap mLocalPatchCountChange;
|
||||
PxU32 mLocalNewTouchCount;
|
||||
PxU32 mLocalLostTouchCount;
|
||||
PxU32 mLocalFoundPatchCount;
|
||||
PxU32 mLocalLostPatchCount;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
155
physx/source/lowlevel/common/include/pipeline/PxcNpWorkUnit.h
Normal file
155
physx/source/lowlevel/common/include/pipeline/PxcNpWorkUnit.h
Normal file
@ -0,0 +1,155 @@
|
||||
//
|
||||
// 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-2021 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_NPWORKUNIT_H
|
||||
#define PXC_NPWORKUNIT_H
|
||||
|
||||
#include "PxcNpThreadContext.h"
|
||||
#include "PxcMaterialMethodImpl.h"
|
||||
#include "PxcNpCache.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxsRigidCore;
|
||||
struct PxsShapeCore;
|
||||
|
||||
struct PxcNpWorkUnitFlag
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eOUTPUT_CONTACTS = 1,
|
||||
eOUTPUT_CONSTRAINTS = 2,
|
||||
eDISABLE_STRONG_FRICTION = 4,
|
||||
eARTICULATION_BODY0 = 8,
|
||||
eARTICULATION_BODY1 = 16,
|
||||
eDYNAMIC_BODY0 = 32,
|
||||
eDYNAMIC_BODY1 = 64,
|
||||
eMODIFIABLE_CONTACT = 128,
|
||||
eFORCE_THRESHOLD = 256,
|
||||
eDETECT_DISCRETE_CONTACT = 512,
|
||||
eHAS_KINEMATIC_ACTOR = 1024,
|
||||
eDISABLE_RESPONSE = 2048,
|
||||
eDETECT_CCD_CONTACTS = 4096
|
||||
};
|
||||
};
|
||||
|
||||
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)
|
||||
};
|
||||
};
|
||||
|
||||
// PT: TODO: fix the inconsistent namings (mXXX) in this class
|
||||
struct PxcNpWorkUnit
|
||||
{
|
||||
const PxsRigidCore* rigidCore0; // INPUT //4 //8
|
||||
const PxsRigidCore* rigidCore1; // INPUT //8 //16
|
||||
|
||||
const PxsShapeCore* shapeCore0; // INPUT //12 //24
|
||||
const PxsShapeCore* shapeCore1; // INPUT //16 //32
|
||||
|
||||
PxU8* ccdContacts; // OUTPUT //20 //40
|
||||
|
||||
PxU8* frictionDataPtr; // INOUT //24 //48
|
||||
|
||||
PxU16 flags; // INPUT //26 //50
|
||||
PxU8 frictionPatchCount; // INOUT //27 //51
|
||||
PxU8 statusFlags; // OUTPUT (see PxcNpWorkUnitStatusFlag) //28 //52
|
||||
|
||||
PxU8 dominance0; // INPUT //29 //53
|
||||
PxU8 dominance1; // INPUT //30 //54
|
||||
PxU8 geomType0; // INPUT //31 //55
|
||||
PxU8 geomType1; // INPUT //32 //56
|
||||
|
||||
PxU32 index; // INPUT //36 //60
|
||||
|
||||
PxReal restDistance; // INPUT //40 //64
|
||||
|
||||
PxU32 mTransformCache0; // //44 //68
|
||||
PxU32 mTransformCache1; // //48 //72
|
||||
|
||||
PxU32 mEdgeIndex; //inout the island gen edge index //52 //76
|
||||
PxU32 mNpIndex; //INPUT //56 //80
|
||||
|
||||
PxReal mTorsionalPatchRadius; //60 //84
|
||||
PxReal mMinTorsionalPatchRadius; //64 //88
|
||||
};
|
||||
|
||||
/*
|
||||
* A struct to record the number of work units a particular constraint pointer references.
|
||||
* This is created at the beginning of the constriant data and is used to bypass constraint preparation when the
|
||||
* bodies are not moving a lot. In this case, we can recycle the constraints and save ourselves some cycles.
|
||||
*/
|
||||
struct PxcNpWorkUnitBatch
|
||||
{
|
||||
PxcNpWorkUnit* mUnits[4];
|
||||
PxU32 mSize;
|
||||
};
|
||||
|
||||
//#if !defined(PX_P64)
|
||||
//PX_COMPILE_TIME_ASSERT(0 == (sizeof(PxcNpWorkUnit) & 0x0f));
|
||||
//#endif
|
||||
|
||||
PX_FORCE_INLINE void PxcNpWorkUnitClearContactState(PxcNpWorkUnit& n)
|
||||
{
|
||||
n.ccdContacts = NULL;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void PxcNpWorkUnitClearCachedState(PxcNpWorkUnit& n)
|
||||
{
|
||||
n.frictionDataPtr = 0;
|
||||
n.frictionPatchCount = 0;
|
||||
n.ccdContacts = NULL;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void PxcNpWorkUnitClearFrictionCachedState(PxcNpWorkUnit& n)
|
||||
{
|
||||
n.frictionDataPtr = 0;
|
||||
n.frictionPatchCount = 0;
|
||||
n.ccdContacts = NULL;
|
||||
}
|
||||
|
||||
#if !defined(PX_P64)
|
||||
//PX_COMPILE_TIME_ASSERT(sizeof(PxcNpWorkUnit)==128);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
138
physx/source/lowlevel/common/include/utils/PxcScratchAllocator.h
Normal file
138
physx/source/lowlevel/common/include/utils/PxcScratchAllocator.h
Normal file
@ -0,0 +1,138 @@
|
||||
//
|
||||
// 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-2021 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_SCRATCHALLOCATOR_H
|
||||
#define PXC_SCRATCHALLOCATOR_H
|
||||
|
||||
#include "foundation/PxAssert.h"
|
||||
#include "PxvConfig.h"
|
||||
#include "PsMutex.h"
|
||||
#include "PsArray.h"
|
||||
#include "PsAllocator.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxcScratchAllocator
|
||||
{
|
||||
PX_NOCOPY(PxcScratchAllocator)
|
||||
public:
|
||||
PxcScratchAllocator() : mStack(PX_DEBUG_EXP("PxcScratchAllocator")), mStart(NULL), mSize(0)
|
||||
{
|
||||
mStack.reserve(64);
|
||||
mStack.pushBack(0);
|
||||
}
|
||||
|
||||
void setBlock(void* addr, PxU32 size)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
Ps::Mutex::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;
|
||||
|
||||
Ps::Mutex::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;
|
||||
}
|
||||
|
||||
Ps::Mutex::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:
|
||||
Ps::Mutex mLock;
|
||||
Ps::Array<PxU8*> mStack;
|
||||
PxU8* mStart;
|
||||
PxU32 mSize;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,150 @@
|
||||
//
|
||||
// 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-2021 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_THREADCOHERENTCACHE_H
|
||||
#define PXC_THREADCOHERENTCACHE_H
|
||||
|
||||
#include "PsMutex.h"
|
||||
#include "PsAllocator.h"
|
||||
#include "PsSList.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 Ps::AlignedAllocator<16, Ps::ReflectionAllocator<T> >
|
||||
{
|
||||
typedef Ps::AlignedAllocator<16, Ps::ReflectionAllocator<T> > Allocator;
|
||||
PX_NOCOPY(PxcThreadCoherentCache)
|
||||
public:
|
||||
|
||||
typedef Ps::SListEntry 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), __FILE__, __LINE__));
|
||||
new (rv) T(mParams);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PX_INLINE void put(T* item)
|
||||
{
|
||||
root.push(*item);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Ps::SList 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()
|
||||
{
|
||||
Ps::SListEntry* np = mFirst;
|
||||
while(np != NULL)
|
||||
{
|
||||
Ps::SListEntry* 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;
|
||||
Ps::SListEntry* mNext;
|
||||
Ps::SListEntry* mFirst;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
393
physx/source/lowlevel/common/src/pipeline/PxcContactCache.cpp
Normal file
393
physx/source/lowlevel/common/src/pipeline/PxcContactCache.cpp
Normal file
@ -0,0 +1,393 @@
|
||||
//
|
||||
// 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-2021 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 "PxsContactManager.h"
|
||||
#include "PsUtilities.h"
|
||||
#include "PxcNpCache.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
//#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
|
||||
true, //PxcContactSphereConvex
|
||||
true, //PxcContactSphereMesh
|
||||
true, //PxcContactSphereHeightField
|
||||
},
|
||||
|
||||
//PxGeometryType::ePLANE
|
||||
{
|
||||
false, //-
|
||||
false, //PxcInvalidContactPair
|
||||
true, //PxcContactPlaneCapsule
|
||||
true, //PxcContactPlaneBox
|
||||
true, //PxcContactPlaneConvex
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
},
|
||||
|
||||
//PxGeometryType::eCAPSULE
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
true, //PxcContactCapsuleCapsule
|
||||
true, //PxcContactCapsuleBox
|
||||
true, //PxcContactCapsuleConvex
|
||||
true, //PxcContactCapsuleMesh
|
||||
true, //PxcContactCapsuleHeightField
|
||||
},
|
||||
|
||||
//PxGeometryType::eBOX
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
true, //PxcContactBoxBox
|
||||
true, //PxcContactBoxConvex
|
||||
true, //PxcContactBoxMesh
|
||||
true, //PxcContactBoxHeightField
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXMESH
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
true, //PxcContactConvexConvex
|
||||
true, //PxcContactConvexMesh2
|
||||
true, //PxcContactConvexHeightField
|
||||
},
|
||||
|
||||
//PxGeometryType::eTRIANGLEMESH
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
},
|
||||
|
||||
//PxGeometryType::eHEIGHTFIELD
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //PxcInvalidContactPair
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void updateContact( Gu::ContactPoint& dst, const PxcLocalContactsCache& contactsData,
|
||||
const Cm::Matrix34& world0, const Cm::Matrix34& 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)
|
||||
Ps::prefetchLine(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)
|
||||
Ps::prefetchLine(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, Gu::Cache& pairContactCache,
|
||||
const PxTransform& tm0, const PxTransform& tm1,
|
||||
const PxcContactMethod conMethod,
|
||||
const Gu::GeometryUnion& shape0, const Gu::GeometryUnion& shape1)
|
||||
{
|
||||
const Gu::NarrowPhaseParams& params = context.mNarrowPhaseParams;
|
||||
|
||||
// gContactCache_NbCalls++;
|
||||
|
||||
if(pairContactCache.mCachedData)
|
||||
prefetchData128(pairContactCache.mCachedData, pairContactCache.mCachedSize);
|
||||
|
||||
ContactBuffer& 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)
|
||||
{
|
||||
Gu::ContactPoint* PX_RESTRICT dst = contactBuffer.contacts;
|
||||
|
||||
const Cm::Matrix34 world1(tm1);
|
||||
const Cm::Matrix34 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)
|
||||
Ps::prefetchLine(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 = Ps::to16(count);
|
||||
contactsData.mUseFaceIndices = useFaceIndices;
|
||||
|
||||
const Gu::ContactPoint* 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;
|
||||
PxcNpCacheWrite(context.mNpCacheStreamPair, pairContactCache, contactsData, nbBytes, bytes);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -0,0 +1,265 @@
|
||||
//
|
||||
// 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-2021 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"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
static bool PxcInvalidContactPair (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(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactSphereCapsule (GU_CONTACT_METHOD_ARGS) { return contactSphereCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactSphereBox (GU_CONTACT_METHOD_ARGS) { return contactSphereBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactSpherePlane (GU_CONTACT_METHOD_ARGS) { return contactSpherePlane(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactSphereConvex (GU_CONTACT_METHOD_ARGS) { return contactCapsuleConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactSphereMesh (GU_CONTACT_METHOD_ARGS) { return contactSphereMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactSphereHeightField (GU_CONTACT_METHOD_ARGS) { return contactSphereHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactPlaneBox (GU_CONTACT_METHOD_ARGS) { return contactPlaneBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactPlaneCapsule (GU_CONTACT_METHOD_ARGS) { return contactPlaneCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactPlaneConvex (GU_CONTACT_METHOD_ARGS) { return contactPlaneConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactCapsuleCapsule (GU_CONTACT_METHOD_ARGS) { return contactCapsuleCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactCapsuleBox (GU_CONTACT_METHOD_ARGS) { return contactCapsuleBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactCapsuleConvex (GU_CONTACT_METHOD_ARGS) { return contactCapsuleConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactCapsuleMesh (GU_CONTACT_METHOD_ARGS) { return contactCapsuleMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactCapsuleHeightField(GU_CONTACT_METHOD_ARGS) { return contactCapsuleHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactBoxBox (GU_CONTACT_METHOD_ARGS) { return contactBoxBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactBoxConvex (GU_CONTACT_METHOD_ARGS) { return contactBoxConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactBoxMesh (GU_CONTACT_METHOD_ARGS) { return contactBoxMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactBoxHeightField (GU_CONTACT_METHOD_ARGS) { return contactBoxHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactConvexConvex (GU_CONTACT_METHOD_ARGS) { return contactConvexConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactConvexMesh (GU_CONTACT_METHOD_ARGS) { return contactConvexMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactConvexHeightField (GU_CONTACT_METHOD_ARGS) { return contactConvexHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
|
||||
static bool PxcPCMContactSphereSphere (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereSphere(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactSpherePlane (GU_CONTACT_METHOD_ARGS) { return pcmContactSpherePlane(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactSphereBox (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactSphereCapsule (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactSphereConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactSphereMesh (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactSphereHeightField (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereHeightField(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactPlaneCapsule (GU_CONTACT_METHOD_ARGS) { return pcmContactPlaneCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactPlaneBox (GU_CONTACT_METHOD_ARGS) { return pcmContactPlaneBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactPlaneConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactPlaneConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactCapsuleCapsule (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactCapsuleBox (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactCapsuleConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactCapsuleMesh (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactCapsuleHeightField (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleHeightField(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactBoxBox (GU_CONTACT_METHOD_ARGS) { return pcmContactBoxBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactBoxConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactBoxConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactBoxMesh (GU_CONTACT_METHOD_ARGS) { return pcmContactBoxMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactBoxHeightField (GU_CONTACT_METHOD_ARGS) { return pcmContactBoxHeightField(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactConvexConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactConvexConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactConvexMesh (GU_CONTACT_METHOD_ARGS) { return pcmContactConvexMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactConvexHeightField (GU_CONTACT_METHOD_ARGS) { return pcmContactConvexHeightField(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
|
||||
#define DYNAMIC_CONTACT_REGISTRATION(x) PxcInvalidContactPair
|
||||
//#define DYNAMIC_CONTACT_REGISTRATION(x) x
|
||||
|
||||
//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
|
||||
PxcContactSphereConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcContactSphereMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcContactSphereHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::ePLANE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
PxcInvalidContactPair, //PxGeometryType::ePLANE
|
||||
PxcContactPlaneCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcContactPlaneBox, //PxGeometryType::eBOX
|
||||
PxcContactPlaneConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
//PxGeometryType::eCAPSULE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
PxcContactCapsuleCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcContactCapsuleBox, //PxGeometryType::eBOX
|
||||
PxcContactCapsuleConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcContactCapsuleMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcContactCapsuleHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eBOX
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
PxcContactBoxBox, //PxGeometryType::eBOX
|
||||
PxcContactBoxConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcContactBoxMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcContactBoxHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
PxcContactConvexConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcContactConvexMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcContactConvexHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eTRIANGLEMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
//PxGeometryType::eHEIGHTFIELD
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
//#if PERSISTENT_CONTACT_MANIFOLD
|
||||
//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
|
||||
PxcPCMContactSphereConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcPCMContactSphereMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcPCMContactSphereHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::ePLANE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
PxcInvalidContactPair, //PxGeometryType::ePLANE
|
||||
PxcPCMContactPlaneCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcPCMContactPlaneBox, //PxGeometryType::eBOX
|
||||
PxcPCMContactPlaneConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
//PxGeometryType::eCAPSULE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
PxcPCMContactCapsuleCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcPCMContactCapsuleBox, //PxGeometryType::eBOX
|
||||
PxcPCMContactCapsuleConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcPCMContactCapsuleMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcPCMContactCapsuleHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eBOX
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
PxcPCMContactBoxBox, //PxGeometryType::eBOX
|
||||
PxcPCMContactBoxConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcPCMContactBoxMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcPCMContactBoxHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
PxcPCMContactConvexConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcPCMContactConvexMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcPCMContactConvexHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eTRIANGLEMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
//PxGeometryType::eHEIGHTFIELD
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
};
|
||||
|
||||
void PxvRegisterHeightFields()
|
||||
{
|
||||
g_ContactMethodTable[PxGeometryType::eSPHERE][PxGeometryType::eHEIGHTFIELD] = PxcContactSphereHeightField;
|
||||
g_ContactMethodTable[PxGeometryType::eCAPSULE][PxGeometryType::eHEIGHTFIELD] = PxcContactCapsuleHeightField;
|
||||
g_ContactMethodTable[PxGeometryType::eBOX][PxGeometryType::eHEIGHTFIELD] = PxcContactBoxHeightField;
|
||||
g_ContactMethodTable[PxGeometryType::eCONVEXMESH][PxGeometryType::eHEIGHTFIELD] = PxcContactConvexHeightField;
|
||||
|
||||
g_PCMContactMethodTable[PxGeometryType::eSPHERE][PxGeometryType::eHEIGHTFIELD] = PxcPCMContactSphereHeightField;
|
||||
g_PCMContactMethodTable[PxGeometryType::eCAPSULE][PxGeometryType::eHEIGHTFIELD] = PxcPCMContactCapsuleHeightField;
|
||||
g_PCMContactMethodTable[PxGeometryType::eBOX][PxGeometryType::eHEIGHTFIELD] = PxcPCMContactBoxHeightField;
|
||||
g_PCMContactMethodTable[PxGeometryType::eCONVEXMESH][PxGeometryType::eHEIGHTFIELD] = PxcPCMContactConvexHeightField;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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-2021 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/PxTriangleMesh.h"
|
||||
|
||||
#include "PxvGeometry.h"
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "PxcNpThreadContext.h"
|
||||
#include "GuHeightField.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
namespace physx
|
||||
{
|
||||
bool PxcGetMaterialShapeHeightField(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo);
|
||||
bool PxcGetMaterialHeightField(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo);
|
||||
PxU32 GetMaterialIndex(const Gu::HeightFieldData* hfData, PxU32 triangleIndex);
|
||||
}
|
||||
|
||||
physx::PxU32 physx::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;
|
||||
}
|
||||
|
||||
bool physx::PxcGetMaterialHeightField(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
PX_ASSERT(index == 1);
|
||||
PX_UNUSED(index);
|
||||
const ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
const PxHeightFieldGeometryLL& hfGeom = shape->geometry.get<const PxHeightFieldGeometryLL>();
|
||||
if(hfGeom.materials.numIndices <= 1)
|
||||
{
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = shape->materialIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU16* materialIndices = hfGeom.materials.indices;
|
||||
|
||||
const Gu::HeightFieldData* hf = hfGeom.heightFieldData;
|
||||
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
const Gu::ContactPoint& contact = contactBuffer.contacts[i];
|
||||
const PxU32 localMaterialIndex = GetMaterialIndex(hf, contact.internalFaceIndex1);
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = materialIndices[localMaterialIndex];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool physx::PxcGetMaterialShapeHeightField(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
const ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
const PxHeightFieldGeometryLL& hfGeom = shape1->geometry.get<const PxHeightFieldGeometryLL>();
|
||||
if(hfGeom.materials.numIndices <= 1)
|
||||
{
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
|
||||
materialInfo[i].mMaterialIndex1 = shape1->materialIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU16* materialIndices = hfGeom.materials.indices;
|
||||
|
||||
const Gu::HeightFieldData* hf = hfGeom.heightFieldData;
|
||||
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
const Gu::ContactPoint& contact = contactBuffer.contacts[i];
|
||||
materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
|
||||
//contact.featureIndex0 = shape0->materialIndex;
|
||||
const PxU32 localMaterialIndex = GetMaterialIndex(hf, contact.internalFaceIndex1);
|
||||
//contact.featureIndex1 = materialIndices[localMaterialIndex];
|
||||
PX_ASSERT(localMaterialIndex<hfGeom.materials.numIndices);
|
||||
materialInfo[i].mMaterialIndex1 = materialIndices[localMaterialIndex];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
108
physx/source/lowlevel/common/src/pipeline/PxcMaterialMesh.cpp
Normal file
108
physx/source/lowlevel/common/src/pipeline/PxcMaterialMesh.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
//
|
||||
// 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-2021 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/PxTriangleMesh.h"
|
||||
|
||||
#include "PxvGeometry.h"
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "PxcNpThreadContext.h"
|
||||
#include "GuHeightField.h"
|
||||
#include "GuTriangleMesh.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
namespace physx
|
||||
{
|
||||
bool PxcGetMaterialShapeMesh(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo);
|
||||
bool PxcGetMaterialMesh(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo);
|
||||
}
|
||||
|
||||
bool physx::PxcGetMaterialMesh(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
PX_ASSERT(index == 1);
|
||||
PX_UNUSED(index);
|
||||
ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
const PxTriangleMeshGeometryLL& shapeMesh = shape->geometry.get<const PxTriangleMeshGeometryLL>();
|
||||
if(shapeMesh.materials.numIndices <= 1)
|
||||
{
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = shape->materialIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
|
||||
Gu::ContactPoint& contact = contactBuffer.contacts[i];
|
||||
const PxU16* eaMaterialIndices = shapeMesh.materialIndices;
|
||||
|
||||
const PxU32 localMaterialIndex = eaMaterialIndices[contact.internalFaceIndex1];//shapeMesh.triangleMesh->getTriangleMaterialIndex(contact.featureIndex1);
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = shapeMesh.materials.indices[localMaterialIndex];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool physx::PxcGetMaterialShapeMesh(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
|
||||
ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
const PxTriangleMeshGeometryLL& shapeMesh = shape1->geometry.get<const PxTriangleMeshGeometryLL>();
|
||||
// const Gu::TriangleMesh* meshData = shapeMesh.meshData;
|
||||
if(shapeMesh.materials.numIndices <= 1)
|
||||
{
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
|
||||
materialInfo[i].mMaterialIndex1 = shape1->materialIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
|
||||
Gu::ContactPoint& contact = contactBuffer.contacts[i];
|
||||
//contact.featureIndex0 = shape0->materialIndex;
|
||||
materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
|
||||
const PxU16* eaMaterialIndices = shapeMesh.materialIndices;
|
||||
|
||||
const PxU32 localMaterialIndex = eaMaterialIndices[contact.internalFaceIndex1];//shapeMesh.triangleMesh->getTriangleMaterialIndex(contact.featureIndex1);
|
||||
//contact.featureIndex1 = shapeMesh.materials.indices[localMaterialIndex];
|
||||
materialInfo[i].mMaterialIndex1 = shapeMesh.materials.indices[localMaterialIndex];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -0,0 +1,140 @@
|
||||
//
|
||||
// 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-2021 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 "PxcMaterialMethodImpl.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
bool PxcGetMaterialShapeShape (MATERIAL_METHOD_ARGS);
|
||||
bool PxcGetMaterialShapeMesh (MATERIAL_METHOD_ARGS);
|
||||
bool PxcGetMaterialShapeHeightField (MATERIAL_METHOD_ARGS);
|
||||
bool PxcGetMaterialShape (SINGLE_MATERIAL_METHOD_ARGS);
|
||||
bool PxcGetMaterialMesh (SINGLE_MATERIAL_METHOD_ARGS);
|
||||
bool PxcGetMaterialHeightField (SINGLE_MATERIAL_METHOD_ARGS);
|
||||
|
||||
|
||||
PxcGetSingleMaterialMethod g_GetSingleMaterialMethodTable[PxGeometryType::eGEOMETRY_COUNT] =
|
||||
{
|
||||
PxcGetMaterialShape, //PxGeometryType::eSPHERE
|
||||
PxcGetMaterialShape, //PxGeometryType::ePLANE
|
||||
PxcGetMaterialShape, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
|
||||
};
|
||||
|
||||
//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::eCONVEXMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
|
||||
},
|
||||
|
||||
//PxGeometryType::ePLANE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
0, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
//PxGeometryType::eCAPSULE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eBOX
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eTRIANGLEMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
0, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
//PxGeometryType::eHEIGHTFIELD
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
0, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
//
|
||||
// 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-2021 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/PxTriangleMesh.h"
|
||||
|
||||
#include "PxvGeometry.h"
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "PxcNpThreadContext.h"
|
||||
#include "GuHeightField.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
namespace physx
|
||||
{
|
||||
bool PxcGetMaterialShape(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = shape->materialIndex;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PxcGetMaterialShapeShape(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
|
||||
materialInfo[i].mMaterialIndex1 = shape1->materialIndex;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
445
physx/source/lowlevel/common/src/pipeline/PxcNpBatch.cpp
Normal file
445
physx/source/lowlevel/common/src/pipeline/PxcNpBatch.cpp
Normal file
@ -0,0 +1,445 @@
|
||||
//
|
||||
// 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-2021 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/PxTriangleMesh.h"
|
||||
|
||||
#include "PxcNpBatch.h"
|
||||
#include "PxcNpWorkUnit.h"
|
||||
#include "PxcContactCache.h"
|
||||
#include "PxcMaterialMethodImpl.h"
|
||||
#include "PxcNpContactPrepShared.h"
|
||||
#include "PxvDynamics.h" // for PxsBodyCore
|
||||
#include "PxvGeometry.h" // for PxsShapeCore
|
||||
#include "CmFlushPool.h"
|
||||
#include "CmTask.h"
|
||||
#include "PxsContactManager.h"
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "PxsTransformCache.h"
|
||||
#include "PxsContactManagerState.h"
|
||||
#include "GuGeometryUnion.h"
|
||||
#include "GuPersistentContactManifold.h"
|
||||
#include "PsFoundation.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
|
||||
static void startContacts(PxsContactManagerOutput& output, PxcNpThreadContext& context)
|
||||
{
|
||||
context.mContactBuffer.reset();
|
||||
|
||||
output.contactForces = NULL;
|
||||
output.contactPatches = NULL;
|
||||
output.contactPoints = NULL;
|
||||
output.nbContacts = 0;
|
||||
output.nbPatches = 0;
|
||||
output.statusFlag = 0;
|
||||
}
|
||||
|
||||
static void flipContacts(PxcNpThreadContext& threadContext, PxsMaterialInfo* PX_RESTRICT materialInfo)
|
||||
{
|
||||
ContactBuffer& buffer = threadContext.mContactBuffer;
|
||||
for(PxU32 i=0; i<buffer.count; ++i)
|
||||
{
|
||||
Gu::ContactPoint& contactPoint = buffer.contacts[i];
|
||||
contactPoint.normal = -contactPoint.normal;
|
||||
Ps::swap(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]++;
|
||||
#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;
|
||||
|
||||
PxU32 forceSize = cmOutput.nbContacts * sizeof(PxReal);
|
||||
if(isMeshType)
|
||||
forceSize += cmOutput.nbContacts * sizeof(PxU32);
|
||||
|
||||
PxU8* PX_RESTRICT contactPatches = NULL;
|
||||
PxU8* PX_RESTRICT contactPoints = NULL;
|
||||
|
||||
PxReal* forceBuffer = 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(Ps::atomicAdd(&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(Ps::atomicAdd(&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(Ps::atomicAdd(&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(isOverflown)
|
||||
{
|
||||
contactPatches = NULL;
|
||||
contactPoints = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU32 alignedOldSize = (oldSize + 0xf) & 0xfffffff0;
|
||||
|
||||
PxU8* data = context.mContactBlockStream.reserve(alignedOldSize + forceSize);
|
||||
if(forceSize)
|
||||
forceBuffer = reinterpret_cast<PxReal*>(data + alignedOldSize);
|
||||
|
||||
contactPatches = data;
|
||||
contactPoints = data + cmOutput.nbPatches * sizeof(PxContactPatch);
|
||||
|
||||
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.contactForces = forceBuffer;
|
||||
}
|
||||
|
||||
if(cache.mCachedSize)
|
||||
{
|
||||
if(cache.isMultiManifold())
|
||||
{
|
||||
PX_ASSERT((cache.mCachedSize & 0xF) == 0);
|
||||
PxU8* newData = context.mNpCacheStreamPair.reserve(cache.mCachedSize);
|
||||
PX_ASSERT((reinterpret_cast<uintptr_t>(newData)& 0xF) == 0);
|
||||
PxMemCopy(newData, & cache.getMultipleManifold(), cache.mCachedSize);
|
||||
cache.setMultiManifold(newData);
|
||||
}
|
||||
else if(useContactCache)
|
||||
{
|
||||
//Copy cache information as well...
|
||||
const PxU8* cachedData = cache.mCachedData;
|
||||
PxU8* newData = context.mNpCacheStreamPair.reserve(PxU32(cache.mCachedSize + 0xf) & 0xfff0);
|
||||
PxMemCopy(newData, cachedData, cache.mCachedSize);
|
||||
cache.mCachedData = newData;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
ContactBuffer& 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 = Ps::to8(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++;
|
||||
#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.flags & PxcNpWorkUnitFlag::eOUTPUT_CONTACTS
|
||||
|| threadContext.mCreateContactStream
|
||||
|| (input.flags & PxcNpWorkUnitFlag::eFORCE_THRESHOLD);
|
||||
|
||||
if((!isMeshType && !createReports))
|
||||
contactForceByteSize = 0;
|
||||
|
||||
bool res = (writeCompressedContact(buffer.contacts, buffer.count, &threadContext, npOutput.nbContacts, npOutput.contactPatches, npOutput.contactPoints, compressedContactSize,
|
||||
reinterpret_cast<PxReal*&>(npOutput.contactForces), contactForceByteSize, threadContext.mMaterialManager, ((input.flags & 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--;
|
||||
#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.flags & PxcNpWorkUnitFlag::eDETECT_DISCRETE_CONTACT))
|
||||
return false;
|
||||
|
||||
if(!(output.statusFlag & PxcNpWorkUnitStatusFlag::eDIRTY_MANAGER) && !(input.flags & PxcNpWorkUnitFlag::eMODIFIABLE_CONTACT))
|
||||
{
|
||||
const PxU32 body0Dynamic = PxU32(input.flags & PxcNpWorkUnitFlag::eDYNAMIC_BODY0);
|
||||
const PxU32 body1Dynamic = PxU32(input.flags & PxcNpWorkUnitFlag::eDYNAMIC_BODY1);
|
||||
|
||||
const PxU32 active0 = PxU32(body0Dynamic && !cachedTransform0->isFrozen());
|
||||
const PxU32 active1 = PxU32(body1Dynamic && !cachedTransform1->isFrozen());
|
||||
|
||||
if(!(active0 || active1))
|
||||
{
|
||||
if(flip)
|
||||
Ps::swap(type0, type1);
|
||||
|
||||
const bool useContactCache = useContactCacheT ? context.mContactCache && g_CanUseContactCache[type0][type1] : false;
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
if(output.nbContacts)
|
||||
context.mNbDiscreteContactPairsWithContacts++;
|
||||
#endif
|
||||
const bool isMeshType = type1 > PxGeometryType::eCONVEXMESH;
|
||||
copyBuffers(output, cache, context, useContactCache, isMeshType);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
output.statusFlag &= (~PxcNpWorkUnitStatusFlag::eDIRTY_MANAGER);
|
||||
|
||||
const PxReal contactDist0 = context.mContactDistance[input.mTransformCache0];
|
||||
const PxReal contactDist1 = context.mContactDistance[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)
|
||||
{
|
||||
PxGeometryType::Enum type0 = static_cast<PxGeometryType::Enum>(input.geomType0);
|
||||
PxGeometryType::Enum type1 = static_cast<PxGeometryType::Enum>(input.geomType1);
|
||||
|
||||
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.shapeCore0);
|
||||
PxsShapeCore* shape1 = const_cast<PxsShapeCore*>(input.shapeCore1);
|
||||
|
||||
if(flip)
|
||||
{
|
||||
Ps::swap(type0, type1);
|
||||
Ps::swap(shape0, shape1);
|
||||
Ps::swap(cachedTransform0, cachedTransform1);
|
||||
}
|
||||
|
||||
PxsMaterialInfo materialInfo[ContactBuffer::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;
|
||||
uintptr_t address = uintptr_t(&cache.getMultipleManifold());
|
||||
manifold.fromBuffer(reinterpret_cast<PxU8*>(address));
|
||||
cache.setMultiManifold(&manifold);
|
||||
}
|
||||
else if(cache.isManifold())
|
||||
{
|
||||
void* address = reinterpret_cast<void*>(&cache.getManifold());
|
||||
Ps::prefetch(address);
|
||||
Ps::prefetch(address, 128);
|
||||
Ps::prefetch(address, 256);
|
||||
}
|
||||
}
|
||||
|
||||
updateDiscreteContactStats(context, type0, type1);
|
||||
|
||||
startContacts(output, context);
|
||||
|
||||
const PxTransform* tm0 = &cachedTransform0->transform;
|
||||
const PxTransform* tm1 = &cachedTransform1->transform;
|
||||
PX_ASSERT(tm0->isSane() && tm1->isSane());
|
||||
|
||||
if(useLegacyCodepath)
|
||||
{
|
||||
// PT: many cache misses here...
|
||||
|
||||
Ps::prefetchLine(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)
|
||||
{
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
if(PxcCacheLocalContacts(context, cache, *tm0, *tm1, conMethod, shape0->geometry, shape1->geometry))
|
||||
context.mNbDiscreteContactPairsWithCacheHits++;
|
||||
#else
|
||||
PxcCacheLocalContacts(context, n.pairCache, *tm0, *tm1, conMethod, shape0->geometry, shape1->geometry);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
conMethod(shape0->geometry, shape1->geometry, *tm0, *tm1, context.mNarrowPhaseParams, cache, context.mContactBuffer, &context.mRenderOutput);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxcContactMethod conMethod = g_PCMContactMethodTable[type0][type1];
|
||||
PX_ASSERT(conMethod);
|
||||
|
||||
conMethod(shape0->geometry, shape1->geometry, *tm0, *tm1, context.mNarrowPhaseParams, cache, context.mContactBuffer, &context.mRenderOutput);
|
||||
}
|
||||
|
||||
const PxcGetMaterialMethod materialMethod = g_GetMaterialMethodTable[type0][type1];
|
||||
// PX_ASSERT(materialMethod);
|
||||
if(materialMethod)
|
||||
materialMethod(shape0, shape1, context, materialInfo);
|
||||
|
||||
if(flip)
|
||||
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));
|
||||
|
||||
PxU8* buffer = context.mNpCacheStreamPair.reserve(size);
|
||||
|
||||
PX_ASSERT((reinterpret_cast<uintptr_t>(buffer)& 0xf) == 0);
|
||||
manifold.toBuffer(buffer);
|
||||
cache.setMultiManifold(buffer);
|
||||
cache.mCachedSize = Ps::to16(size);
|
||||
}
|
||||
}
|
||||
|
||||
const bool isMeshType = type1 > PxGeometryType::eCONVEXMESH;
|
||||
finishContacts(input, output, context, materialInfo, isMeshType);
|
||||
}
|
||||
|
||||
void physx::PxcDiscreteNarrowPhase(PxcNpThreadContext& context, const PxcNpWorkUnit& input, Gu::Cache& cache, PxsContactManagerOutput& output)
|
||||
{
|
||||
discreteNarrowPhase<true>(context, input, cache, output);
|
||||
}
|
||||
|
||||
void physx::PxcDiscreteNarrowPhasePCM(PxcNpThreadContext& context, const PxcNpWorkUnit& input, Gu::Cache& cache, PxsContactManagerOutput& output)
|
||||
{
|
||||
discreteNarrowPhase<false>(context, input, cache, output);
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 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 "PsUserAllocated.h"
|
||||
#include "PxcNpMemBlockPool.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
void PxcNpCacheStreamPair::reset()
|
||||
{
|
||||
mBlock = NULL;
|
||||
mUsed = 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
size = (size+15)&~15;
|
||||
|
||||
if(size>PxcNpMemBlock::SIZE)
|
||||
{
|
||||
return reinterpret_cast<PxU8*>(-1);
|
||||
}
|
||||
|
||||
if(mBlock == NULL || mUsed + size > PxcNpMemBlock::SIZE)
|
||||
{
|
||||
mBlock = mBlockPool.acquireNpCacheBlock();
|
||||
mUsed = 0;
|
||||
}
|
||||
|
||||
PxU8* ptr;
|
||||
if(mBlock == NULL)
|
||||
ptr = 0;
|
||||
else
|
||||
{
|
||||
ptr = mBlock->data+mUsed;
|
||||
mUsed += size;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@ -0,0 +1,554 @@
|
||||
//
|
||||
// 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-2021 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 "PsMathUtils.h"
|
||||
#include "PxcNpWorkUnit.h"
|
||||
#include "PxvDynamics.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "PxsMaterialCombiner.h"
|
||||
|
||||
#include "PxcNpContactPrepShared.h"
|
||||
#include "PsAtomic.h"
|
||||
#include "PxsContactManagerState.h"
|
||||
|
||||
#include "PsVecMath.h"
|
||||
using namespace physx;
|
||||
using namespace Ps::aos;
|
||||
|
||||
static PX_FORCE_INLINE void copyContactPoint(PxContact* PX_RESTRICT point, const Gu::ContactPoint* 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;
|
||||
}
|
||||
|
||||
struct StridePatch
|
||||
{
|
||||
PxU8 startIndex;
|
||||
PxU8 endIndex;
|
||||
PxU8 nextIndex;
|
||||
PxU8 totalCount;
|
||||
bool isRoot;
|
||||
};
|
||||
|
||||
PxU32 physx::writeCompressedContact(const Gu::ContactPoint* const PX_RESTRICT contactPoints, const PxU32 numContactPoints, PxcNpThreadContext* threadContext,
|
||||
PxU8& writtenContactCount, PxU8*& outContactPatches, PxU8*& outContactPoints, PxU16& compressedContactSize, PxReal*& outContactForces, PxU32 contactForceByteSize,
|
||||
const PxsMaterialManager* materialManager, bool hasModifiableContacts, bool forceNoResponse, 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Calculate the size of the contact buffer...
|
||||
PX_ALLOCA(strPatches, StridePatch, numContactPoints);
|
||||
|
||||
StridePatch* stridePatches = &strPatches[0];
|
||||
|
||||
PxU32 numStrideHeaders = 1;
|
||||
|
||||
/*const bool hasInternalFaceIndex = contactPoints[0].internalFaceIndex0 != PXC_CONTACT_NO_FACE_INDEX ||
|
||||
contactPoints[0].internalFaceIndex1 != PXC_CONTACT_NO_FACE_INDEX;*/
|
||||
const bool isModifiable = !forceNoResponse && hasModifiableContacts;
|
||||
|
||||
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 PxU32 patchHeaderSize = sizeof(PxContactPatch) * (isModifiable ? totalContactPoints : totalUniquePatches) + additionalHeaderSize;
|
||||
const PxU32 pointSize = totalContactPoints * (isModifiable ? sizeof(PxModifiableContact) : sizeof(PxContact));
|
||||
|
||||
PxU32 requiredContactSize = pointSize;
|
||||
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;
|
||||
|
||||
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(Ps::atomicAdd(&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;
|
||||
|
||||
PxU32 patchIndex = PxU32(Ps::atomicAdd(&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;
|
||||
|
||||
if(contactForceByteSize)
|
||||
{
|
||||
contactForceByteSize = isMeshType ? contactForceByteSize * 2 : contactForceByteSize;
|
||||
contactIndex = PxU32(Ps::atomicAdd(&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
|
||||
{
|
||||
PxU32 alignedRequiredSize = (requiredContactSize + requiredPatchSize + 0xf) & 0xfffffff0;
|
||||
contactForceByteSize = (isMeshType ? contactForceByteSize * 2 : contactForceByteSize);
|
||||
PxU32 totalSize = alignedRequiredSize + contactForceByteSize;
|
||||
PxU8* data = manager ? blockStream->reserve(totalSize, *manager) : threadContext->mContactBlockStream.reserve(totalSize);
|
||||
|
||||
patchData = data;
|
||||
contactData = patchData + requiredPatchSize;
|
||||
|
||||
if(contactForceByteSize)
|
||||
{
|
||||
forceData = reinterpret_cast<PxReal*>((data + alignedRequiredSize));
|
||||
|
||||
if (isMeshType)
|
||||
triangleIndice = reinterpret_cast<PxU32*>(forceData + numContactPoints);
|
||||
|
||||
if(data)
|
||||
{
|
||||
PxMemZero(forceData, contactForceByteSize);
|
||||
}
|
||||
}
|
||||
|
||||
totalRequiredSize = alignedRequiredSize;
|
||||
|
||||
}
|
||||
|
||||
Ps::prefetchLine(patchData);
|
||||
Ps::prefetchLine(contactData);
|
||||
|
||||
if(patchData == NULL)
|
||||
{
|
||||
writtenContactCount = 0;
|
||||
outContactPatches = NULL;
|
||||
outContactPoints = NULL;
|
||||
outContactForces = NULL;
|
||||
compressedContactSize = 0;
|
||||
numPatches = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
if(threadContext)
|
||||
{
|
||||
threadContext->mCompressedCacheSize += totalRequiredSize;
|
||||
threadContext->mTotalCompressedCacheSize += totalRequiredSize;
|
||||
}
|
||||
#endif
|
||||
compressedContactSize = Ps::to16(totalRequiredSize);
|
||||
|
||||
|
||||
|
||||
//PxU32 startIndex = 0;
|
||||
|
||||
//Extract first material
|
||||
PxU16 origMatIndex0 = pMaterial[0].mMaterialIndex0;
|
||||
PxU16 origMatIndex1 = pMaterial[0].mMaterialIndex1;
|
||||
|
||||
PxReal staticFriction, dynamicFriction, combinedRestitution;
|
||||
PxU32 materialFlags;
|
||||
{
|
||||
const PxsMaterialData& data0 = *materialManager->getMaterial(origMatIndex0);
|
||||
const PxsMaterialData& data1 = *materialManager->getMaterial(origMatIndex1);
|
||||
|
||||
combinedRestitution = PxsMaterialCombiner::combineRestitution(data0, data1);
|
||||
PxsMaterialCombiner combiner(1.0f, 1.0f);
|
||||
PxsMaterialCombiner::PxsCombinedMaterial combinedMat = combiner.combineIsotropicFriction(data0, data1);
|
||||
staticFriction = combinedMat.staFriction;
|
||||
dynamicFriction = combinedMat.dynFriction;
|
||||
materialFlags = combinedMat.flags;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
PxContactPatch* PX_RESTRICT patch = patches++;
|
||||
|
||||
PxU32 startIndex = rootPatch.startIndex;
|
||||
|
||||
const PxU16 matIndex0 = pMaterial[startIndex].mMaterialIndex0;
|
||||
const PxU16 matIndex1 = pMaterial[startIndex].mMaterialIndex1;
|
||||
if(matIndex0 != origMatIndex0 || matIndex1 != origMatIndex1)
|
||||
{
|
||||
const PxsMaterialData& data0 = *materialManager->getMaterial(matIndex0);
|
||||
const PxsMaterialData& data1 = *materialManager->getMaterial(matIndex1);
|
||||
|
||||
combinedRestitution = PxsMaterialCombiner::combineRestitution(data0, data1);
|
||||
PxsMaterialCombiner combiner(1.0f, 1.0f);
|
||||
PxsMaterialCombiner::PxsCombinedMaterial combinedMat = combiner.combineIsotropicFriction(data0, data1);
|
||||
staticFriction = combinedMat.staFriction;
|
||||
dynamicFriction = combinedMat.dynFriction;
|
||||
materialFlags = combinedMat.flags;
|
||||
origMatIndex0 = matIndex0;
|
||||
origMatIndex1 = matIndex1;
|
||||
}
|
||||
|
||||
patch->nbContacts = rootPatch.totalCount;
|
||||
|
||||
patch->startContactIndex = Ps::to8(currentIndex);
|
||||
patch->materialFlags = PxU8(materialFlags);
|
||||
patch->staticFriction = staticFriction;
|
||||
patch->dynamicFriction = dynamicFriction;
|
||||
patch->restitution = combinedRestitution;
|
||||
patch->materialIndex0 = matIndex0;
|
||||
patch->materialIndex1 = matIndex1;
|
||||
patch->normal = contactPoints[0].normal;
|
||||
patch->mMassModification.mInvMassScale0 = 1.0f;
|
||||
patch->mMassModification.mInvMassScale1 = 1.0f;
|
||||
patch->mMassModification.mInvInertiaScale0 = 1.0f;
|
||||
patch->mMassModification.mInvInertiaScale1 = 1.0f;
|
||||
patch->internalFlags = PxU8(flags);
|
||||
|
||||
//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[0].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++;
|
||||
Ps::prefetchLine(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++;
|
||||
Ps::prefetchLine(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 PxU16 matIndex0 = pMaterial[rootPatch.startIndex].mMaterialIndex0;
|
||||
const PxU16 matIndex1 = pMaterial[rootPatch.startIndex].mMaterialIndex1;
|
||||
if(matIndex0 != origMatIndex0 || matIndex1 != origMatIndex1)
|
||||
{
|
||||
const PxsMaterialData& data0 = *materialManager->getMaterial(matIndex0);
|
||||
const PxsMaterialData& data1 = *materialManager->getMaterial(matIndex1);
|
||||
|
||||
combinedRestitution = PxsMaterialCombiner::combineRestitution(data0, data1);
|
||||
PxsMaterialCombiner combiner(1.0f, 1.0f);
|
||||
PxsMaterialCombiner::PxsCombinedMaterial combinedMat = combiner.combineIsotropicFriction(data0, data1);
|
||||
staticFriction = combinedMat.staFriction;
|
||||
dynamicFriction = combinedMat.dynFriction;
|
||||
materialFlags = combinedMat.flags;
|
||||
origMatIndex0 = matIndex0;
|
||||
origMatIndex1 = matIndex1;
|
||||
}
|
||||
|
||||
PxContactPatch* PX_RESTRICT patch = patches++;
|
||||
patch->normal = contactPoints[rootPatch.startIndex].normal;
|
||||
patch->nbContacts = rootPatch.totalCount;
|
||||
patch->startContactIndex = Ps::to8(currentIndex);
|
||||
//KS - we could probably compress this further into the header but the complexity might not be worth it
|
||||
patch->staticFriction = staticFriction;
|
||||
patch->dynamicFriction = dynamicFriction;
|
||||
patch->restitution = combinedRestitution;
|
||||
patch->materialIndex0 = matIndex0;
|
||||
patch->materialIndex1 = matIndex1;
|
||||
patch->materialFlags = PxU8(materialFlags);
|
||||
patch->internalFlags = PxU8(flags);
|
||||
patch->mMassModification.mInvMassScale0 = 1.0f;
|
||||
patch->mMassModification.mInvMassScale1 = 1.0f;
|
||||
patch->mMassModification.mInvInertiaScale0 = 1.0f;
|
||||
patch->mMassModification.mInvInertiaScale1 = 1.0f;
|
||||
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++;
|
||||
Ps::prefetchLine(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++;
|
||||
Ps::prefetchLine(point, 128);
|
||||
}
|
||||
index = stridePatches[index].nextIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writtenContactCount = Ps::to8(totalContactPoints);
|
||||
|
||||
return totalRequiredSize;
|
||||
}
|
||||
351
physx/source/lowlevel/common/src/pipeline/PxcNpMemBlockPool.cpp
Normal file
351
physx/source/lowlevel/common/src/pipeline/PxcNpMemBlockPool.cpp
Normal file
@ -0,0 +1,351 @@
|
||||
//
|
||||
// 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-2021 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 "PsUserAllocated.h"
|
||||
#include "PsInlineArray.h"
|
||||
#include "PsFoundation.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
PxcNpMemBlockPool::PxcNpMemBlockPool(PxcScratchAllocator& allocator):
|
||||
mConstraints(PX_DEBUG_EXP("PxcNpMemBlockPool::mConstraints")),
|
||||
mExceptionalConstraints(PX_DEBUG_EXP("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)
|
||||
{
|
||||
Ps::Mutex::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()
|
||||
{
|
||||
Ps::Mutex::ScopedLock lock(mLock);
|
||||
while(mUnused.size())
|
||||
{
|
||||
PX_FREE(mUnused.popBack());
|
||||
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()
|
||||
{
|
||||
Ps::Mutex::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)
|
||||
{
|
||||
Ps::Mutex::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
|
||||
Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
|
||||
"Reached maximum number of allocated blocks so 16k block allocation will fail!");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if PX_CHECKED
|
||||
if(mInitialBlocks)
|
||||
{
|
||||
Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
|
||||
"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)
|
||||
{
|
||||
Ps::Mutex::ScopedLock lock(mLock);
|
||||
mExceptionalConstraints.pushBack(memory);
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::release(PxcNpMemBlockArray& deadArray, PxU32* allocationCount)
|
||||
{
|
||||
Ps::Mutex::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())
|
||||
PX_FREE(mUnused.popBack());
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
Ps::Mutex::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;
|
||||
}
|
||||
|
||||
@ -0,0 +1,94 @@
|
||||
//
|
||||
// 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-2021 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),
|
||||
mBodySimPool (PX_DEBUG_EXP("BodySimPool")),
|
||||
mPCM (false),
|
||||
mContactCache (false),
|
||||
mCreateContactStream (params->mCreateContactStream),
|
||||
mCreateAveragePoint (false),
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
mCompressedCacheSize (0),
|
||||
mNbDiscreteContactPairsWithCacheHits(0),
|
||||
mNbDiscreteContactPairsWithContacts (0),
|
||||
#endif
|
||||
mMaxPatches (0),
|
||||
mTotalCompressedCacheSize (0),
|
||||
mContactStreamPool (params->mContactStreamPool),
|
||||
mPatchStreamPool (params->mPatchStreamPool),
|
||||
mForceAndIndiceStreamPool (params->mForceAndIndiceStreamPool),
|
||||
mMaterialManager (params->mMaterialManager),
|
||||
mLocalNewTouchCount (0),
|
||||
mLocalLostTouchCount (0),
|
||||
mLocalFoundPatchCount (0),
|
||||
mLocalLostPatchCount (0)
|
||||
{
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
clearStats();
|
||||
#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;
|
||||
}
|
||||
#endif
|
||||
|
||||
void PxcNpThreadContext::reset(PxU32 cmCount)
|
||||
{
|
||||
mContactBlockStream.reset();
|
||||
mNpCacheStreamPair.reset();
|
||||
|
||||
mLocalChangeTouch.clear();
|
||||
mLocalChangeTouch.resize(cmCount);
|
||||
mLocalPatchCountChange.clear();
|
||||
mLocalPatchCountChange.resize(cmCount);
|
||||
mLocalNewTouchCount = 0;
|
||||
mLocalLostTouchCount = 0;
|
||||
mLocalFoundPatchCount = 0;
|
||||
mLocalLostPatchCount = 0;
|
||||
}
|
||||
Reference in New Issue
Block a user