This commit is contained in:
2025-11-28 23:13:44 +05:30
commit a3a8e79709
7360 changed files with 1156074 additions and 0 deletions

View File

@ -0,0 +1,127 @@
//
// 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 PXS_MATERIAL_H
#define PXS_MATERIAL_H
#include "foundation/PxVec3.h"
#include "common/PxMetaData.h"
#include "PxMaterial.h"
#include "PsUserAllocated.h"
#include "PsUtilities.h"
#include "CmPhysXCommon.h"
#include "CmUtils.h"
namespace physx
{
#define MATERIAL_INVALID_HANDLE 0xffff
PX_ALIGN_PREFIX(16) struct PxsMaterialData
{
PxReal dynamicFriction; //4
PxReal staticFriction; //8
PxReal restitution; //12
PxMaterialFlags flags; //14
PxU8 fricRestCombineMode; //15
PxU8 padding; //16
PxsMaterialData()
: dynamicFriction(0.0f)
, staticFriction(0.0f)
, restitution(0.0f)
, fricRestCombineMode((PxCombineMode::eAVERAGE << 4) | PxCombineMode::eAVERAGE)
, padding(PX_PADDING_8)
{}
PxsMaterialData(const PxEMPTY) {}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxCombineMode::Enum getFrictionCombineMode() const
{
return PxCombineMode::Enum(fricRestCombineMode >> 4);
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxCombineMode::Enum getRestitutionCombineMode() const
{
return PxCombineMode::Enum(fricRestCombineMode & 0xf);
}
PX_FORCE_INLINE void setFrictionCombineMode(PxCombineMode::Enum frictionFlags)
{
fricRestCombineMode = Ps::to8((fricRestCombineMode & 0xf) | (frictionFlags << 4));
}
PX_FORCE_INLINE void setRestitutionCombineMode(PxCombineMode::Enum restitutionFlags)
{
fricRestCombineMode = Ps::to8((fricRestCombineMode & 0xf0) | (restitutionFlags));
}
}PX_ALIGN_SUFFIX(16);
class PxsMaterialCore : public PxsMaterialData, public Ps::UserAllocated
{
public:
PxsMaterialCore(const PxsMaterialData& desc)
: PxsMaterialData(desc)
, mNxMaterial(0)
, mMaterialIndex(MATERIAL_INVALID_HANDLE)
, mPadding(PX_PADDING_16)
{
}
PxsMaterialCore()
: mNxMaterial(0)
, mMaterialIndex(MATERIAL_INVALID_HANDLE)
, mPadding(PX_PADDING_16)
{
}
PxsMaterialCore(const PxEMPTY) : PxsMaterialData(PxEmpty) {}
~PxsMaterialCore()
{
}
PX_FORCE_INLINE void setNxMaterial(PxMaterial* m) { mNxMaterial = m; }
PX_FORCE_INLINE PxMaterial* getNxMaterial() const { return mNxMaterial; }
PX_FORCE_INLINE void setMaterialIndex(const PxU16 materialIndex) { mMaterialIndex = materialIndex; }
PX_FORCE_INLINE PxU16 getMaterialIndex() const { return mMaterialIndex; }
protected:
PxMaterial* mNxMaterial;
PxU16 mMaterialIndex; //handle assign by the handle manager
PxU16 mPadding;
};
} //namespace phyxs
#endif

View File

@ -0,0 +1,149 @@
//
// 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 PXS_MATERIALMANAGER
#define PXS_MATERIALMANAGER
#include "PxsMaterialCore.h"
#include "PsAlignedMalloc.h"
namespace physx
{
struct PxsMaterialInfo
{
PxU16 mMaterialIndex0;
PxU16 mMaterialIndex1;
};
class PxsMaterialManager
{
public:
PxsMaterialManager()
{
const PxU32 matCount = 128;
materials = reinterpret_cast<PxsMaterialCore*>(physx::shdfnd::AlignedAllocator<16>().allocate(sizeof(PxsMaterialCore)*matCount, __FILE__, __LINE__));
maxMaterials = matCount;
for(PxU32 i=0; i<matCount; ++i)
{
materials[i].setMaterialIndex(MATERIAL_INVALID_HANDLE);
}
}
~PxsMaterialManager()
{
physx::shdfnd::AlignedAllocator<16>().deallocate(materials);
}
void setMaterial(PxsMaterialCore* mat)
{
const PxU16 materialIndex = mat->getMaterialIndex();
resize(PxU32(materialIndex) + 1);
materials[materialIndex] = *mat;
}
void updateMaterial(PxsMaterialCore* mat)
{
materials[mat->getMaterialIndex()] =*mat;
}
void removeMaterial(PxsMaterialCore* mat)
{
mat->setMaterialIndex(MATERIAL_INVALID_HANDLE);
}
PX_FORCE_INLINE PxsMaterialCore* getMaterial(const PxU32 index)const
{
PX_ASSERT(index < maxMaterials);
return &materials[index];
}
PxU32 getMaxSize()const
{
return maxMaterials;
}
void resize(PxU32 minValueForMax)
{
if(maxMaterials>=minValueForMax)
return;
const PxU32 numMaterials = maxMaterials;
maxMaterials = (minValueForMax+31)&~31;
PxsMaterialCore* mat = reinterpret_cast<PxsMaterialCore*>(physx::shdfnd::AlignedAllocator<16>().allocate(sizeof(PxsMaterialCore)*maxMaterials, __FILE__, __LINE__));
for(PxU32 i=0; i<numMaterials; ++i)
{
mat[i] = materials[i];
}
for(PxU32 i = numMaterials; i < maxMaterials; ++i)
{
mat[i].setMaterialIndex(MATERIAL_INVALID_HANDLE);
}
physx::shdfnd::AlignedAllocator<16>().deallocate(materials);
materials = mat;
}
PxsMaterialCore* materials;//make sure materials's start address is 16 bytes align
PxU32 maxMaterials;
PxU32 mPad[2];
};
class PxsMaterialManagerIterator
{
public:
PxsMaterialManagerIterator(PxsMaterialManager& manager) : mManager(manager), mIndex(0)
{
}
bool getNextMaterial(PxsMaterialCore*& materialCore)
{
const PxU32 maxSize = mManager.getMaxSize();
PxU32 index = mIndex;
while(index < maxSize && mManager.getMaterial(index)->getMaterialIndex() == MATERIAL_INVALID_HANDLE)
index++;
materialCore = NULL;
if(index < maxSize)
materialCore = mManager.getMaterial(index++);
mIndex = index;
return materialCore!=NULL;
}
private:
PxsMaterialManagerIterator& operator=(const PxsMaterialManagerIterator&);
PxsMaterialManager& mManager;
PxU32 mIndex;
};
}
#endif

View File

@ -0,0 +1,47 @@
//
// 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 PXD_CONFIG_H
#define PXD_CONFIG_H
/*! \file internal top level include file for lowlevel. */
#include "CmPhysXCommon.h"
#include "PxPhysXConfig.h"
/************************************************************************/
/* Compiler workarounds */
/************************************************************************/
#if PX_VC
#pragma warning(disable: 4355 ) // "this" used in base member initializer list
#pragma warning(disable: 4146 ) // unary minus operator applied to unsigned type.
#endif
#endif

View File

@ -0,0 +1,183 @@
//
// 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 PXV_DYNAMICS_H
#define PXV_DYNAMICS_H
#include "foundation/PxVec3.h"
#include "foundation/PxQuat.h"
#include "foundation/PxTransform.h"
#include "foundation/PxSimpleTypes.h"
#include "PsIntrinsics.h"
#include "PxRigidDynamic.h"
namespace physx
{
/*!
\file
Dynamics interface.
*/
struct PxsRigidCore
{
//= ATTENTION! =====================================================================================
// Changing the data layout of this class breaks the binary serialization format. See comments for
// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
// accordingly.
//==================================================================================================
PxsRigidCore() : mFlags(0), solverIterationCounts(0) {}
PxsRigidCore(const PxEMPTY) : mFlags(PxEmpty) {}
PX_ALIGN_PREFIX(16)
PxTransform body2World PX_ALIGN_SUFFIX(16);
PxRigidBodyFlags mFlags; // API body flags
PxU16 solverIterationCounts; // vel iters are in low word and pos iters in high word.
PX_FORCE_INLINE PxU32 isKinematic() const { return mFlags & PxRigidBodyFlag::eKINEMATIC; }
PX_FORCE_INLINE PxU32 hasCCD() const { return mFlags & PxRigidBodyFlag::eENABLE_CCD; }
PX_FORCE_INLINE PxU32 hasCCDFriction() const { return mFlags & PxRigidBodyFlag::eENABLE_CCD_FRICTION; }
PX_FORCE_INLINE PxU32 hasIdtBody2Actor() const { return mFlags & PxRigidBodyFlag::eRESERVED; }
};
PX_COMPILE_TIME_ASSERT(sizeof(PxsRigidCore) == 32);
struct PxsBodyCore: public PxsRigidCore
{
//= ATTENTION! =====================================================================================
// Changing the data layout of this class breaks the binary serialization format. See comments for
// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
// accordingly.
//==================================================================================================
PxsBodyCore() : PxsRigidCore() { kinematicLink = PxU8(0); }
PxsBodyCore(const PxEMPTY) : PxsRigidCore(PxEmpty) {}
PX_FORCE_INLINE const PxTransform& getBody2Actor() const { return body2Actor; }
PX_FORCE_INLINE void setBody2Actor(const PxTransform& t)
{
if(t.p.isZero() && t.q.isIdentity())
mFlags |= PxRigidBodyFlag::eRESERVED;
else
mFlags.clear(PxRigidBodyFlag::eRESERVED);
body2Actor = t;
}
protected:
PxTransform body2Actor;
public:
PxReal ccdAdvanceCoefficient; //64
PxVec3 linearVelocity;
PxReal maxPenBias;
PxVec3 angularVelocity;
PxReal contactReportThreshold; //96
PxReal maxAngularVelocitySq;
PxReal maxLinearVelocitySq;
PxReal linearDamping;
PxReal angularDamping; //112
PxVec3 inverseInertia;
PxReal inverseMass; //128
PxReal maxContactImpulse;
PxReal sleepThreshold;
PxReal freezeThreshold;
PxReal wakeCounter; //144 this is authoritative wakeCounter
PxReal solverWakeCounter; //this is calculated by the solver when it performs sleepCheck. It is committed to wakeCounter in ScAfterIntegrationTask if the body is still awake.
PxU32 numCountedInteractions;
PxU32 numBodyInteractions; //Used by adaptive force to keep track of the total number of body interactions
PxU8 isFastMoving; //This could be a single bit but it's a u8 at the moment for simplicity's sake
PxU8 disableGravity; //This could be a single bit but it's a u8 at the moment for simplicity's sake
PxRigidDynamicLockFlags lockFlags; //This is u8.
PxU8 kinematicLink; //160 This indicates whether the articulation link is kinematic link. All fits into 16 byte alignment
// PT: TODO: revisit this / move to PxsCCD.cpp
PX_FORCE_INLINE bool shouldCreateContactReports() const
{
const PxU32* binary = reinterpret_cast<const PxU32*>(&contactReportThreshold);
return *binary != 0x7f7fffff; // PX_MAX_REAL
}
// PT: moved from Sc::BodyCore ctor - we don't want to duplicate all this in immediate mode
PX_FORCE_INLINE void init( const PxTransform& bodyPose,
const PxVec3& inverseInertia_, PxReal inverseMass_,
PxReal wakeCounter_, PxReal scaleSpeed,
PxReal linearDamping_, PxReal angularDamping_,
PxReal maxLinearVelocitySq_, PxReal maxAngularVelocitySq_)
{
PX_ASSERT(bodyPose.p.isFinite());
PX_ASSERT(bodyPose.q.isFinite());
// PT: TODO: unify naming convention
// From PxsRigidCore
body2World = bodyPose;
mFlags = PxRigidBodyFlags();
solverIterationCounts = (1 << 8) | 4;
setBody2Actor(PxTransform(PxIdentity));
ccdAdvanceCoefficient = 0.15f;
linearVelocity = PxVec3(0.0f);
maxPenBias = -1e32f;//-PX_MAX_F32;
angularVelocity = PxVec3(0.0f);
contactReportThreshold = PX_MAX_F32;
maxAngularVelocitySq = maxAngularVelocitySq_;
maxLinearVelocitySq = maxLinearVelocitySq_;
linearDamping = linearDamping_;
angularDamping = angularDamping_;
inverseInertia = inverseInertia_;
inverseMass = inverseMass_;
maxContactImpulse = 1e32f;// PX_MAX_F32;
sleepThreshold = 5e-5f * scaleSpeed * scaleSpeed;
freezeThreshold = 2.5e-5f * scaleSpeed * scaleSpeed;
wakeCounter = wakeCounter_;
// PT: this one is not initialized?
//solverWakeCounter
// PT: these are initialized in BodySim ctor
//numCountedInteractions;
//numBodyInteractions;
isFastMoving = false;
disableGravity = false;
lockFlags = PxRigidDynamicLockFlags(0);
}
};
PX_COMPILE_TIME_ASSERT(sizeof(PxsBodyCore) == 160);
}
#endif

View File

@ -0,0 +1,80 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-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 PXV_GEOMETRY_H
#define PXV_GEOMETRY_H
#include "foundation/PxTransform.h"
#include "PxvConfig.h"
/*!
\file
Geometry interface
*/
/************************************************************************/
/* Shapes */
/************************************************************************/
// moved to
#include "GuGeometryUnion.h"
namespace physx
{
struct PxsShapeCore
{
//= ATTENTION! =====================================================================================
// Changing the data layout of this class breaks the binary serialization format. See comments for
// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
// accordingly.
//==================================================================================================
// PX_SERIALIZATION
PxsShapeCore() {}
PxsShapeCore(const PxEMPTY) : geometry(PxEmpty) {}
//~PX_SERIALIZATION
// PT: TODO: unify naming convention
PX_ALIGN_PREFIX(16)
PxTransform transform PX_ALIGN_SUFFIX(16);
PxReal contactOffset;
PxU8 mShapeFlags; // !< API shape flags // PT: TODO: use PxShapeFlags here. Needs to move flags to separate file.
PxU8 mOwnsMaterialIdxMemory; // PT: for de-serialization to avoid deallocating material index list. Moved there from Sc::ShapeCore (since one byte was free).
PxU16 materialIndex;
Gu::GeometryUnion geometry;
};
PX_COMPILE_TIME_ASSERT( (sizeof(PxsShapeCore)&0xf) == 0);
}
#endif

View File

@ -0,0 +1,116 @@
//
// 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 PXD_INIT_H
#define PXD_INIT_H
#include "PxvConfig.h"
#include "PsBasicTemplates.h"
namespace physx
{
/*!
\file
PhysX Low-level, Memory management
*/
/************************************************************************/
/* Error Handling */
/************************************************************************/
enum PxvErrorCode
{
PXD_ERROR_NO_ERROR = 0,
PXD_ERROR_INVALID_PARAMETER,
PXD_ERROR_INVALID_PARAMETER_SIZE,
PXD_ERROR_INTERNAL_ERROR,
PXD_ERROR_NOT_IMPLEMENTED,
PXD_ERROR_NO_CONTEXT,
PXD_ERROR_NO_TASK_MANAGER,
PXD_ERROR_WARNING
};
class PxShape;
class PxRigidActor;
struct PxsShapeCore;
struct PxsRigidCore;
struct PxvOffsetTable
{
PX_FORCE_INLINE PxvOffsetTable() {}
PX_FORCE_INLINE const PxShape* convertPxsShape2Px(const PxsShapeCore* pxs) const
{
return shdfnd::pointerOffset<const PxShape*>(pxs, pxsShapeCore2PxShape);
}
PX_FORCE_INLINE const PxRigidActor* convertPxsRigidCore2PxRigidBody(const PxsRigidCore* pxs) const
{
return shdfnd::pointerOffset<const PxRigidActor*>(pxs, pxsRigidCore2PxRigidBody);
}
PX_FORCE_INLINE const PxRigidActor* convertPxsRigidCore2PxRigidStatic(const PxsRigidCore* pxs) const
{
return shdfnd::pointerOffset<const PxRigidActor*>(pxs, pxsRigidCore2PxRigidStatic);
}
ptrdiff_t pxsShapeCore2PxShape;
ptrdiff_t pxsRigidCore2PxRigidBody;
ptrdiff_t pxsRigidCore2PxRigidStatic;
};
extern PxvOffsetTable gPxvOffsetTable;
/*!
Initialize low-level implementation.
*/
void PxvInit(const PxvOffsetTable& offsetTable);
/*!
Shut down low-level implementation.
*/
void PxvTerm();
/*!
Initialize low-level implementation.
*/
void PxvRegisterHeightFields();
#if PX_SUPPORT_GPU_PHYSX
class PxPhysXGpu* PxvGetPhysXGpu(bool createIfNeeded);
#endif
}
#endif

View File

@ -0,0 +1,213 @@
//
// 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 PXV_MANAGER_H
#define PXV_MANAGER_H
#include "foundation/PxVec3.h"
#include "foundation/PxQuat.h"
#include "foundation/PxTransform.h"
#include "foundation/PxMemory.h"
#include "PxvConfig.h"
#include "PxvGeometry.h"
namespace physx
{
/*!
\file
Manager interface
*/
/************************************************************************/
/* Managers */
/************************************************************************/
class PxsContactManager;
struct PxsRigidCore;
struct PxsShapeCore;
class PxsRigidBody;
/*!
Type of PXD_MANAGER_CCD_MODE property
*/
enum PxvContactManagerCCDMode
{
PXD_MANAGER_CCD_NONE,
PXD_MANAGER_CCD_LINEAR
};
/*!
Manager descriptor
*/
struct PxvManagerDescRigidRigid
{
/*!
Manager user data
\sa PXD_MANAGER_USER_DATA
*/
//void* userData;
/*!
Dominance setting for one way interactions.
A dominance of 0 means the corresp. body will
not be pushable by the other body in the constraint.
\sa PXD_MANAGER_DOMINANCE0
*/
PxU8 dominance0;
/*!
Dominance setting for one way interactions.
A dominance of 0 means the corresp. body will
not be pushable by the other body in the constraint.
\sa PXD_MANAGER_DOMINANCE1
*/
PxU8 dominance1;
/*!
PxsRigidBodies
*/
PxsRigidBody* rigidBody0;
PxsRigidBody* rigidBody1;
/*!
Shape Core structures
*/
const PxsShapeCore* shapeCore0;
const PxsShapeCore* shapeCore1;
/*!
Body Core structures
*/
PxsRigidCore* rigidCore0;
PxsRigidCore* rigidCore1;
/*!
Enable contact information reporting.
*/
int reportContactInfo;
/*!
Enable contact impulse threshold reporting.
*/
int hasForceThreshold;
/*!
Enable generated contacts to be changeable
*/
int contactChangeable;
/*!
Disable strong friction
*/
//int disableStrongFriction;
/*!
Contact resolution rest distance.
*/
PxReal restDistance;
/*!
Disable contact response
*/
int disableResponse;
/*!
Disable discrete contact generation
*/
int disableDiscreteContact;
/*!
Disable CCD contact generation
*/
int disableCCDContact;
/*!
Is connected to an articulation (1 - first body, 2 - second body)
*/
int hasArticulations;
/*!
is connected to a dynamic (1 - first body, 2 - second body)
*/
int hasDynamics;
/*!
Is the pair touching? Use when re-creating the manager with prior knowledge about touch status.
positive: pair is touching
0: touch state unknown (this is a new pair)
negative: pair is not touching
Default is 0
*/
int hasTouch;
/*!
Identifies whether body 1 is kinematic. We can treat kinematics as statics and embed velocity into constraint
because kinematic bodies' velocities will not change
*/
bool body1Kinematic;
/*
Index entries into the transform cache for shape 0
*/
PxU32 transformCache0;
/*
Index entries into the transform cache for shape 1
*/
PxU32 transformCache1;
PxvManagerDescRigidRigid()
{
PxMemSet(this, 0, sizeof(PxvManagerDescRigidRigid));
dominance0 = 1u;
dominance1 = 1u;
}
};
/*!
Report struct for contact manager touch reports
*/
struct PxvContactManagerTouchEvent
{
PxsContactManager* manager; // Manager handle
void* userData; // Manager userdata
};
}
#endif

View File

@ -0,0 +1,114 @@
//
// 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 PXV_SIM_STATS_H
#define PXV_SIM_STATS_H
#include "foundation/PxAssert.h"
#include "foundation/PxMemory.h"
#include "geometry/PxGeometry.h"
#include "CmPhysXCommon.h"
namespace physx
{
/*!
\file
Context handling
*/
/************************************************************************/
/* Context handling, types */
/************************************************************************/
/*!
Description: contains statistics for the simulation.
*/
struct PxvSimStats
{
PxvSimStats() { clearAll(); }
void clearAll() { PxMemZero(this, sizeof(PxvSimStats)); } // set counters to zero
PX_FORCE_INLINE void incCCDPairs(PxGeometryType::Enum g0, PxGeometryType::Enum g1)
{
PX_ASSERT(g0 <= g1); // That's how they should be sorted
mNbCCDPairs[g0][g1]++;
}
PX_FORCE_INLINE void decCCDPairs(PxGeometryType::Enum g0, PxGeometryType::Enum g1)
{
PX_ASSERT(g0 <= g1); // That's how they should be sorted
PX_ASSERT(mNbCCDPairs[g0][g1]);
mNbCCDPairs[g0][g1]--;
}
PX_FORCE_INLINE void incModifiedContactPairs(PxGeometryType::Enum g0, PxGeometryType::Enum g1)
{
PX_ASSERT(g0 <= g1); // That's how they should be sorted
mNbModifiedContactPairs[g0][g1]++;
}
PX_FORCE_INLINE void decModifiedContactPairs(PxGeometryType::Enum g0, PxGeometryType::Enum g1)
{
PX_ASSERT(g0 <= g1); // That's how they should be sorted
PX_ASSERT(mNbModifiedContactPairs[g0][g1]);
mNbModifiedContactPairs[g0][g1]--;
}
// PT: those guys are now persistent and shouldn't be cleared each frame
PxU32 mNbDiscreteContactPairs [PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT];
PxU32 mNbCCDPairs [PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT];
PxU32 mNbModifiedContactPairs [PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT];
PxU32 mNbDiscreteContactPairsTotal; // PT: sum of mNbDiscreteContactPairs, i.e. number of pairs reaching narrow phase
PxU32 mNbDiscreteContactPairsWithCacheHits;
PxU32 mNbDiscreteContactPairsWithContacts;
PxU32 mNbActiveConstraints;
PxU32 mNbActiveDynamicBodies;
PxU32 mNbActiveKinematicBodies;
PxU32 mNbAxisSolverConstraints;
PxU32 mTotalCompressedContactSize;
PxU32 mTotalConstraintSize;
PxU32 mPeakConstraintBlockAllocations;
PxU32 mNbNewPairs;
PxU32 mNbLostPairs;
PxU32 mNbNewTouches;
PxU32 mNbLostTouches;
PxU32 mNbPartitions;
};
}
#endif

View File

@ -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 "PxvGlobals.h"
#include "PxsContext.h"
#include "PxcContactMethodImpl.h"
#include "GuContactMethodImpl.h"
#if PX_SUPPORT_GPU_PHYSX
#include "PxPhysXGpu.h"
physx::PxPhysXGpu* gPxPhysXGpu;
#endif
namespace physx
{
PxvOffsetTable gPxvOffsetTable;
void PxvInit(const PxvOffsetTable& offsetTable)
{
#if PX_SUPPORT_GPU_PHYSX
gPxPhysXGpu = NULL;
#endif
gPxvOffsetTable = offsetTable;
}
void PxvTerm()
{
#if PX_SUPPORT_GPU_PHYSX
if (gPxPhysXGpu)
{
gPxPhysXGpu->release();
gPxPhysXGpu = NULL;
}
#endif
}
}
#if PX_SUPPORT_GPU_PHYSX
namespace physx
{
//forward declare stuff from PxPhysXGpuModuleLoader.cpp
void PxLoadPhysxGPUModule(const char* appGUID);
typedef physx::PxPhysXGpu* (PxCreatePhysXGpu_FUNC)();
extern PxCreatePhysXGpu_FUNC* g_PxCreatePhysXGpu_Func;
PxPhysXGpu* PxvGetPhysXGpu(bool createIfNeeded)
{
if (!gPxPhysXGpu && createIfNeeded)
{
#ifdef PX_PHYSX_GPU_STATIC
gPxPhysXGpu = PxCreatePhysXGpu();
#else
PxLoadPhysxGPUModule(NULL);
if (g_PxCreatePhysXGpu_Func)
{
gPxPhysXGpu = g_PxCreatePhysXGpu_Func();
}
#endif
}
return gPxPhysXGpu;
}
}
#endif

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,69 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-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

View 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

View 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

View File

@ -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

View File

@ -0,0 +1,57 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-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

View File

@ -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

View File

@ -0,0 +1,212 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-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

View 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

View 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

View File

@ -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

View 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;
}

View File

@ -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;
}
}

View File

@ -0,0 +1,117 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-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;
}

View 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;
}

View File

@ -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
},
};
}

View File

@ -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;
}
}

View 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);
}

View File

@ -0,0 +1,75 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-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;
}

View File

@ -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;
}

View 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;
}

View File

@ -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;
}

View File

@ -0,0 +1,51 @@
//
// 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 PXS_BODYSIM_H
#define PXS_BODYSIM_H
#include "PxsRigidBody.h"
namespace physx
{
struct PxsBodySim
{
public:
PxsBodySim() : mRigidBody(NULL)/*, mBodySimIndex(0xffffffff), mUpdated(0)*/
{
}
PxsRigidBody* mRigidBody; //4 or 8
//PxU32 mUpdated; //12 or 16
};
}//physx
#endif

View File

@ -0,0 +1,628 @@
//
// 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 "Ps.h"
#include "GuCCDSweepConvexMesh.h"
#include "PsHashMap.h"
#include "PxsIslandSim.h"
#ifndef PXS_CCD_H
#define PXS_CCD_H
#define CCD_DEBUG_PRINTS 0
#define CCD_POST_DEPENETRATE_DIST 0.001f
#define CCD_ROTATION_LOCKING 0
#define CCD_MIN_TIME_LEFT 0.01f
#define CCD_ANGULAR_IMPULSE 0
#define DEBUG_RENDER_CCD 0
#if CCD_DEBUG_PRINTS
namespace physx {
extern void printCCDDebug(const char* msg, const PxsRigidBody* atom0, PxGeometryType::Enum g0, bool printPtr = true);
extern void printShape(PxsRigidBody* atom0, PxGeometryType::Enum g0, const char* annotation, PxReal dt, PxU32 pass, bool printPtr = true);
}
#define PRINTCCDSHAPE(x) printShape x
#define PRINTCCDDEBUG(x) printCCDDebug x
#else
#define PRINTCCDSHAPE(x)
#define PRINTCCDDEBUG(x)
#endif
namespace physx
{
// ------------------------------------------------------------------------------------------------------------
// a fraction of objects will be CCD active so this is dynamic, not a member of PsxRigidBody
// CCD code builds a temporary array of PxsCCDPair objects (allocated in blocks)
// this is done to gather scattered data from memory and also to reduce PxsRidigBody permanent memory footprint
// we have to do it every pass since new CMs can become fast moving after each pass (and sometimes cease to be)
//
struct PxsCCDBody;
class PxsRigidBody;
struct PxsShapeCore;
struct PxsRigidCore;
class PxsContactManager;
class PxsContext;
class PxCCDContactModifyCallback;
class PxcNpThreadContext;
class PxvNphaseImplementationContext;
namespace Dy
{
class ThresholdStream;
}
/**
\brief structure to represent interactions between a given body and another body.
*/
struct PxsCCDOverlap
{
//The body the interaction relates to
PxsCCDBody* mBody;
//The next interaction in the list
PxsCCDOverlap* mNext;
};
/**
\brief Temporary CCD representation for a shape.
Stores data about a shape that may be frequently used in CCD. It also stores update counters per-shape that can be compared with the body's update
counter to determine if the shape needs its transforms re-calculated. This avoids us needing to store a list of shapes in a CCD body.
*/
struct PxsCCDShape : public Gu::CCDShape
{
public:
const PxsShapeCore* mShapeCore; //Shape core (can be shared)
const PxsRigidCore* mRigidCore; //Rigid body core
IG::NodeIndex mNodeIndex;
/**
\brief Returns the world-space pose for this shape
\param[in] atom The rigid body that this CCD shape is associated with
*/
PxTransform getAbsPose(const PxsRigidBody* atom) const;
/**
\brief Returns the world-space previous pose for this shape
\param[in] atom The rigid body that this CCD shape is associated with
*/
PxTransform getLastCCDAbsPose(const PxsRigidBody* atom) const;
};
/**
\brief Structure to represent a body in the CCD system.
*/
struct PxsCCDBody
{
Cm::SpatialVector mPreSolverVelocity;
PxU16 mIndex; //The CCD body's index
bool mPassDone; //Whether it has been processed in the current CCD pass
bool mHasAnyPassDone; //Whether this body was influenced by any passes
PxReal mTimeLeft; //CCD time left to elapse (normalized in range 0-1)
PxsRigidBody* mBody; //The rigid body
PxsCCDOverlap* mOverlappingObjects; //A list of overlapping bodies for island update
PxU32 mUpdateCount; //How many times this body has eben updated in the CCD. This is correlated with CCD shapes' update counts.
PxU32 mNbInteractionsThisPass; //How many interactions this pass
/**
\brief Returns the CCD body's index.
\return The CCD body's index.
*/
PX_FORCE_INLINE PxU32 getIndex() const { return mIndex; }
/**
\brief Tests whether this body has already registered an overlap with a given body.
\param[in] body The body to test against.
\return Whether this body has already registered an overlap with a given body.
*/
bool overlaps(PxsCCDBody* body) const
{
PxsCCDOverlap* overlaps = mOverlappingObjects;
while(overlaps)
{
if(overlaps->mBody == body)
return true;
overlaps = overlaps->mNext;
}
return false;
}
/**
\brief Registers an overlap with a given body
\param[in] overlap The CCD overlap to register.
*/
void addOverlap(PxsCCDOverlap* overlap)
{
overlap->mNext = mOverlappingObjects;
mOverlappingObjects = overlap;
}
};
/**
\brief a container class used in the CCD that minimizes frequency of hitting the allocator.
This class stores a set of blocks of memory. It is effectively an array that resizes more efficiently because it doesn't need to
reallocate an entire buffer and copy data.
*/
template<typename T, int BLOCK_SIZE>
struct PxsCCDBlockArray
{
/**
\brief A block of data
*/
struct Block : Ps::UserAllocated { T items[BLOCK_SIZE]; };
/**
\brief A header for a block of data.
*/
struct BlockInfo
{
Block* block;
PxU32 count; // number of elements in this block
BlockInfo(Block* aBlock, PxU32 aCount) : block(aBlock), count(aCount) {}
};
/*
\brief An array of block headers
*/
Ps::Array<BlockInfo> blocks;
/**
\brief The current block.
*/
PxU32 currentBlock;
/**
\brief Constructor
*/
PxsCCDBlockArray() : currentBlock(0)
{
blocks.pushBack(BlockInfo(PX_NEW(Block), 0));
}
/**
\brief Destructor
*/
~PxsCCDBlockArray()
{
for (PxU32 i = 0; i < blocks.size(); i++)
{
PX_DELETE(blocks[i].block);
}
currentBlock = 0;
}
/**
\brief Clears this block array.
\note This clear function also deletes all additional blocks
*/
void clear()
{
for (PxU32 i = 0; i < blocks.size(); i++)
{
PX_DELETE(blocks[i].block);
}
blocks.clear();
blocks.pushBack(BlockInfo(PX_NEW(Block), 0)); // at least one block is expected to always be present in the array
currentBlock = 0;
}
/**
\brief Clears this block array but does not release the memory.
*/
void clear_NoDelete()
{
currentBlock = 0;
blocks[0].count = 0;
}
/**
\brief Push a new element onto the back of the block array
\return The new element
*/
T& pushBack()
{
PxU32 numBlocks = blocks.size();
if (blocks[currentBlock].count == BLOCK_SIZE)
{
if((currentBlock + 1) == numBlocks)
{
blocks.pushBack(BlockInfo(PX_NEW(Block), 0));
numBlocks ++;
}
currentBlock++;
blocks[currentBlock].count = 0;
}
const PxU32 count = blocks[currentBlock].count ++;
return blocks[currentBlock].block->items[count];
}
/**
\brief Pushes a new element onto the back of this array, intitializing it to match the data
\param data The data to initialize the new element to
\return The new element
*/
T& pushBack(T& data)
{
PxU32 numBlocks = blocks.size();
if (blocks[currentBlock].count == BLOCK_SIZE)
{
if((currentBlock + 1) == numBlocks)
{
blocks.pushBack(BlockInfo(PX_NEW(Block), 0));
numBlocks ++;
}
currentBlock++;
blocks[currentBlock].count = 0;
}
const PxU32 count = blocks[currentBlock].count ++;
blocks[currentBlock].block->items[count] = data;
return blocks[currentBlock].block->items[count];
}
/**
\brief Pops the last element from the list.
*/
void popBack()
{
PX_ASSERT(blocks[currentBlock].count > 0);
if (blocks[currentBlock].count > 1)
blocks[currentBlock].count --;
else
{
PX_DELETE(blocks[currentBlock].block);
blocks.popBack();
currentBlock--;
}
}
/**
\brief Returns the current size of the array.
\return The current size of the array.
*/
PxU32 size() const
{
return (currentBlock)*BLOCK_SIZE + blocks[currentBlock].count;
}
/**
\brief Returns the element at a given index in the array
\param[in] index The index of the element in the array
\return The element at a given index in the array.
*/
T& operator[] (PxU32 index) const
{
PX_ASSERT(index/BLOCK_SIZE < blocks.size());
PX_ASSERT(index%BLOCK_SIZE < blocks[index/BLOCK_SIZE].count);
return blocks[index/BLOCK_SIZE].block->items[index%BLOCK_SIZE];
}
};
/**
\brief A structure to represent a potential CCD interaction between a pair of shapes
*/
struct PxsCCDPair
{
/**
\brief Defines whether this is an estimated TOI or an accurate TOI.
We store pairs in a priority queue based on the TOIs. We use cheap estimates to cull away work and lazily evaluate TOIs. This means that an element in the
priority queue may either be an estimate or a precise result.
*/
enum E_TOIType
{
eEstimate,
ePrecise
};
PxsRigidBody* mBa0; // Body A. Can be NULL for statics
PxsRigidBody* mBa1; // Body B. Can be NULL for statics
PxsCCDShape* mCCDShape0; // Shape A
PxsCCDShape* mCCDShape1; // Shape B
PxVec3 mMinToiNormal; // The contact normal. Only valid for precise results. On the surface of body/shape A
PxReal mMinToi; // Min TOI. Valid for both precise and estimated results but estimates may be too early (i.e. conservative).
PxReal mPenetrationPostStep; // Valid only for precise sweeps. Only used for initial intersections (i.e. at TOI = 0).
PxVec3 mMinToiPoint; // The contact point. Only valid for precise sweep results.
PxReal mPenetration; // The penetration. Only valid for precise sweep results.
PxsContactManager* mCm; // The contact manager.
PxU32 mIslandId; // The index of the island this pair is in
PxGeometryType::Enum mG0, mG1; // The geometry types for shapes 0 and 1
bool mIsEarliestToiHit; // Indicates this was the earliest hit for one of the bodies in the pair
bool mIsModifiable; // Indicates whether this contact is modifiable
PxU32 mFaceIndex; // The face index. Only valid for precise sweeps involving meshes or heightfields.
PxU16 mMaterialIndex0; // The material index for shape 0
PxU16 mMaterialIndex1; // The material index for shape 1
PxReal mDynamicFriction; // The dynamic friction coefficient
PxReal mStaticFriction; // The static friction coefficient
PxReal mRestitution; // The restitution coefficient
PxU32 mEstimatePass; // The current estimation pass. Used after a sweep hit was found to determine if the pair needs re-estimating.
PxReal mAppliedForce; // The applied force for this pair. Only valid if the pair has been responded to.
PxReal mMaxImpulse; // The maximum impulse to be applied
E_TOIType mToiType; // The TOI type (estimate, precise).
bool mHasFriction; // Whether we want to simulate CCD friction for this pair
/**
\brief Perform a precise sweep for this pair
\param[in] threadContext The per-thread context
\param[in] dt The time-step
\param[in] pass The current CCD pass
\return The normalized TOI. <=1.0 indicates a hit. Otherwise PX_MAX_REAL.
*/
PxReal sweepFindToi(PxcNpThreadContext& threadContext, PxReal dt, PxU32 pass, PxReal ccdThreshold);
/**
\brief Performs a sweep estimation for this pair
\return The normalized TOI. <= 1.0 indicates a potential hit, otherwise PX_MAX_REAL.
*/
PxReal sweepEstimateToi(PxReal ccdThreshold);
/**
\brief Advances this pair to the TOI
\param[in] dt The time-step
\param[in] clipTrajectoryToToi Indicates whether we clip the body's trajectory to the end pose. Only done in the final pass
\return Whether the advance was successful. An advance will be unsuccessful if body bodies were already updated.
*/
bool sweepAdvanceToToi(PxReal dt, bool clipTrajectoryToToi);
/**
\brief Updates the transforms of the shapes involved in this pair.
*/
void updateShapes();
};
/**
\brief Block array of CCD bodies
*/
typedef PxsCCDBlockArray<PxsCCDBody, 128> PxsCCDBodyArray;
/**
\brief Block array of CCD pairs
*/
typedef PxsCCDBlockArray<PxsCCDPair, 128> PxsCCDPairArray;
/**
\brief Block array of CCD overlaps
*/
typedef PxsCCDBlockArray<PxsCCDOverlap, 128> PxsCCDOverlapArray;
/**
\brief Block array of CCD shapes
*/
typedef PxsCCDBlockArray<PxsCCDShape, 128> PxsCCDShapeArray;
/**
\brief Pair structure to be able to look-up a rigid body-shape pair in a map
*/
typedef Ps::Pair<const PxsRigidCore*, const PxsShapeCore*> PxsRigidShapePair;
/**
\brief CCD context object.
*/
class PxsCCDContext
{
public:
/**
\brief Creates this PxsCCDContext
*/
static PxsCCDContext* create(PxsContext* context, Dy::ThresholdStream& dynamicsContext, PxvNphaseImplementationContext& nPhaseContext,
PxReal ccdThreshold);
/**
\brief Destroys this PxsCCDContext
*/
void destroy();
/**
\brief Returns the CCD contact modification callback
\return The CCD contact modification callback
*/
PX_FORCE_INLINE PxCCDContactModifyCallback* getCCDContactModifyCallback() const { return mCCDContactModifyCallback; }
/**
\brief Sets the CCD contact modification callback
\param[in] c The CCD contact modification callback
*/
PX_FORCE_INLINE void setCCDContactModifyCallback(PxCCDContactModifyCallback* c) { mCCDContactModifyCallback = c; }
/**
\brief Returns the maximum number of CCD passes
\return The maximum number of CCD passes
*/
PX_FORCE_INLINE PxU32 getCCDMaxPasses() const { return mCCDMaxPasses; }
/**
\brief Sets the maximum number of CCD passes
\param[in] ccdMaxPasses The maximum number of CCD passes
*/
PX_FORCE_INLINE void setCCDMaxPasses(PxU32 ccdMaxPasses) { mCCDMaxPasses = ccdMaxPasses; }
/**
\brief Returns the current CCD pass
\return The current CCD pass
*/
PX_FORCE_INLINE PxU32 getCurrentCCDPass() const { return miCCDPass; }
/**
\brief Returns The number of swept hits reported
\return The number of swept hits reported
*/
PX_FORCE_INLINE PxI32 getNumSweepHits() const { return mSweepTotalHits; }
/**
\brief Returns The number of updated bodies
\return The number of updated bodies in this CCD pass
*/
PX_FORCE_INLINE PxU32 getNumUpdatedBodies() const { return mUpdatedCCDBodies.size(); }
/**
\brief Returns The update bodies array
\return The updated bodies array from this CCD pass
*/
PX_FORCE_INLINE PxsRigidBody*const* getUpdatedBodies() const { return mUpdatedCCDBodies.begin(); }
/**
\brief Returns Clears the updated bodies array
*/
PX_FORCE_INLINE void clearUpdatedBodies() { mUpdatedCCDBodies.forceSize_Unsafe(0); }
PX_FORCE_INLINE PxReal getCCDThreshold() const { return mCCDThreshold;}
/**
\brief Runs the CCD contact modification.
\param[in] contacts The list of modifiable contacts
\param[in] contactCount The number of contacts
\param[in] shapeCore0 The first shape core
\param[in] shapeCore1 The second shape core
\param[in] rigidCore0 The first rigid core
\param[in] rigidCore1 The second rigid core
\param[in] rigid0 The first rigid body
\param[in] rigid1 The second rigid body
*/
void runCCDModifiableContact(PxModifiableContact* PX_RESTRICT contacts, PxU32 contactCount, const PxsShapeCore* PX_RESTRICT shapeCore0,
const PxsShapeCore* PX_RESTRICT shapeCore1, const PxsRigidCore* PX_RESTRICT rigidCore0, const PxsRigidCore* PX_RESTRICT rigidCore1,
const PxsRigidBody* PX_RESTRICT rigid0, const PxsRigidBody* PX_RESTRICT rigid1);
/**
\brief Performs a single CCD update
This occurs after broad phase and is responsible for creating islands, finding the TOI of collisions, filtering contacts, issuing modification callbacks and responding to
collisions. At the end of this phase all bodies will have stepper to their first TOI if they were involved in a CCD collision this frame.
\param[in] dt The timestep to simulate
\param[in] continuation The continuation task
\param[in] islandSim The island manager
\param[in] disableResweep If this is true, we perform a reduced-fidelity CCD approach
*/
void updateCCD(PxReal dt, PxBaseTask* continuation, IG::IslandSim& islandSim, bool disableResweep, PxI32 numFastMovingShapes);
/**
\brief Signals the beginning of a CCD multi-pass update
*/
void updateCCDBegin();
/**
\brief Resets the CCD contact state in any contact managers that previously had a reported CCD touch. This must be called if CCD update is bypassed for a frame
*/
void resetContactManagers();
protected:
/**
\brief Constructor for PxsCCDContext
\param[in] context The PxsContext that is associated with this PxsCCDContext.
*/
PxsCCDContext(PxsContext* context, Dy::ThresholdStream& thresholdStream, PxvNphaseImplementationContext& nPhaseContext,
PxReal ccdThreshold);
/**
\brief Destructor for PxsCCDContext
*/
~PxsCCDContext();
private:
/**
\brief Verifies the consistency of the CCD context at the beginning
*/
void verifyCCDBegin();
/**
\brief Cleans up after the CCD update has completed
*/
void updateCCDEnd();
/**
\brief Spawns the update island tasks after the initial sweep estimates have been performed
\param[in] continuation The continuation task
*/
void postCCDSweep(PxBaseTask* continuation);
/**
\brief Creates contact buffers for CCD contacts. These will be sent to the user in the contact notification.
\param[in] continuation The continuation task
*/
void postCCDAdvance(PxBaseTask* continuation);
/**
\brief The final phase of the CCD task chain. Cleans up after the parallel update/postCCDAdvance stages.
\param[in] continuation The continuation task
*/
void postCCDDepenetrate(PxBaseTask* continuation);
typedef Cm::DelegateTask<PxsCCDContext, &PxsCCDContext::postCCDSweep> PostCCDSweepTask;
typedef Cm::DelegateTask<PxsCCDContext, &PxsCCDContext::postCCDAdvance> PostCCDAdvanceTask;
typedef Cm::DelegateTask<PxsCCDContext, &PxsCCDContext::postCCDDepenetrate> PostCCDDepenetrateTask;
PostCCDSweepTask mPostCCDSweepTask;
PostCCDAdvanceTask mPostCCDAdvanceTask;
PostCCDDepenetrateTask mPostCCDDepenetrateTask;
PxCCDContactModifyCallback* mCCDContactModifyCallback;
// CCD global data
bool mDisableCCDResweep;
PxU32 miCCDPass;
PxI32 mSweepTotalHits;
// a fraction of objects will be CCD active so PxsCCDBody is dynamic, not a member of PxsRigidBody
PxsCCDBodyArray mCCDBodies;
PxsCCDOverlapArray mCCDOverlaps;
PxsCCDShapeArray mCCDShapes;
Ps::Array<PxsCCDBody*> mIslandBodies;
Ps::Array<PxU16> mIslandSizes;
Ps::Array<PxsRigidBody*> mUpdatedCCDBodies;
Ps::HashMap<PxsRigidShapePair, PxsCCDShape*> mMap;
// temporary array updated during CCD update
//Array<PxsCCDPair> mCCDPairs;
PxsCCDPairArray mCCDPairs;
Ps::Array<PxsCCDPair*> mCCDPtrPairs;
// number of pairs per island
Ps::Array<PxU32> mCCDIslandHistogram;
// thread context valid during CCD update
PxcNpThreadContext* mCCDThreadContext;
// number of pairs to process per thread
PxU32 mCCDPairsPerBatch;
PxU32 mCCDMaxPasses;
PxsContext* mContext;
Dy::ThresholdStream& mThresholdStream;
PxvNphaseImplementationContext& mNphaseContext;
Ps::Mutex mMutex;
PxReal mCCDThreshold;
private:
PX_NOCOPY(PxsCCDContext)
};
}
#endif

View File

@ -0,0 +1,178 @@
//
// 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 PXS_CONTACTMANAGER_H
#define PXS_CONTACTMANAGER_H
#include "PxvConfig.h"
#include "PxcNpWorkUnit.h"
namespace physx
{
class PxsContext;
class PxsRigidBody;
struct PxsCCDBody;
class PxsMaterialManager;
struct PxsCCDShape;
namespace Dy
{
class DynamicsContext;
}
namespace Sc
{
class ShapeInteraction;
}
enum PxsPairVisColor
{
eVIS_COLOR_SWEPTINTEGRATE_OFF = 0x000000,
eVIS_COLOR_SWEPTINTEGRATE_SLOW = 0x404040,
eVIS_COLOR_SWEPTINTEGRATE_CLEAR = 0x007f00,
eVIS_COLOR_SWEPTINTEGRATE_IMPACT = 0x1680ff,
eVIS_COLOR_SWEPTINTEGRATE_FAIL = 0x0000ff
};
/**
\brief Additional header structure for CCD contact data stream.
*/
struct PxsCCDContactHeader
{
/**
\brief Stream for next collision. The same pair can collide multiple times during multiple CCD passes.
*/
PxsCCDContactHeader* nextStream; //4 //8
/**
\brief Size (in bytes) of the CCD contact stream (not including force buffer)
*/
PxU16 contactStreamSize; //6 //10
/**
\brief Defines whether the stream is from a previous pass.
It could happen that the stream can not get allocated because we run out of memory. In that case the current event should not use the stream
from an event of the previous pass.
*/
PxU16 isFromPreviousPass; //8 //12
PxU8 pad[12 - sizeof(PxsCCDContactHeader*)]; //16
};
PX_COMPILE_TIME_ASSERT((sizeof(PxsCCDContactHeader) & 0xF) == 0);
class PxsContactManager
{
public:
PxsContactManager(PxsContext* context, PxU32 index);
~PxsContactManager();
PX_FORCE_INLINE void setDisableStrongFriction(PxU32 d) { (!d) ? mNpUnit.flags &= ~PxcNpWorkUnitFlag::eDISABLE_STRONG_FRICTION
: mNpUnit.flags |= PxcNpWorkUnitFlag::eDISABLE_STRONG_FRICTION; }
PX_FORCE_INLINE PxReal getRestDistance() const { return mNpUnit.restDistance; }
PX_FORCE_INLINE void setRestDistance(PxReal v) { mNpUnit.restDistance = v; }
void destroy();
PX_FORCE_INLINE PxU8 getDominance0() const { return mNpUnit.dominance0; }
PX_FORCE_INLINE void setDominance0(PxU8 v) { mNpUnit.dominance0 = v; }
PX_FORCE_INLINE PxU8 getDominance1() const { return mNpUnit.dominance1; }
PX_FORCE_INLINE void setDominance1(PxU8 v) { mNpUnit.dominance1 = v; }
PX_FORCE_INLINE PxU16 getTouchStatus() const { return PxU16(mNpUnit.statusFlags & PxcNpWorkUnitStatusFlag::eHAS_TOUCH); }
PX_FORCE_INLINE PxU16 touchStatusKnown() const { return PxU16(mNpUnit.statusFlags & PxcNpWorkUnitStatusFlag::eTOUCH_KNOWN); }
PX_FORCE_INLINE PxI32 getTouchIdx() const { return (mNpUnit.statusFlags& PxcNpWorkUnitStatusFlag::eHAS_TOUCH) ? 1 : (mNpUnit.statusFlags& PxcNpWorkUnitStatusFlag::eHAS_NO_TOUCH ? -1 : 0); }
PX_FORCE_INLINE PxU32 getIndex() const { return mNpUnit.index; }
PX_FORCE_INLINE PxU16 getHasCCDRetouch() const { return PxU16(mNpUnit.statusFlags & PxcNpWorkUnitStatusFlag::eHAS_CCD_RETOUCH); }
PX_FORCE_INLINE void clearCCDRetouch() { mNpUnit.statusFlags &= ~PxcNpWorkUnitStatusFlag::eHAS_CCD_RETOUCH; }
PX_FORCE_INLINE void raiseCCDRetouch() { mNpUnit.statusFlags |= PxcNpWorkUnitStatusFlag::eHAS_CCD_RETOUCH; }
// flags stuff - needs to be refactored
PX_FORCE_INLINE Ps::IntBool isChangeable() const { return Ps::IntBool(mFlags & PXS_CM_CHANGEABLE); }
PX_FORCE_INLINE Ps::IntBool getCCD() const { return Ps::IntBool((mFlags & PXS_CM_CCD_LINEAR) && (mNpUnit.flags & PxcNpWorkUnitFlag::eDETECT_CCD_CONTACTS)); }
PX_FORCE_INLINE Ps::IntBool getHadCCDContact() const { return Ps::IntBool(mFlags & PXS_CM_CCD_CONTACT); }
PX_FORCE_INLINE void setHadCCDContact() { mFlags |= PXS_CM_CCD_CONTACT; }
void setCCD(bool enable);
PX_FORCE_INLINE void clearCCDContactInfo() { mFlags &= ~PXS_CM_CCD_CONTACT; mNpUnit.ccdContacts = NULL; }
PX_FORCE_INLINE PxcNpWorkUnit& getWorkUnit() { return mNpUnit; }
PX_FORCE_INLINE const PxcNpWorkUnit& getWorkUnit() const { return mNpUnit; }
PX_FORCE_INLINE void* getUserData() const { return mShapeInteraction; }
// Setup solver-constraints
void resetCachedState();
void resetFrictionCachedState();
Sc::ShapeInteraction* getShapeInteraction() const { return mShapeInteraction; }
private:
//KS - moving this up - we want to get at flags
PxsRigidBody* mRigidBody0; //4 //8
PxsRigidBody* mRigidBody1; //8 //16
PxU32 mFlags; //20 //36
Sc::ShapeInteraction* mShapeInteraction; //16 //32
friend class PxsContext;
// everything required for narrow phase to run
PxcNpWorkUnit mNpUnit;
enum
{
PXS_CM_CHANGEABLE = (1<<0),
PXS_CM_CCD_LINEAR = (1<<1),
PXS_CM_CCD_CONTACT = (1 << 2)
};
friend class Dy::DynamicsContext;
friend struct PxsCCDPair;
friend class PxsIslandManager;
friend class PxsCCDContext;
friend class Sc::ShapeInteraction;
};
}
#endif

View File

@ -0,0 +1,95 @@
//
// 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 PXS_CONTACT_MANAGER_STATE_H
#define PXS_CONTACT_MANAGER_STATE_H
#include "foundation/PxSimpleTypes.h"
namespace physx
{
struct PxsShapeCore;
/**
There is an implicit 1:1 mapping between PxgContactManagerInput and PxsContactManagerOutput. The structures are split because PxgNpContactManagerInput contains constant
data that is produced by the CPU code and PxgNpContactManagerOutput contains per-frame contact information produced by the NP.
There is also a 1:1 mapping between the PxgNpContactManager and PxsContactManager. This mapping is handled within the PxgNPhaseCore.
The previous contact states are implicitly cached in PxsContactManager and will be propagated to the solver. Friction correlation is also done implicitly using cached
information in PxsContactManager.
The NP will produce a list of pairs that found/lost patches for the solver along with updating the PxgNpContactManagerOutput for all pairs.
*/
struct PxsContactManagerStatusFlag
{
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),
eTOUCH_KNOWN = eHAS_NO_TOUCH | eHAS_TOUCH // The touch status is known (if narrowphase never ran for a pair then no flag will be set)
};
};
struct PX_ALIGN_PREFIX(16) PxsContactManagerOutput
{
PxU8* contactPatches; //Start index/ptr for contact patches
PxU8* contactPoints; //Start index/ptr for contact points
PxReal* contactForces; //Start index/ptr for contact forces
PxU8 nbContacts; //Num contacts
PxU8 nbPatches; //Num patches
PxU8 statusFlag; //Status flag (has touch etc.)
PxU8 prevPatches; //Previous number of patches
PX_FORCE_INLINE PxU32* getInternalFaceIndice()
{
return reinterpret_cast<PxU32*>(contactForces + nbContacts);
}
}
PX_ALIGN_SUFFIX(16);
struct /*PX_ALIGN_PREFIX(16)*/ PxsContactManagerPersistency
{
PxU8 mPrevPatches;
PxU8 mNbFrictionPatches;
PxU8 mNbPrevFrictionPatches;
}
/*PX_ALIGN_SUFFIX(16)*/;
}
#endif //PXG_CONTACT_MANAGER_H

View File

@ -0,0 +1,339 @@
//
// 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 PXS_CONTEXT_H
#define PXS_CONTEXT_H
#include "PxVisualizationParameter.h"
#include "PxSceneDesc.h"
#include "CmPool.h"
#include "PxvNphaseImplementationContext.h"
#include "PxvSimStats.h"
#include "PxsContactManager.h"
#include "PxcNpBatch.h"
#include "PxcConstraintBlockStream.h"
#include "PxcNpCacheStreamPair.h"
#include "PxcNpMemBlockPool.h"
#include "CmRenderOutput.h"
#include "CmUtils.h"
#include "CmTask.h"
#include "PxContactModifyCallback.h"
#include "PxsTransformCache.h"
#include "GuPersistentContactManifold.h"
#include "DyArticulation.h"
#if PX_SUPPORT_GPU_PHYSX
namespace physx
{
class PxCudaContextManager;
}
#endif
namespace physx
{
class PxsRigidBody;
struct PxcConstraintBlock;
class PxsMaterialManager;
class PxsCCDContext;
struct PxsContactManagerOutput;
struct PxvContactManagerTouchEvent;
namespace Cm
{
class FlushPool;
}
namespace IG
{
class SimpleIslandManager;
typedef PxU32 EdgeIndex;
}
enum PxsTouchEventCount
{
PXS_LOST_TOUCH_COUNT = 0,
PXS_NEW_TOUCH_COUNT = 1,
PXS_CCD_RETOUCH_COUNT = 2, // pairs that are touching at a CCD pass and were touching at discrete collision or at a previous CCD pass already
// (but they could have lost touch in between)
PXS_PATCH_FOUND_COUNT = 3,
PXS_PATCH_LOST_COUNT = 4,
PXS_TOUCH_EVENT_COUNT = 5
};
class PxsContext : public Ps::UserAllocated, public PxcNpContext
{
PX_NOCOPY(PxsContext)
public:
PxsContext( const PxSceneDesc& desc, PxTaskManager*, Cm::FlushPool&, PxCudaContextManager*, PxU64 contextID);
~PxsContext();
void removeRigidBody(PxsRigidBody&);
Dy::Articulation* createArticulation();
void destroyArticulation(Dy::Articulation&);
void createTransformCache(Ps::VirtualAllocatorCallback& allocatorCallback);
PxsContactManager* createContactManager(PxsContactManager* contactManager, const bool useCCD);
void createCache(Gu::Cache& cache, PxsContactManager* cm, PxU8 geomType0, PxU8 geomType1);
void destroyCache(Gu::Cache& cache);
void destroyContactManager(PxsContactManager* cm);
PX_FORCE_INLINE PxU64 getContextId() const { return mContextID; }
// Collision properties
PX_FORCE_INLINE PxContactModifyCallback* getContactModifyCallback() const { return mContactModifyCallback; }
PX_FORCE_INLINE void setContactModifyCallback(PxContactModifyCallback* c) { mContactModifyCallback = c; mNpImplementationContext->setContactModifyCallback(c);}
// resource-related
void setScratchBlock(void* addr, PxU32 size);
void setContactDistance(Ps::Array<PxReal, Ps::VirtualAllocator>* contactDistance);
// Task-related
void updateContactManager(PxReal dt, bool hasBoundsArrayChanged, bool hasContactDistanceChanged, PxBaseTask* continuation, PxBaseTask* firstPassContinuation);
void secondPassUpdateContactManager(PxReal dt, PxBaseTask* continuation);
void fetchUpdateContactManager();
void swapStreams();
void resetThreadContexts();
// Manager status change
bool getManagerTouchEventCount(int* newTouch, int* lostTouch, int* ccdTouch) const;
bool fillManagerTouchEvents(
PxvContactManagerTouchEvent* newTouch, PxI32& newTouchCount,
PxvContactManagerTouchEvent* lostTouch, PxI32& lostTouchCount,
PxvContactManagerTouchEvent* ccdTouch, PxI32& ccdTouchCount);
PX_FORCE_INLINE void getManagerPatchEventCount(PxU32& foundPatch, PxU32& lostPatch) const { foundPatch = mCMTouchEventCount[PXS_PATCH_FOUND_COUNT]; lostPatch = mCMTouchEventCount[PXS_PATCH_LOST_COUNT]; }
bool fillManagerPatchChangedEvents(
PxsContactManager** foundPatch, PxU32& foundPatchCount,
PxsContactManager** lostPatch, PxU32& lostPatchCount);
void beginUpdate();
// PX_ENABLE_SIM_STATS
PX_FORCE_INLINE PxvSimStats& getSimStats() { return mSimStats; }
PX_FORCE_INLINE const PxvSimStats& getSimStats() const { return mSimStats; }
PX_FORCE_INLINE Cm::FlushPool& getTaskPool() const { return mTaskPool; }
PX_FORCE_INLINE Cm::RenderBuffer& getRenderBuffer() { return mRenderBuffer; }
PxReal getVisualizationParameter(PxVisualizationParameter::Enum param) const;
void setVisualizationParameter(PxVisualizationParameter::Enum param, PxReal value);
PX_FORCE_INLINE void setVisualizationCullingBox(const PxBounds3& box) { mVisualizationCullingBox = box; }
PX_FORCE_INLINE const PxBounds3& getVisualizationCullingBox()const { return mVisualizationCullingBox; }
PX_FORCE_INLINE PxReal getRenderScale() const { return mVisualizationParams[PxVisualizationParameter::eSCALE]; }
Cm::RenderOutput getRenderOutput() { return Cm::RenderOutput(mRenderBuffer); }
PX_FORCE_INLINE bool getPCM() const { return mPCM; }
PX_FORCE_INLINE bool getContactCacheFlag() const { return mContactCache; }
PX_FORCE_INLINE bool getCreateAveragePoint() const { return mCreateAveragePoint; }
// general stuff
void shiftOrigin(const PxVec3& shift);
void setCreateContactStream(bool to);
PX_FORCE_INLINE void setPCM(bool enabled) { mPCM = enabled; }
PX_FORCE_INLINE void setContactCache(bool enabled) { mContactCache = enabled; }
PX_FORCE_INLINE PxcScratchAllocator& getScratchAllocator() { return mScratchAllocator; }
PX_FORCE_INLINE PxsTransformCache& getTransformCache() { return *mTransformCache; }
PX_FORCE_INLINE PxReal* getContactDistance() { return mContactDistance->begin(); }
PX_FORCE_INLINE PxvNphaseImplementationContext* getNphaseImplementationContext() const
{
return mNpImplementationContext;
}
PX_FORCE_INLINE void setNphaseImplementationContext(PxvNphaseImplementationContext* ctx)
{
mNpImplementationContext = ctx;
}
PX_FORCE_INLINE PxvNphaseImplementationContext* getNphaseFallbackImplementationContext() const
{
return mNpFallbackImplementationContext;
}
PX_FORCE_INLINE void setNphaseFallbackImplementationContext(PxvNphaseImplementationContext* ctx)
{
mNpFallbackImplementationContext = ctx;
}
PxU32 getTotalCompressedContactSize() const { return mTotalCompressedCacheSize; }
PxU32 getMaxPatchCount() const { return mMaxPatches; }
PX_FORCE_INLINE PxcThreadCoherentCache<PxcNpThreadContext, PxcNpContext>& getNpThreadContextPool()
{
return mNpThreadContextPool;
}
PX_FORCE_INLINE PxcNpThreadContext* getNpThreadContext()
{
// We may want to conditional compile to exclude this on single threaded implementations
// if it is determined to be a performance hit.
return mNpThreadContextPool.get();
}
PX_FORCE_INLINE void putNpThreadContext(PxcNpThreadContext* threadContext)
{ mNpThreadContextPool.put(threadContext); }
PX_FORCE_INLINE Ps::Mutex& getLock() { return mLock; }
PX_FORCE_INLINE PxTaskManager& getTaskManager()
{
PX_ASSERT(mTaskManager);
return *mTaskManager;
}
PX_FORCE_INLINE PxCudaContextManager* getCudaContextManager()
{
return mCudaContextManager;
}
PX_FORCE_INLINE void clearManagerTouchEvents();
PX_FORCE_INLINE Cm::PoolList<PxsContactManager, PxsContext>& getContactManagerPool()
{
return this->mContactManagerPool;
}
PX_FORCE_INLINE void setActiveContactManager(const PxsContactManager* manager)
{
const PxU32 index = manager->getIndex();
if (index >= mActiveContactManager.size())
{
PxU32 newSize = (2 * index + 256)&~255;
mActiveContactManager.resize(newSize);
}
mActiveContactManager.set(index);
//Record any pairs that have CCD enabled!
if (manager->getCCD())
{
if (index >= mActiveContactManagersWithCCD.size())
{
PxU32 newSize = (2 * index + 256)&~255;
mActiveContactManagersWithCCD.resize(newSize);
}
mActiveContactManagersWithCCD.set(index);
}
}
private:
void mergeCMDiscreteUpdateResults(PxBaseTask* continuation);
PxU32 mIndex;
// Threading
PxcThreadCoherentCache<PxcNpThreadContext, PxcNpContext>
mNpThreadContextPool;
// Contact managers
Cm::PoolList<PxsContactManager, PxsContext> mContactManagerPool;
Ps::Pool<Gu::LargePersistentContactManifold> mManifoldPool;
Ps::Pool<Gu::SpherePersistentContactManifold> mSphereManifoldPool;
Cm::BitMap mActiveContactManager;
Cm::BitMap mActiveContactManagersWithCCD; //KS - adding to filter any pairs that had a touch
Cm::BitMap mContactManagersWithCCDTouch; //KS - adding to filter any pairs that had a touch
Cm::BitMap mContactManagerTouchEvent;
Cm::BitMap mContactManagerPatchChangeEvent;
PxU32 mCMTouchEventCount[PXS_TOUCH_EVENT_COUNT];
Ps::Mutex mLock;
PxContactModifyCallback* mContactModifyCallback;
// narrowphase platform-dependent implementations support
PxvNphaseImplementationContext* mNpImplementationContext;
PxvNphaseImplementationContext* mNpFallbackImplementationContext;
// debug rendering (CS TODO: MS would like to have these wrapped into a class)
PxReal mVisualizationParams[PxVisualizationParameter::eNUM_VALUES];
PxBounds3 mVisualizationCullingBox;
PxTaskManager* mTaskManager;
Cm::FlushPool& mTaskPool;
PxCudaContextManager* mCudaContextManager;
// PxU32 mTouchesLost;
// PxU32 mTouchesFound;
// PX_ENABLE_SIM_STATS
PxvSimStats mSimStats;
bool mPCM;
bool mContactCache;
bool mCreateAveragePoint;
PxsTransformCache* mTransformCache;
Ps::Array<PxReal, Ps::VirtualAllocator>* mContactDistance;
PxU32 mMaxPatches;
PxU32 mTotalCompressedCacheSize;
PxU64 mContextID;
friend class PxsCCDContext;
friend class PxsNphaseImplementationContext;
friend class PxgNphaseImplementationContext; //FDTODO ideally it shouldn't be here..
};
PX_FORCE_INLINE void PxsContext::clearManagerTouchEvents()
{
mContactManagerTouchEvent.clear();
mContactManagerPatchChangeEvent.clear();
for(PxU32 i = 0; i < PXS_TOUCH_EVENT_COUNT; ++i)
{
mCMTouchEventCount[i] = 0;
}
}
}
#endif

View File

@ -0,0 +1,98 @@
//
// 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 PXS_DEFAULT_MEMORY_MANAGER_H
#define PXS_DEFAULT_MEMORY_MANAGER_H
#include "PxsMemoryManager.h"
#include "PsAllocator.h"
#include "PsArray.h"
namespace physx
{
class PxsDefaultMemoryAllocator : public Ps::VirtualAllocatorCallback
{
public:
PxsDefaultMemoryAllocator(const char* name = NULL)
{
PX_UNUSED(name);
#if 0 //PX_USE_NAMED_ALLOCATOR
if (name)
strcpy(mName, name);
else
strcpy(mName, "");
#endif
}
virtual ~PxsDefaultMemoryAllocator()
{
}
virtual void* allocate(const size_t newByteSize, const char* filename, const int line)
{
PX_UNUSED(line);
PX_UNUSED(filename);
#if 0 //PX_USE_NAMED_ALLOCATOR
return PX_ALLOC(newByteSize, mName);
#else
return PX_ALLOC(newByteSize, filename);
#endif
}
virtual void deallocate(void* ptr)
{
if (ptr)
PX_FREE(ptr);
}
#if 0 //PX_USE_NAMED_ALLOCATOR
char mName[32];
#endif
};
class PxsDefaultMemoryManager : public PxsMemoryManager
{
public:
virtual ~PxsDefaultMemoryManager();
virtual Ps::VirtualAllocatorCallback* createHostMemoryAllocator(const PxU32 gpuComputeVersion = 0);
virtual Ps::VirtualAllocatorCallback* createDeviceMemoryAllocator(const PxU32 gpuComputeVersion = 0);
virtual void destroyMemoryAllocator();
Ps::Array<Ps::VirtualAllocatorCallback*> mAllocators;
};
}
#endif

View File

@ -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 PXS_HEAP_MEMORY_ALLOCATOR_H
#define PXS_HEAP_MEMORY_ALLOCATOR_H
#include "foundation/PxSimpleTypes.h"
namespace physx
{
namespace shdfnd
{
class VirtualAllocatorCallback;
}
class PxErrorCallback;
class PxsHostMemoryAllocator;
class PxsHeapMemoryAllocator : public Ps::VirtualAllocatorCallback
{
public:
virtual ~PxsHeapMemoryAllocator(){}
virtual void* allocate(const size_t size, const char* file, const int line) = 0;
virtual void deallocate(void* ptr) = 0;
};
class PxsHeapMemoryAllocatorManager
{
public:
virtual ~PxsHeapMemoryAllocatorManager()
{
}
PxsHeapMemoryAllocator* mMappedMemoryAllocators;
};
}
#endif

View File

@ -0,0 +1,40 @@
//
// 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 PXS_INCREMENTAL_CONSTRAINT_PARTITIONING_H
#define PXS_INCREMENTAL_CONSTRAINT_PARTITIONING_H
#include "PxsSimpleIslandManager.h"
namespace physx
{
}
#endif

View File

@ -0,0 +1,363 @@
//
// 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 PXS_ISLAND_MANAGER_TYPES_H
#define PXS_ISLAND_MANAGER_TYPES_H
#include "CmPhysXCommon.h"
namespace physx
{
class PxsContactManager;
class PxsRigidBody;
namespace Dy
{
struct Constraint;
class Articulation;
}
typedef PxU32 NodeType;
typedef PxU32 EdgeType;
typedef PxU32 IslandType;
#define INVALID_NODE 0xffffffff
#define INVALID_EDGE 0xffffffff
#define INVALID_ISLAND 0xffffffff
namespace Dy
{
typedef size_t ArticulationLinkHandle;
}
//----------------------------------------------------------------------------//
template <class T, T INVLD> class PxsIslandManagerHook
{
friend class PxsIslandManager;
T index;
public:
static const T INVALID = INVLD;
PX_FORCE_INLINE PxsIslandManagerHook(): index(INVLD) {}
PX_FORCE_INLINE PxsIslandManagerHook(const T id): index(id) {}
PX_FORCE_INLINE PxsIslandManagerHook(const PxsIslandManagerHook<T,INVLD>& src) : index(src.index) {}
PX_FORCE_INLINE ~PxsIslandManagerHook(){}
PX_FORCE_INLINE bool isManaged() const { return index!=INVLD; }
private:
};
typedef PxsIslandManagerHook<NodeType,INVALID_NODE> PxsIslandManagerNodeHook;
typedef PxsIslandManagerHook<EdgeType,INVALID_EDGE> PxsIslandManagerEdgeHook;
typedef PxsIslandManagerHook<IslandType,INVALID_ISLAND> PxsIslandManagerIslandHook;
//----------------------------------------------------------------------------//
/**
\brief PxsIslandObjects contains arrays of all rigid bodies, articulations, contact managers, and constraints that
belong to all awake islands. The per array indices denoting the ownership per island are stored in PxsIslandIndices.
@see PxsIslandManager::getIslandObjects
*/
struct PxsIslandObjects
{
/**
\brief Array of all rigid bodies in all awake islands.
\note Each rigid body corresponds to the void* passed to PxsIslandManager::addBody. The PxsRigidBody ptr is computed
by adding the rigid body offset value (passed to PxsIslandManager::create) to the void* pointer
ie [(PxsRigidBody*)((PxU8*)owner + rigidBodyOffset)]
@see PxsIslandManager::addBody, PxsIslandManager::create
*/
PxsRigidBody*const* bodies;
/**
\brief Array of all articulation roots in all awake islands.
\note Each Articulation* corresponds to Dy::getArticulation(articLinkHandle) where
articLinkHandle is the handle passed to PxsIslandManager::setArticulationRootLinkHandle.
@see PxsIslandManager::setArticulationRootLinkHandle, Dy::getArticulation
*/
Dy::Articulation*const* articulations;
/**
\brief Array of all articulation roots in all awake islands.
\note Each void* corresponds to the void* passed to PxsIslandManager::setArticulationRootLinkHandle
@see PxsIslandManager::setArticulationRootLinkHandle
*/
void*const* articulationOwners;
/**
\brief Array of all contact managers in all awake islands.
@see PxsIslandManager::setEdgeRigidCM
*/
struct PxsIndexedContactManager* contactManagers;
/**
\brief Array of all constraints in all awake islands.
@see PxsIslandManager::setEdgeConstraint
*/
struct PxsIndexedConstraint* constraints;
PxsIslandObjects() : bodies(NULL), articulations(NULL), articulationOwners(NULL), contactManagers(NULL), constraints(NULL)
{
}
};
//----------------------------------------------------------------------------//
/**
\brief An array of PxsIslandIndices describes the rigid bodies, articulations, contacts and constraints that
belong to each island.
\note Given an array of PxsIslandIndices, the rigid bodies of the ith island span the inclusive range:
(PxsIslandObjects::bodies[PxsIslandIndices[i]], PxsIslandObjects::bodies[PxsIslandIndices[i+1]-1])
\note Given an array of PxsIslandIndices, the constraints of the ith island span the inclusive range:
(PxsIslandObjects::constraints[PxsIslandIndices[i]], PxsIslandObjects::constraints[PxsIslandIndices[i+1]-1])
@see PxsIslandObjects::getIslandIndices, PxsIslandObjects::getIslandCount
*/
class PxsIslandIndices
{
public:
PxsIslandIndices(){}
~PxsIslandIndices(){}
/**
\brief Return true if the corresponding island has a contact with a static rigid body.
*/
PX_FORCE_INLINE bool getHasStaticContact() const
{
return (1 & hasStaticContact) ? true : false;
}
/**
\brief The starting index of island rigid bodies in the array PxsIslandObjects::bodies
*/
NodeType bodies;
/**
\brief The starting index of island articulations in the arrays PxsIslandObjects::articulations and PxsIslandObjects::articulationOwners
\note The total number of articulations is clamped at 32767 on any platform that uses 16-bit handles.
*/
NodeType articulations : 8*sizeof(NodeType)-1;
private:
NodeType hasStaticContact : 1;
public:
/**
\brief The starting index of island contact managers in the array PxsIslandObjects::contactManagers.
*/
EdgeType contactManagers;
/**
\brief The starting index of island constraints in the array PxsIslandObjects::constraints.
\note islandId is for internal use only and is used for tracking islands that need a second pass.
*/
union
{
EdgeType constraints;
IslandType islandId;
};
//private:
/**
\brief Internal use only.
*/
PX_FORCE_INLINE void setHasStaticContact(const bool b)
{
hasStaticContact = NodeType(b ? 1 : 0);
}
};
PX_COMPILE_TIME_ASSERT(0==(0x07 & sizeof(PxsIslandIndices)));
//----------------------------------------------------------------------------//
typedef Dy::ArticulationLinkHandle PxsNodeType;
/**
\brief Each contact manager or constraint references two separate bodies, where
a body can be a dynamic rigid body, a kinematic rigid body, an articulation or a static.
The struct PxsIndexedInteraction describes the bodies that make up the pair.
*/
struct PxsIndexedInteraction
{
/**
\brief An enumerated list of all possible body types.
A body type is stored for each body in the pair.
*/
enum Enum
{
eBODY = 0,
eKINEMATIC = 1,
eARTICULATION = 2,
eWORLD = 3
};
/**
\brief An index describing how to access body0
\note If body0 is a dynamic (eBODY) rigid body then solverBody0 is an index into PxsIslandObjects::bodies.
\note If body0 is a kinematic (eKINEMATIC) rigid body then solverBody0 is an index into PxsIslandManager::getActiveKinematics.
\note If body0 is a static (eWORLD) then solverBody0 is PX_MAX_U32 or PX_MAX_U64, depending on the platform being 32- or 64-bit.
\note If body0 is an articulation then the articulation is found directly from Dy::getArticulation(articulation0)
*/
union
{
PxsNodeType solverBody0;
Dy::ArticulationLinkHandle articulation0;
};
/**
\brief An index describing how to access body1
\note If body1 is a dynamic (eBODY) rigid body then solverBody1 is an index into PxsIslandObjects::bodies.
\note If body1 is a kinematic (eKINEMATIC) rigid body then solverBody1 is an index into PxsIslandManager::getActiveKinematics.
\note If body1 is a static (eWORLD) then solverBody1 is PX_MAX_U32 or PX_MAX_U64, depending on the platform being 32- or 64-bit.
\note If body1 is an articulation then the articulation is found directly from Dy::getArticulation(articulation1)
*/
union
{
PxsNodeType solverBody1;
Dy::ArticulationLinkHandle articulation1;
};
/**
\brief The type (eBODY, eKINEMATIC etc) of body0
*/
PxU8 indexType0;
/**
\brief The type (eBODY, eKINEMATIC etc) of body1
*/
PxU8 indexType1;
PxU8 pad[2];
};
/**
@see PxsIslandObjects, PxsIndexedInteraction
*/
struct PxsIndexedContactManager : public PxsIndexedInteraction
{
/**
\brief The contact manager corresponds to the value set in PxsIslandManager::setEdgeRigidCM
*/
PxsContactManager* contactManager;
PxsIndexedContactManager(PxsContactManager* cm) : contactManager(cm) {}
};
#if !PX_X64
PX_COMPILE_TIME_ASSERT(0==(sizeof(PxsIndexedContactManager) & 0x0f));
#endif
/**
@see PxsIslandObjects, PxsIndexedInteraction
*/
struct PxsIndexedConstraint : public PxsIndexedInteraction
{
/**
\brief The constraint corresponds to the value set in PxsIslandManager::setEdgeConstraint
*/
Dy::Constraint* constraint;
PxsIndexedConstraint(Dy::Constraint* c) : constraint(c) {}
};
#if !PX_P64_FAMILY
PX_COMPILE_TIME_ASSERT(0==(sizeof(PxsIndexedConstraint) & 0x0f));
#endif
//----------------------------------------------------------------------------//
/**
\brief Any sleeping contact pair that finds itself in an awake island after 1st pass island gen
must participate in 2nd pass narrowphase so that contacts can be generated.
\note Contact managers in sleeping pairs are NULL until PxsIslandManager::setWokenPairContactManagers is complete.
@see PxsIslandManager::getNarrowPhaseSecondPassContactManagers, PxsIslandManager::getNumNarrowPhaseSecondPassContactManagers,
PxsIslandManager::setWokenPairContactManagers
*/
struct PxsNarrowPhaseSecondPassContactManager
{
/**
\brief The contact manager that is to participate in 2nd pass narrowphase.
\note This pointer is NULL after 1st pass island gen and remains NULL until PxsIslandManager::setWokenPairContactManagers
completes.
*/
PxsContactManager* mCM;
/**
\brief The corresponding entry in PxsIslandObjects::contactManagers.
\note All sleeping pairs have a null contact manager during 1st pass island gen. After 1st pass island gen completes,
the bodies to be woken are externally processed. Waking up bodies generates contact managers and passes the pointer to the
corresponding edge. So that the contact manager can be efficiently passed to PxsIslandObjects we store mEdgeId and mSolverCMId.
The contact manager pointers are set in PxsIslandManager::setWokenPairContactManagers
*/
EdgeType mSolverCMId; //Keeps a track of which entries in the solver islands temporarily have a null contact manager
/**
\brief The internal id of the corresponding edge.
*/
EdgeType mEdgeId;
};
} //namespace physx
#endif //PXS_ISLAND_MANAGER_TYPES_H

View File

@ -0,0 +1,78 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-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 PXS_ISLAND_NODEINDEX_H
#define PXS_ISLAND_NODEINDEX_H
#include "foundation/PxSimpleTypes.h"
namespace physx
{
namespace IG
{
#define IG_INVALID_NODE 0x1FFFFFFu
class NodeIndex
{
private:
PxU32 ind;
public:
explicit PX_CUDA_CALLABLE PX_FORCE_INLINE NodeIndex(PxU32 id, PxU32 articLinkId) : ind((id << 7) | (articLinkId << 1) | 1)
{
}
explicit PX_CUDA_CALLABLE PX_FORCE_INLINE NodeIndex(PxU32 id = IG_INVALID_NODE) : ind((id << 7))
{
}
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 index() const { return ind >> 7; }
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 articulationLinkId() const { return ((ind >> 1) & 63); }
PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 isArticulation() const { return ind & 1; }
PX_CUDA_CALLABLE PX_FORCE_INLINE bool isStaticBody() const { return (ind >> 7) == IG_INVALID_NODE; }
PX_CUDA_CALLABLE bool isValid() const { return (ind >> 7) != IG_INVALID_NODE; }
PX_CUDA_CALLABLE void setIndices(PxU32 index, PxU32 articLinkId) { ind = ((index << 7) | (articLinkId << 1) | 1); }
PX_CUDA_CALLABLE void setIndices(PxU32 index) { ind = ((index << 7)); }
PX_CUDA_CALLABLE bool operator < (const IG::NodeIndex& other) const { return ind < other.ind; }
PX_CUDA_CALLABLE bool operator <= (const IG::NodeIndex& other) const { return ind <= other.ind; }
PX_CUDA_CALLABLE bool operator == (const IG::NodeIndex& other) const { return ind == other.ind; }
};
}
}
#endif

View File

@ -0,0 +1,940 @@
//
// 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 PXS_ISLAND_SIM_H
#define PXS_ISLAND_SIM_H
#include "CmPhysXCommon.h"
#include "foundation/PxAssert.h"
#include "PsArray.h"
#include "CmBitMap.h"
#include "CmPriorityQueue.h"
#include "CmBlockArray.h"
#include "PxsIslandNodeIndex.h"
namespace physx
{
namespace Dy
{
struct Constraint;
class ArticulationV;
}
namespace Sc
{
class ArticulationSim;
}
class PxsContactManager;
class PxsRigidBody;
struct PartitionEdge;
namespace IG
{
//This index is
#define IG_INVALID_ISLAND 0xFFFFFFFFu
#define IG_INVALID_EDGE 0xFFFFFFFFu
#define IG_INVALID_LINK 0xFFu
typedef PxU32 IslandId;
typedef PxU32 EdgeIndex;
typedef PxU32 EdgeInstanceIndex;
class IslandSim;
struct Edge
{
//Edge instances can be implicitly calculated based on this edge index, which is an offset into the array of edges.
//From that, the child edge index is simply the
//The constraint or contact referenced by this edge
enum EdgeType
{
eCONTACT_MANAGER,
eCONSTRAINT,
eEDGE_TYPE_COUNT
};
enum EdgeState
{
eINSERTED =1<<0,
ePENDING_DESTROYED =1<<1,
eACTIVE =1<<2,
eIN_DIRTY_LIST =1<<3,
eDESTROYED =1<<4,
eREPORT_ONLY_DESTROY=1<<5,
eACTIVATING =1<<6
};
//NodeIndex mNode1, mNode2;
EdgeType mEdgeType;
PxU16 mEdgeState;
EdgeIndex mNextIslandEdge, mPrevIslandEdge;
PX_FORCE_INLINE void setInserted() { mEdgeState |= (eINSERTED); }
PX_FORCE_INLINE void clearInserted() { mEdgeState &= (~eINSERTED); }
PX_FORCE_INLINE void clearDestroyed() { mEdgeState &=(~eDESTROYED);}
PX_FORCE_INLINE void setPendingDestroyed() { mEdgeState |= ePENDING_DESTROYED; }
PX_FORCE_INLINE void clearPendingDestroyed() { mEdgeState &= (~ePENDING_DESTROYED); }
PX_FORCE_INLINE void activateEdge() { mEdgeState |= eACTIVE; }
PX_FORCE_INLINE void deactivateEdge() { mEdgeState &= (~eACTIVE); }
PX_FORCE_INLINE void markInDirtyList() { mEdgeState |= (eIN_DIRTY_LIST); }
PX_FORCE_INLINE void clearInDirtyList() { mEdgeState &= (~eIN_DIRTY_LIST); }
PX_FORCE_INLINE void setReportOnlyDestroy() { mEdgeState |= (eREPORT_ONLY_DESTROY); }
PX_FORCE_INLINE void clearReportOnlyDestroy() { mEdgeState &= (~eREPORT_ONLY_DESTROY); }
public:
Edge() : mEdgeType(Edge::eCONTACT_MANAGER), mEdgeState(eDESTROYED),
mNextIslandEdge(IG_INVALID_EDGE), mPrevIslandEdge(IG_INVALID_EDGE)
{
}
PX_FORCE_INLINE bool isInserted() const { return !!(mEdgeState & eINSERTED);}
PX_FORCE_INLINE bool isDestroyed() const { return !!(mEdgeState & eDESTROYED); }
PX_FORCE_INLINE bool isPendingDestroyed() const { return !!(mEdgeState & ePENDING_DESTROYED); }
PX_FORCE_INLINE bool isActive() const { return !!(mEdgeState & eACTIVE); }
PX_FORCE_INLINE bool isInDirtyList() const { return !!(mEdgeState & eIN_DIRTY_LIST); }
PX_FORCE_INLINE EdgeType getEdgeType() const { return mEdgeType; }
//PX_FORCE_INLINE const NodeIndex getIndex1() const { return mNode1; }
//PX_FORCE_INLINE const NodeIndex getIndex2() const { return mNode2; }
PX_FORCE_INLINE bool isReportOnlyDestroy() { return !!(mEdgeState & eREPORT_ONLY_DESTROY); }
};
struct EdgeInstance
{
EdgeInstanceIndex mNextEdge, mPrevEdge; //The next edge instance in this node's list of edge instances
EdgeInstance() : mNextEdge(IG_INVALID_EDGE), mPrevEdge(IG_INVALID_EDGE)
{
}
};
template<typename Handle>
class HandleManager
{
Ps::Array<Handle> mFreeHandles;
Handle mCurrentHandle;
public:
HandleManager() : mFreeHandles(PX_DEBUG_EXP("FreeHandles")), mCurrentHandle(0)
{
}
~HandleManager(){}
Handle getHandle()
{
if(mFreeHandles.size())
{
Handle handle = mFreeHandles.popBack();
PX_ASSERT(isValidHandle(handle));
return handle;
}
return mCurrentHandle++;
}
bool isNotFreeHandle(Handle handle)
{
for(PxU32 a = 0; a < mFreeHandles.size(); ++a)
{
if(mFreeHandles[a] == handle)
return false;
}
return true;
}
void freeHandle(Handle handle)
{
PX_ASSERT(isValidHandle(handle));
PX_ASSERT(isNotFreeHandle(handle));
if(handle == mCurrentHandle)
mCurrentHandle--;
else
mFreeHandles.pushBack(handle);
}
bool isValidHandle(Handle handle)
{
return handle < mCurrentHandle;
}
PX_FORCE_INLINE PxU32 getTotalHandles() const { return mCurrentHandle; }
};
class Node
{
public:
enum NodeType
{
eRIGID_BODY_TYPE,
eARTICULATION_TYPE,
eTYPE_COUNT
};
enum State
{
eREADY_FOR_SLEEPING = 1u << 0, //! Ready to go to sleep
eACTIVE = 1u << 1, //! Active
eKINEMATIC = 1u << 2, //! Kinematic
eDELETED = 1u << 3, //! Is pending deletion
eDIRTY = 1u << 4, //! Is dirty (i.e. lost a connection)
eACTIVATING = 1u << 5, //! Is in the activating list
eDEACTIVATING = 1u << 6 //! It is being forced to deactivate this frame
};
EdgeInstanceIndex mFirstEdgeIndex;
PxU8 mFlags;
PxU8 mType;
PxU16 mStaticTouchCount;
//PxU32 mActiveNodeIndex; //! Look-up for this node in the active nodes list, activating list or deactivating list...
NodeIndex mNextNode, mPrevNode;
//A counter for the number of active references to this body. Whenever an edge is activated, this is incremented.
//Whenver an edge is deactivated, this is decremented. This is used for kinematic bodies to determine if they need
//to be in the active kinematics list
PxU32 mActiveRefCount;
//A node can correspond with either a rigid body or an articulation or softBody
union
{
PxsRigidBody* mRigidBody;
Dy::ArticulationV* mLLArticulation;
};
PX_FORCE_INLINE Node() : mFirstEdgeIndex(IG_INVALID_EDGE), mFlags(eDELETED), mType(eRIGID_BODY_TYPE),
mStaticTouchCount(0), mActiveRefCount(0), mRigidBody(NULL)
{
}
PX_FORCE_INLINE ~Node() {}
PX_FORCE_INLINE void reset()
{
mFirstEdgeIndex = IG_INVALID_EDGE;
mFlags = eDELETED;
mRigidBody = NULL;
mActiveRefCount = 0;
mStaticTouchCount = 0;
}
PX_FORCE_INLINE void setRigidBody(PxsRigidBody* body) { mRigidBody = body; }
PX_FORCE_INLINE PxsRigidBody* getRigidBody() const { return mRigidBody; }
PX_FORCE_INLINE Dy::ArticulationV* getArticulation() const { return mLLArticulation; }
PX_FORCE_INLINE void setActive() { mFlags |= eACTIVE; }
PX_FORCE_INLINE void clearActive() { mFlags &= ~eACTIVE; }
PX_FORCE_INLINE void setActivating() { mFlags |= eACTIVATING; }
PX_FORCE_INLINE void clearActivating() { mFlags &= ~eACTIVATING; }
PX_FORCE_INLINE void setDeactivating() { mFlags |= eDEACTIVATING; }
PX_FORCE_INLINE void clearDeactivating() { mFlags &= (~eDEACTIVATING); }
//Activates a body/node.
PX_FORCE_INLINE void setIsReadyForSleeping() { mFlags |= eREADY_FOR_SLEEPING; }
PX_FORCE_INLINE void clearIsReadyForSleeping(){ mFlags &= (~eREADY_FOR_SLEEPING);}
PX_FORCE_INLINE void setIsDeleted(){mFlags |= eDELETED; }
PX_FORCE_INLINE void setKinematicFlag() {PX_ASSERT(!isKinematic()); mFlags |= eKINEMATIC;}
PX_FORCE_INLINE void clearKinematicFlag(){ PX_ASSERT(isKinematic()); mFlags &= (~eKINEMATIC);}
PX_FORCE_INLINE void markDirty(){mFlags |= eDIRTY;}
PX_FORCE_INLINE void clearDirty(){mFlags &= (~eDIRTY);}
public:
PX_FORCE_INLINE bool isActive() const { return !!(mFlags & eACTIVE); }
PX_FORCE_INLINE bool isActiveOrActivating() const { return !!(mFlags & (eACTIVE | eACTIVATING)); }
PX_FORCE_INLINE bool isActivating() const { return !!(mFlags & eACTIVATING); }
PX_FORCE_INLINE bool isDeactivating() const { return !!(mFlags & eDEACTIVATING); }
PX_FORCE_INLINE bool isKinematic() const { return !!(mFlags & eKINEMATIC); }
PX_FORCE_INLINE bool isDeleted() const { return !!(mFlags & eDELETED); }
PX_FORCE_INLINE bool isDirty() const { return !!(mFlags & eDIRTY); }
PX_FORCE_INLINE bool isReadyForSleeping() const { return !!(mFlags & eREADY_FOR_SLEEPING); }
PX_FORCE_INLINE NodeType getNodeType() const { return NodeType(mType); }
friend class SimpleIslandManager;
};
struct Island
{
NodeIndex mRootNode;
NodeIndex mLastNode;
PxU32 mSize[Node::eTYPE_COUNT];
PxU32 mActiveIndex;
EdgeIndex mFirstEdge[Edge::eEDGE_TYPE_COUNT], mLastEdge[Edge::eEDGE_TYPE_COUNT];
PxU32 mEdgeCount[Edge::eEDGE_TYPE_COUNT];
Island() : mActiveIndex(IG_INVALID_ISLAND)
{
for(PxU32 a = 0; a < Edge::eEDGE_TYPE_COUNT; ++a)
{
mFirstEdge[a] = IG_INVALID_EDGE;
mLastEdge[a] = IG_INVALID_EDGE;
mEdgeCount[a] = 0;
}
for(PxU32 a = 0; a < Node::eTYPE_COUNT; ++a)
{
mSize[a] = 0;
}
}
};
struct TraversalState
{
NodeIndex mNodeIndex;
PxU32 mCurrentIndex;
PxU32 mPrevIndex;
PxU32 mDepth;
TraversalState()
{
}
TraversalState(NodeIndex nodeIndex, PxU32 currentIndex, PxU32 prevIndex, PxU32 depth) :
mNodeIndex(nodeIndex), mCurrentIndex(currentIndex), mPrevIndex(prevIndex), mDepth(depth)
{
}
};
struct QueueElement
{
TraversalState* mState;
PxU32 mHopCount;
QueueElement()
{
}
QueueElement(TraversalState* state, PxU32 hopCount) : mState(state), mHopCount(hopCount)
{
}
};
struct NodeComparator
{
NodeComparator()
{
}
bool operator() (const QueueElement& node0, const QueueElement& node1) const
{
return node0.mHopCount < node1.mHopCount;
}
private:
NodeComparator& operator = (const NodeComparator&);
};
class IslandSim
{
HandleManager<IslandId> mIslandHandles; //! Handle manager for islands
Ps::Array<Node> mNodes; //! The nodes used in the constraint graph
Ps::Array<PxU32> mActiveNodeIndex; //! The active node index for each node
Cm::BlockArray<Edge> mEdges;
Cm::BlockArray<EdgeInstance> mEdgeInstances; //! Edges used to connect nodes in the constraint graph
Ps::Array<Island> mIslands; //! The array of islands
Ps::Array<PxU32> mIslandStaticTouchCount; //! Array of static touch counts per-island
Ps::Array<NodeIndex> mActiveNodes[Node::eTYPE_COUNT]; //! An array of active nodes
Ps::Array<NodeIndex> mActiveKinematicNodes; //! An array of active or referenced kinematic nodes
Ps::Array<EdgeIndex> mActivatedEdges[Edge::eEDGE_TYPE_COUNT]; //! An array of active edges
PxU32 mActiveEdgeCount[Edge::eEDGE_TYPE_COUNT];
Ps::Array<PxU32> mHopCounts; //! The observed number of "hops" from a given node to its root node. May be inaccurate but used to accelerate searches.
Ps::Array<NodeIndex> mFastRoute; //! The observed last route from a given node to the root node. We try the fast route (unless its broken) before trying others.
Ps::Array<IslandId> mIslandIds; //! The array of per-node island ids
Cm::BitMap mIslandAwake; //! Indicates whether an island is awake or not
Cm::BitMap mActiveContactEdges;
//An array of active islands
Ps::Array<IslandId> mActiveIslands;
PxU32 mInitialActiveNodeCount[Edge::eEDGE_TYPE_COUNT];
Ps::Array<NodeIndex> mNodesToPutToSleep[Node::eTYPE_COUNT];
//Input to this frame's island management (changed nodes/edges)
//Input list of changes observed this frame. If there no changes, no work to be done.
Ps::Array<EdgeIndex> mDirtyEdges[Edge::eEDGE_TYPE_COUNT];
//Dirty nodes. These nodes lost at least one connection so we need to recompute islands from these nodes
//Ps::Array<NodeIndex> mDirtyNodes;
Cm::BitMap mDirtyMap;
PxU32 mLastMapIndex;
//An array of nodes to activate
Ps::Array<NodeIndex> mActivatingNodes;
Ps::Array<EdgeIndex> mDestroyedEdges;
Ps::Array<IslandId> mTempIslandIds;
//Temporary, transient data used for traversals. TODO - move to PxsSimpleIslandManager. Or if we keep it here, we can
//process multiple island simulations in parallel
Cm::PriorityQueue<QueueElement, NodeComparator>
mPriorityQueue; //! Priority queue used for graph traversal
Ps::Array<TraversalState> mVisitedNodes; //! The list of nodes visited in the current traversal
Cm::BitMap mVisitedState; //! Indicates whether a node has been visited
Ps::Array<EdgeIndex> mIslandSplitEdges[Edge::eEDGE_TYPE_COUNT];
Ps::Array<EdgeIndex> mDeactivatingEdges[Edge::eEDGE_TYPE_COUNT];
Ps::Array<PartitionEdge*>* mFirstPartitionEdges;
Cm::BlockArray<NodeIndex>& mEdgeNodeIndices;
Ps::Array<physx::PartitionEdge*>* mDestroyedPartitionEdges;
PxU32* mNpIndexPtr;
PxU64 mContextId;
public:
IslandSim(Ps::Array<PartitionEdge*>* firstPartitionEdges, Cm::BlockArray<NodeIndex>& edgeNodeIndices, Ps::Array<PartitionEdge*>* destroyedPartitionEdges, PxU64 contextID);
~IslandSim() {}
void resize(const PxU32 nbNodes, const PxU32 nbContactManagers, const PxU32 nbConstraints);
void addRigidBody(PxsRigidBody* body, bool isKinematic, bool isActive, NodeIndex nodeIndex);
void addArticulation(Sc::ArticulationSim* articulation, Dy::ArticulationV* llArtic, bool isActive, NodeIndex nodeIndex);
void addContactManager(PxsContactManager* manager, NodeIndex nodeHandle1, NodeIndex nodeHandle2, EdgeIndex handle);
void addConstraint(Dy::Constraint* constraint, NodeIndex nodeHandle1, NodeIndex nodeHandle2, EdgeIndex handle);
void activateNode(NodeIndex index);
void deactivateNode(NodeIndex index);
void putNodeToSleep(NodeIndex index);
void removeConnection(EdgeIndex edgeIndex);
PX_FORCE_INLINE PxU32 getNbNodes() const { return mNodes.size(); }
PX_FORCE_INLINE PxU32 getNbActiveNodes(Node::NodeType type) const { return mActiveNodes[type].size(); }
PX_FORCE_INLINE const NodeIndex* getActiveNodes(Node::NodeType type) const { return mActiveNodes[type].begin(); }
PX_FORCE_INLINE PxU32 getNbActiveKinematics() const { return mActiveKinematicNodes.size(); }
PX_FORCE_INLINE const NodeIndex* getActiveKinematics() const { return mActiveKinematicNodes.begin(); }
PX_FORCE_INLINE PxU32 getNbNodesToActivate(Node::NodeType type) const { return mActiveNodes[type].size() - mInitialActiveNodeCount[type]; }
PX_FORCE_INLINE const NodeIndex* getNodesToActivate(Node::NodeType type) const { return mActiveNodes[type].begin() + mInitialActiveNodeCount[type]; }
PX_FORCE_INLINE PxU32 getNbNodesToDeactivate(Node::NodeType type) const { return mNodesToPutToSleep[type].size(); }
PX_FORCE_INLINE const NodeIndex* getNodesToDeactivate(Node::NodeType type) const { return mNodesToPutToSleep[type].begin(); }
PX_FORCE_INLINE PxU32 getNbActivatedEdges(Edge::EdgeType type) const { return mActivatedEdges[type].size(); }
PX_FORCE_INLINE const EdgeIndex* getActivatedEdges(Edge::EdgeType type) const { return mActivatedEdges[type].begin(); }
PX_FORCE_INLINE PxU32 getNbActiveEdges(Edge::EdgeType type) const { return mActiveEdgeCount[type]; }
PX_FORCE_INLINE PartitionEdge* getFirstPartitionEdge(IG::EdgeIndex edgeIndex) const { return (*mFirstPartitionEdges)[edgeIndex]; }
PX_FORCE_INLINE void setFirstPartitionEdge(IG::EdgeIndex edgeIndex, PartitionEdge* partitionEdge) { (*mFirstPartitionEdges)[edgeIndex] = partitionEdge; }
//PX_FORCE_INLINE const EdgeIndex* getActiveEdges(Edge::EdgeType type) const { return mActiveEdges[type].begin(); }
PX_FORCE_INLINE PxsRigidBody* getRigidBody(NodeIndex nodeIndex) const
{
const Node& node = mNodes[nodeIndex.index()];
PX_ASSERT(node.mType == Node::eRIGID_BODY_TYPE);
return node.mRigidBody;
}
PX_FORCE_INLINE Dy::ArticulationV* getLLArticulation(NodeIndex nodeIndex) const
{
const Node& node = mNodes[nodeIndex.index()];
PX_ASSERT(node.mType == Node::eARTICULATION_TYPE);
return node.mLLArticulation;
}
PX_FORCE_INLINE void clearDeactivations()
{
mNodesToPutToSleep[0].forceSize_Unsafe(0);
mNodesToPutToSleep[1].forceSize_Unsafe(0);
mDeactivatingEdges[0].forceSize_Unsafe(0);
mDeactivatingEdges[1].forceSize_Unsafe(0);
}
PX_FORCE_INLINE const Island& getIsland(IG::IslandId islandIndex) const { return mIslands[islandIndex]; }
PX_FORCE_INLINE PxU32 getNbActiveIslands() const { return mActiveIslands.size(); }
PX_FORCE_INLINE const IslandId* getActiveIslands() const { return mActiveIslands.begin(); }
PX_FORCE_INLINE PxU32 getNbDeactivatingEdges(const IG::Edge::EdgeType edgeType) const { return mDeactivatingEdges[edgeType].size(); }
PX_FORCE_INLINE const EdgeIndex* getDeactivatingEdges(const IG::Edge::EdgeType edgeType) const { return mDeactivatingEdges[edgeType].begin(); }
PX_FORCE_INLINE PxU32 getNbDestroyedEdges() const { return mDestroyedEdges.size(); }
PX_FORCE_INLINE const EdgeIndex* getDestroyedEdges() const { return mDestroyedEdges.begin(); }
PX_FORCE_INLINE PxU32 getNbDestroyedPartitionEdges() const { return mDestroyedPartitionEdges->size(); }
PX_FORCE_INLINE const PartitionEdge*const * getDestroyedPartitionEdges() const { return mDestroyedPartitionEdges->begin(); }
PX_FORCE_INLINE PartitionEdge** getDestroyedPartitionEdges() { return mDestroyedPartitionEdges->begin(); }
PX_FORCE_INLINE PxU32 getNbDirtyEdges(IG::Edge::EdgeType type) const { return mDirtyEdges[type].size(); }
PX_FORCE_INLINE const EdgeIndex* getDirtyEdges(IG::Edge::EdgeType type) const { return mDirtyEdges[type].begin(); }
PX_FORCE_INLINE const Edge& getEdge(const EdgeIndex edgeIndex) const { return mEdges[edgeIndex]; }
PX_FORCE_INLINE Edge& getEdge(const EdgeIndex edgeIndex) { return mEdges[edgeIndex]; }
PX_FORCE_INLINE const Node& getNode(const NodeIndex& nodeIndex) const { return mNodes[nodeIndex.index()]; }
PX_FORCE_INLINE const Island& getIsland(const NodeIndex& nodeIndex) const { PX_ASSERT(mIslandIds[nodeIndex.index()] != IG_INVALID_ISLAND); return mIslands[mIslandIds[nodeIndex.index()]]; }
PX_FORCE_INLINE PxU32 getIslandStaticTouchCount(const NodeIndex& nodeIndex) const { PX_ASSERT(mIslandIds[nodeIndex.index()] != IG_INVALID_ISLAND); return mIslandStaticTouchCount[mIslandIds[nodeIndex.index()]]; }
PX_FORCE_INLINE const Cm::BitMap& getActiveContactManagerBitmap() const { return mActiveContactEdges; }
PX_FORCE_INLINE PxU32 getActiveNodeIndex(const NodeIndex& nodeIndex) const { PxU32 activeNodeIndex = mActiveNodeIndex[nodeIndex.index()]; return activeNodeIndex;}
PX_FORCE_INLINE const PxU32* getActiveNodeIndex() const { return mActiveNodeIndex.begin(); }
PX_FORCE_INLINE PxU32 getNbActiveNodeIndex() const { return mActiveNodeIndex.size(); }
void setKinematic(IG::NodeIndex nodeIndex);
void setDynamic(IG::NodeIndex nodeIndex);
PX_FORCE_INLINE void setEdgeNodeIndexPtr(PxU32* ptr) { mNpIndexPtr = ptr; }
PX_FORCE_INLINE NodeIndex getNodeIndex1(IG::EdgeIndex index) const { return mEdgeNodeIndices[2 * index]; }
PX_FORCE_INLINE NodeIndex getNodeIndex2(IG::EdgeIndex index) const { return mEdgeNodeIndices[2 * index + 1]; }
PX_FORCE_INLINE PxU32* getEdgeNodeIndexPtr() const { return mNpIndexPtr; }
PX_FORCE_INLINE PxU64 getContextId() const { return mContextId; }
PxU32 getNbIslands() const { return mIslandStaticTouchCount.size(); }
const PxU32* getIslandStaticTouchCount() const { return mIslandStaticTouchCount.begin(); }
const PxU32* getIslandIds() const { return mIslandIds.begin(); }
bool checkInternalConsistency();
private:
void insertNewEdges();
void removeDestroyedEdges();
void wakeIslands();
void wakeIslands2();
void processNewEdges();
void processLostEdges(Ps::Array<NodeIndex>& destroyedNodes, bool allowDeactivation, bool permitKinematicDeactivation, PxU32 dirtyNodeLimit);
void removeConnectionInternal(EdgeIndex edgeIndex);
void addConnection(NodeIndex nodeHandle1, NodeIndex nodeHandle2, Edge::EdgeType edgeType, EdgeIndex handle);
void addConnectionToGraph(EdgeIndex index);
void removeConnectionFromGraph(EdgeIndex edgeIndex);
void connectEdge(EdgeInstance& instance, EdgeInstanceIndex edgeIndex, Node& source, NodeIndex destination);
void disconnectEdge(EdgeInstance& instance, EdgeInstanceIndex edgeIndex, Node& node);
//Merges 2 islands together. The returned id is the id of the merged island
IslandId mergeIslands(IslandId island0, IslandId island1, NodeIndex node0, NodeIndex node1);
void mergeIslandsInternal(Island& island0, Island& island1, IslandId islandId0, IslandId islandId1, NodeIndex node0, NodeIndex node1);
IslandSim& operator = (const IslandSim&);
IslandSim(const IslandSim&);
void unwindRoute(PxU32 traversalIndex, NodeIndex lastNode, PxU32 hopCount, IslandId id);
void activateIsland(IslandId island);
void deactivateIsland(IslandId island);
bool canFindRoot(NodeIndex startNode, NodeIndex targetNode, Ps::Array<NodeIndex>* visitedNodes);
bool tryFastPath(NodeIndex startNode, NodeIndex targetNode, IslandId islandId);
bool findRoute(NodeIndex startNode, NodeIndex targetNode, IslandId islandId);
bool isPathTo(NodeIndex startNode, NodeIndex targetNode);
void addNode(bool isActive, bool isKinematic, Node::NodeType type, NodeIndex nodeIndex);
void activateNodeInternal(NodeIndex index);
void deactivateNodeInternal(NodeIndex index);
PX_FORCE_INLINE void notifyReadyForSleeping(const NodeIndex nodeIndex)
{
Node& node = mNodes[nodeIndex.index()];
//PX_ASSERT(node.isActive());
node.setIsReadyForSleeping();
}
PX_FORCE_INLINE void notifyNotReadyForSleeping(const NodeIndex nodeIndex)
{
Node& node = mNodes[nodeIndex.index()];
PX_ASSERT(node.isActive() || node.isActivating());
node.clearIsReadyForSleeping();
}
PX_FORCE_INLINE void markIslandActive(IslandId islandId)
{
Island& island = mIslands[islandId];
PX_ASSERT(!mIslandAwake.test(islandId));
PX_ASSERT(island.mActiveIndex == IG_INVALID_ISLAND);
mIslandAwake.set(islandId);
island.mActiveIndex = mActiveIslands.size();
mActiveIslands.pushBack(islandId);
}
PX_FORCE_INLINE void markIslandInactive(IslandId islandId)
{
Island& island = mIslands[islandId];
PX_ASSERT(mIslandAwake.test(islandId));
PX_ASSERT(island.mActiveIndex != IG_INVALID_ISLAND);
PX_ASSERT(mActiveIslands[island.mActiveIndex] == islandId);
IslandId replaceId = mActiveIslands[mActiveIslands.size()-1];
PX_ASSERT(mIslandAwake.test(replaceId));
Island& replaceIsland = mIslands[replaceId];
replaceIsland.mActiveIndex = island.mActiveIndex;
mActiveIslands[island.mActiveIndex] = replaceId;
mActiveIslands.forceSize_Unsafe(mActiveIslands.size()-1);
island.mActiveIndex = IG_INVALID_ISLAND;
mIslandAwake.reset(islandId);
}
PX_FORCE_INLINE void markKinematicActive(NodeIndex index)
{
Node& node = mNodes[index.index()];
PX_ASSERT(node.isKinematic());
if(node.mActiveRefCount == 0 && mActiveNodeIndex[index.index()] == IG_INVALID_NODE)
{
//PX_ASSERT(mActiveNodeIndex[index.index()] == IG_INVALID_NODE);
//node.mActiveNodeIndex = mActiveKinematicNodes.size();
mActiveNodeIndex[index.index()] = mActiveKinematicNodes.size();
mActiveKinematicNodes.pushBack(index);
}
}
PX_FORCE_INLINE void markKinematicInactive(NodeIndex index)
{
Node& node = mNodes[index.index()];
PX_ASSERT(node.isKinematic());
PX_ASSERT(mActiveNodeIndex[index.index()] != IG_INVALID_NODE);
PX_ASSERT(mActiveKinematicNodes[mActiveNodeIndex[index.index()]].index() == index.index());
if(node.mActiveRefCount == 0)
{
//Only remove from active kinematic list if it has no active contacts referencing it *and* it is asleep
if(mActiveNodeIndex[index.index()] != IG_INVALID_NODE)
{
//Need to verify active node index because there is an edge case where a node could be woken, then put to
//sleep in the same frame. This would mean that it would not have an active index at this stage.
NodeIndex replaceIndex = mActiveKinematicNodes.back();
PX_ASSERT(mActiveNodeIndex[replaceIndex.index()] == mActiveKinematicNodes.size()-1);
mActiveNodeIndex[replaceIndex.index()] = mActiveNodeIndex[index.index()];
mActiveKinematicNodes[mActiveNodeIndex[index.index()]] = replaceIndex;
mActiveKinematicNodes.forceSize_Unsafe(mActiveKinematicNodes.size()-1);
mActiveNodeIndex[index.index()] = IG_INVALID_NODE;
}
}
}
PX_FORCE_INLINE void markActive(NodeIndex index)
{
Node& node = mNodes[index.index()];
PX_ASSERT(!node.isKinematic());
PX_ASSERT(mActiveNodeIndex[index.index()] == IG_INVALID_NODE);
mActiveNodeIndex[index.index()] = mActiveNodes[node.mType].size();
mActiveNodes[node.mType].pushBack(index);
}
PX_FORCE_INLINE void markInactive(NodeIndex index)
{
Node& node = mNodes[index.index()];
PX_ASSERT(!node.isKinematic());
PX_ASSERT(mActiveNodeIndex[index.index()] != IG_INVALID_NODE);
Ps::Array<NodeIndex>& activeNodes = mActiveNodes[node.mType];
PX_ASSERT(activeNodes[mActiveNodeIndex[index.index()]].index() == index.index());
const PxU32 initialActiveNodeCount = mInitialActiveNodeCount[node.mType];
if(mActiveNodeIndex[index.index()] < initialActiveNodeCount)
{
//It's in the initial active node set. We retain a list of active nodes, where the existing active nodes
//are at the beginning of the array and the newly activated nodes are at the end of the array...
//The solution is to move the node to the end of the initial active node list in this case
PxU32 activeNodeIndex = mActiveNodeIndex[index.index()];
NodeIndex replaceIndex = activeNodes[initialActiveNodeCount-1];
PX_ASSERT(mActiveNodeIndex[replaceIndex.index()] == initialActiveNodeCount-1);
mActiveNodeIndex[index.index()] = mActiveNodeIndex[replaceIndex.index()];
mActiveNodeIndex[replaceIndex.index()] = activeNodeIndex;
activeNodes[activeNodeIndex] = replaceIndex;
activeNodes[mActiveNodeIndex[index.index()]] = index;
mInitialActiveNodeCount[node.mType]--;
}
PX_ASSERT(!node.isKinematic());
PX_ASSERT(mActiveNodeIndex[index.index()] != IG_INVALID_NODE);
PX_ASSERT(activeNodes[mActiveNodeIndex[index.index()]].index() == index.index());
NodeIndex replaceIndex = activeNodes.back();
PX_ASSERT(mActiveNodeIndex[replaceIndex.index()] == activeNodes.size()-1);
mActiveNodeIndex[replaceIndex.index()] = mActiveNodeIndex[index.index()];
activeNodes[mActiveNodeIndex[index.index()]] = replaceIndex;
activeNodes.forceSize_Unsafe(activeNodes.size()-1);
mActiveNodeIndex[index.index()] = IG_INVALID_NODE;
}
PX_FORCE_INLINE void markEdgeActive(EdgeIndex index)
{
Edge& edge = mEdges[index];
PX_ASSERT((edge.mEdgeState & Edge::eACTIVATING) == 0);
edge.mEdgeState |= Edge::eACTIVATING;
mActivatedEdges[edge.mEdgeType].pushBack(index);
mActiveEdgeCount[edge.mEdgeType]++;
//Set the active bit...
if(edge.mEdgeType == Edge::eCONTACT_MANAGER)
mActiveContactEdges.set(index);
NodeIndex nodeIndex1 = mEdgeNodeIndices[2 * index];
NodeIndex nodeIndex2 = mEdgeNodeIndices[2 * index + 1];
if (nodeIndex1.index() != IG_INVALID_NODE && nodeIndex2.index() != IG_INVALID_NODE)
{
PX_ASSERT((!mNodes[nodeIndex1.index()].isKinematic()) || (!mNodes[nodeIndex2.index()].isKinematic()) || edge.getEdgeType() == IG::Edge::eCONTACT_MANAGER);
{
Node& node = mNodes[nodeIndex1.index()];
if(node.mActiveRefCount == 0 && node.isKinematic() && !(node.isActive() || node.isActivating()))
{
//Add to active kinematic list
markKinematicActive(nodeIndex1);
}
node.mActiveRefCount++;
}
{
Node& node = mNodes[nodeIndex2.index()];
if(node.mActiveRefCount == 0 && node.isKinematic() && !(node.isActive() || node.isActivating()))
{
//Add to active kinematic list
markKinematicActive(nodeIndex2);
}
node.mActiveRefCount++;
}
}
}
void removeEdgeFromActivatingList(EdgeIndex index);
PX_FORCE_INLINE void removeEdgeFromIsland(Island& island, EdgeIndex edgeIndex)
{
Edge& edge = mEdges[edgeIndex];
if(edge.mNextIslandEdge != IG_INVALID_EDGE)
{
PX_ASSERT(mEdges[edge.mNextIslandEdge].mPrevIslandEdge == edgeIndex);
mEdges[edge.mNextIslandEdge].mPrevIslandEdge = edge.mPrevIslandEdge;
}
else
{
PX_ASSERT(island.mLastEdge[edge.mEdgeType] == edgeIndex);
island.mLastEdge[edge.mEdgeType] = edge.mPrevIslandEdge;
}
if(edge.mPrevIslandEdge != IG_INVALID_EDGE)
{
PX_ASSERT(mEdges[edge.mPrevIslandEdge].mNextIslandEdge == edgeIndex);
mEdges[edge.mPrevIslandEdge].mNextIslandEdge = edge.mNextIslandEdge;
}
else
{
PX_ASSERT(island.mFirstEdge[edge.mEdgeType] == edgeIndex);
island.mFirstEdge[edge.mEdgeType] = edge.mNextIslandEdge;
}
island.mEdgeCount[edge.mEdgeType]--;
edge.mNextIslandEdge = edge.mPrevIslandEdge = IG_INVALID_EDGE;
}
PX_FORCE_INLINE void addEdgeToIsland(Island& island, EdgeIndex edgeIndex)
{
Edge& edge = mEdges[edgeIndex];
PX_ASSERT(edge.mNextIslandEdge == IG_INVALID_EDGE && edge.mPrevIslandEdge == IG_INVALID_EDGE);
if(island.mLastEdge[edge.mEdgeType] != IG_INVALID_EDGE)
{
PX_ASSERT(mEdges[island.mLastEdge[edge.mEdgeType]].mNextIslandEdge == IG_INVALID_EDGE);
mEdges[island.mLastEdge[edge.mEdgeType]].mNextIslandEdge = edgeIndex;
}
else
{
PX_ASSERT(island.mFirstEdge[edge.mEdgeType] == IG_INVALID_EDGE);
island.mFirstEdge[edge.mEdgeType] = edgeIndex;
}
edge.mPrevIslandEdge = island.mLastEdge[edge.mEdgeType];
island.mLastEdge[edge.mEdgeType] = edgeIndex;
island.mEdgeCount[edge.mEdgeType]++;
}
PX_FORCE_INLINE void removeNodeFromIsland(Island& island, NodeIndex nodeIndex)
{
Node& node = mNodes[nodeIndex.index()];
if(node.mNextNode.isValid())
{
PX_ASSERT(mNodes[node.mNextNode.index()].mPrevNode.index() == nodeIndex.index());
mNodes[node.mNextNode.index()].mPrevNode = node.mPrevNode;
}
else
{
PX_ASSERT(island.mLastNode.index() == nodeIndex.index());
island.mLastNode = node.mPrevNode;
}
if(node.mPrevNode.isValid())
{
PX_ASSERT(mNodes[node.mPrevNode.index()].mNextNode.index() == nodeIndex.index());
mNodes[node.mPrevNode.index()].mNextNode = node.mNextNode;
}
else
{
PX_ASSERT(island.mRootNode.index() == nodeIndex.index());
island.mRootNode = node.mNextNode;
}
island.mSize[node.mType]--;
node.mNextNode = NodeIndex(); node.mPrevNode = NodeIndex();
}
//void setEdgeConnectedInternal(EdgeIndex edgeIndex);
//void setEdgeDisconnectedInternal(EdgeIndex edgeIndex);
friend class SimpleIslandManager;
friend class ThirdPassTask;
};
}
struct PartitionIndexData
{
PxU16 mPartitionIndex; //! The current partition this edge is in. Used to find the edge efficiently. PxU8 is probably too small (256 partitions max) but PxU16 should be more than enough
PxU8 mPatchIndex; //! The patch index for this partition edge. There may be multiple entries for a given edge if there are multiple patches.
PxU8 mCType; //! The type of constraint this is
PxU32 mPartitionEntryIndex; //! index of partition edges for this partition
};
struct PartitionNodeData
{
IG::NodeIndex mNodeIndex0;
IG::NodeIndex mNodeIndex1;
PxU32 mNextIndex0;
PxU32 mNextIndex1;
};
#define INVALID_PARTITION_INDEX 0xFFFF
struct PartitionEdge
{
IG::EdgeIndex mEdgeIndex; //! The edge index into the island manager. Used to identify the contact manager/constraint
IG::NodeIndex mNode0; //! The node index for node 0. Can be obtained from the edge index alternatively
IG::NodeIndex mNode1; //! The node idnex for node 1. Can be obtained from the edge index alternatively
bool mInfiniteMass0; //! Whether body 0 is kinematic
bool mArticulation0; //! Whether body 0 is an articulation link
bool mInfiniteMass1; //! Whether body 1 is kinematic
bool mArticulation1; //! Whether body 1 is an articulation link
PartitionEdge* mNextPatch; //! for the contact manager has more than 1 patch, we have next patch's edge and previous patch's edge to connect to this edge
PxU32 mUniqueIndex; //! a unique ID for this edge
//KS - This constructor explicitly does not set mUniqueIndex. It is filled in by the pool allocator and this constructor
//is called afterwards. We do not want to stomp the uniqueIndex value
PartitionEdge() : mEdgeIndex(IG_INVALID_EDGE), mInfiniteMass0(false), mArticulation0(false),
mInfiniteMass1(false), mArticulation1(false), mNextPatch(NULL)//, mUniqueIndex(IG_INVALID_EDGE)
{
}
};
}
#endif

View File

@ -0,0 +1,48 @@
//
// 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 PXS_KERNEL_WRANGLER_H
#define PXS_KERNEL_WRANGLER_H
#include "foundation/PxSimpleTypes.h"
namespace physx
{
class KernelWrangler;
class PxErrorCallback;
class PxsKernelWranglerManager
{
public:
virtual ~PxsKernelWranglerManager(){}
virtual KernelWrangler* getKernelWrangler() = 0;
};
}
#endif

View File

@ -0,0 +1,143 @@
//
// 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 PXS_MATERIALCOMBINER_H
#define PXS_MATERIALCOMBINER_H
#include "PxsMaterialCore.h"
namespace physx
{
class PxsMaterialCombiner
{
public:
class PxsCombinedMaterial
{
public:
PxReal staFriction;
PxReal dynFriction;
PxU32 flags; //PxMaterialFlag::eDISABLE_FRICTION, PxMaterialFlag::eDISABLE_STRONG_FRICTION.
};
static PxReal combineRestitution(const PxsMaterialData& material0, const PxsMaterialData& material1);
PxsMaterialCombiner(PxReal staticFrictionScaling, PxReal dynamicFrictionScaling);
PxsCombinedMaterial combineIsotropicFriction(const PxsMaterialData& material0, const PxsMaterialData& material1);
//ML:: move this function to header file to avoid LHS in Xbox
PX_FORCE_INLINE void combineIsotropicFriction(const PxsMaterialData& mat0, const PxsMaterialData& mat1, PxReal& dynamicFriction, PxReal& staticFriction, PxU32& flags)
{
const PxU32 combineFlags= (mat0.flags | mat1.flags); //& (PxMaterialFlag::eDISABLE_STRONG_FRICTION|PxMaterialFlag::eDISABLE_FRICTION); //eventually set DisStrongFric flag, lower all others.
if (!(combineFlags & PxMaterialFlag::eDISABLE_FRICTION))
{
const PxI32 fictionCombineMode = PxMax(mat0.getFrictionCombineMode(), mat1.getFrictionCombineMode());
PxReal dynFriction = 0.f;
PxReal staFriction = 0.f;
switch (fictionCombineMode)
{
case PxCombineMode::eAVERAGE:
dynFriction = 0.5f * (mat0.dynamicFriction + mat1.dynamicFriction);
staFriction = 0.5f * (mat0.staticFriction + mat1.staticFriction);
break;
case PxCombineMode::eMIN:
dynFriction = PxMin(mat0.dynamicFriction, mat1.dynamicFriction);
staFriction = PxMin(mat0.staticFriction, mat1.staticFriction);
break;
case PxCombineMode::eMULTIPLY:
dynFriction = (mat0.dynamicFriction * mat1.dynamicFriction);
staFriction = (mat0.staticFriction * mat1.staticFriction);
break;
case PxCombineMode::eMAX:
dynFriction = PxMax(mat0.dynamicFriction, mat1.dynamicFriction);
staFriction = PxMax(mat0.staticFriction, mat1.staticFriction);
break;
}
dynFriction*=mDynamicFrictionScaling;
staFriction*=mStaticFrictionScaling;
//isotropic case
const PxReal fDynFriction = PxMax(dynFriction, 0.f);
const PxReal fStaFriction = physx::intrinsics::fsel(staFriction - fDynFriction, staFriction*mStaticFrictionScaling, fDynFriction);
/*dest.dynFriction = fDynFriction;
dest.staFriction = fStaFriction;*/
dynamicFriction = fDynFriction;
staticFriction = fStaFriction;
flags = combineFlags;
}
else
{
/* dest.flags |= PxMaterialFlag::eDISABLE_STRONG_FRICTION;
dest.staFriction = 0.0f;
dest.dynFriction = 0.0f;*/
flags = (combineFlags | PxMaterialFlag::eDISABLE_STRONG_FRICTION);
dynamicFriction = 0.f;
staticFriction = 0.f;
}
}
//private:
protected:
static PX_FORCE_INLINE PxReal combineScalars(PxReal a, PxReal b, PxI32 nxCombineMode)
{
switch (nxCombineMode)
{
case PxCombineMode::eAVERAGE:
return 0.5f * (a + b);
case PxCombineMode::eMIN:
return PxMin(a,b);
case PxCombineMode::eMULTIPLY:
return a * b;
case PxCombineMode::eMAX:
return PxMax(a,b);
default:
/* Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
"Sc::MaterialCombiner::combineScalars(): unknown combine mode");*/
return PxReal(0);
}
}
PxReal mStaticFrictionScaling, mDynamicFrictionScaling;
};
}
#endif

View File

@ -0,0 +1,59 @@
//
// 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 PXS_MEMORY_MANAGER_H
#define PXS_MEMORY_MANAGER_H
#include "foundation/PxPreprocessor.h"
#include "foundation/PxSimpleTypes.h"
#include "CmPhysXCommon.h"
namespace physx
{
namespace shdfnd
{
class VirtualAllocatorCallback;
}
class PxsMemoryManager
{
public:
virtual ~PxsMemoryManager(){}
virtual Ps::VirtualAllocatorCallback* createHostMemoryAllocator(const PxU32 gpuComputeVersion = 0) = 0;
virtual Ps::VirtualAllocatorCallback* createDeviceMemoryAllocator(const PxU32 gpuComputeVersion = 0) = 0;
virtual void destroyMemoryAllocator() = 0;
};
PxsMemoryManager* createMemoryManager();
}
#endif

View File

@ -0,0 +1,148 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-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 PXS_NPHASE_IMPLEMENTATION_CONTEXT_H
#define PXS_NPHASE_IMPLEMENTATION_CONTEXT_H
#include "PxvNphaseImplementationContext.h"
#include "PxsContactManagerState.h"
#include "PxcNpCache.h"
namespace physx
{
struct PxsContactManagers : PxsContactManagerBase
{
Ps::Array<PxsContactManagerOutput> mOutputContactManagers;
Ps::Array<PxsContactManager*> mContactManagerMapping;
Ps::Array<Gu::Cache> mCaches;
PxsContactManagers(const PxU32 bucketId) : PxsContactManagerBase(bucketId),
mOutputContactManagers(PX_DEBUG_EXP("mOutputContactManagers")),
mContactManagerMapping(PX_DEBUG_EXP("mContactManagerMapping")),
mCaches(PX_DEBUG_EXP("mCaches"))
{
}
void clear()
{
mOutputContactManagers.forceSize_Unsafe(0);
mContactManagerMapping.forceSize_Unsafe(0);
mCaches.forceSize_Unsafe(0);
}
private:
PX_NOCOPY(PxsContactManagers)
};
class PxsNphaseImplementationContext: public PxvNphaseImplementationContextUsableAsFallback
{
public:
static PxsNphaseImplementationContext* create(PxsContext& context, IG::IslandSim* islandSim);
PxsNphaseImplementationContext(PxsContext& context, IG::IslandSim* islandSim, PxU32 index = 0): PxvNphaseImplementationContextUsableAsFallback(context), mNarrowPhasePairs(index), mNewNarrowPhasePairs(index),
mModifyCallback(NULL), mIslandSim(islandSim) {}
virtual void destroy();
virtual void updateContactManager(PxReal dt, bool hasBoundsArrayChanged, bool hasContactDistanceChanged, PxBaseTask* continuation, PxBaseTask* firstPassContinuation);
virtual void postBroadPhaseUpdateContactManager() {}
virtual void secondPassUpdateContactManager(PxReal dt, PxBaseTask* continuation);
virtual void registerContactManager(PxsContactManager* cm, PxI32 touching, PxU32 numPatches);
virtual void registerContactManagers(PxsContactManager** cm, PxU32 nbContactManagers, PxU32 maxContactManagerId);
virtual void unregisterContactManager(PxsContactManager* cm);
virtual void unregisterContactManagerFallback(PxsContactManager* cm, PxsContactManagerOutput* cmOutputs);
virtual void refreshContactManager(PxsContactManager* cm);
virtual void refreshContactManagerFallback(PxsContactManager* cm, PxsContactManagerOutput* cmOutputs);
virtual void registerShape(const PxsShapeCore& shapeCore);
virtual void updateShapeMaterial(const PxsShapeCore& shapeCore);
virtual void updateShapeContactOffset(const PxsShapeCore& shapeCore);
virtual void unregisterShape(const PxsShapeCore& shapeCore);
virtual void registerMaterial(const PxsMaterialCore& materialCore);
virtual void updateMaterial(const PxsMaterialCore& materialCore);
virtual void unregisterMaterial(const PxsMaterialCore& materialCore);
virtual void appendContactManagers();
virtual void appendContactManagersFallback(PxsContactManagerOutput* cmOutputs);
virtual void removeContactManagersFallback(PxsContactManagerOutput* cmOutputs);
virtual void setContactModifyCallback(PxContactModifyCallback* callback) { mModifyCallback = callback; }
virtual PxsContactManagerOutputIterator getContactManagerOutputs();
virtual PxsContactManagerOutput& getNewContactManagerOutput(PxU32 npIndex);
virtual PxsContactManagerOutput* getGPUContactManagerOutputBase() { return NULL; }
virtual void acquireContext(){}
virtual void releaseContext(){}
virtual void preallocateNewBuffers(PxU32 /*nbNewPairs*/, PxU32 /*maxIndex*/) { /*TODO - implement if it's useful to do so*/}
void processContactManager(PxReal dt, PxsContactManagerOutput* cmOutputs, PxBaseTask* continuation);
void processContactManagerSecondPass(PxReal dt, PxBaseTask* continuation);
void fetchUpdateContactManager() {}
void startNarrowPhaseTasks() {}
virtual void lock() { mContactManagerMutex.lock(); }
virtual void unlock() { mContactManagerMutex.unlock(); }
Ps::Array<PxU32> mRemovedContactManagers;
PxsContactManagers mNarrowPhasePairs;
PxsContactManagers mNewNarrowPhasePairs;
PxContactModifyCallback* mModifyCallback;
IG::IslandSim* mIslandSim;
Ps::Mutex mContactManagerMutex;
private:
void unregisterContactManagerInternal(PxU32 npIndex, PxsContactManagers& managers, PxsContactManagerOutput* cmOutputs);
PX_NOCOPY(PxsNphaseImplementationContext)
};
}
#endif

View File

@ -0,0 +1,182 @@
//
// 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 PXS_RIGID_BODY_H
#define PXS_RIGID_BODY_H
#include "PxvDynamics.h"
#include "CmSpatialVector.h"
namespace physx
{
struct PxsCCDBody;
#define PX_INTERNAL_LOCK_FLAG_START 8
PX_ALIGN_PREFIX(16)
class PxsRigidBody
{
public:
enum PxsRigidBodyFlag
{
eFROZEN = 1 << 0, //This flag indicates that the stabilization is enabled and the body is
//"frozen". By "frozen", we mean that the body's transform is unchanged
//from the previous frame. This permits various optimizations.
eFREEZE_THIS_FRAME = 1 << 1,
eUNFREEZE_THIS_FRAME = 1 << 2,
eACTIVATE_THIS_FRAME = 1 << 3,
eDEACTIVATE_THIS_FRAME = 1 << 4,
// PT: this flag is now only used on the GPU. For the CPU the data is now stored directly in PxsBodyCore.
eDISABLE_GRAVITY_GPU = 1 << 5,
eSPECULATIVE_CCD = 1 << 6,
//KS - copied here for GPU simulation to avoid needing to pass another set of flags around.
eLOCK_LINEAR_X = 1 << (PX_INTERNAL_LOCK_FLAG_START),
eLOCK_LINEAR_Y = 1 << (PX_INTERNAL_LOCK_FLAG_START + 1),
eLOCK_LINEAR_Z = 1 << (PX_INTERNAL_LOCK_FLAG_START + 2),
eLOCK_ANGULAR_X = 1 << (PX_INTERNAL_LOCK_FLAG_START + 3),
eLOCK_ANGULAR_Y = 1 << (PX_INTERNAL_LOCK_FLAG_START + 4),
eLOCK_ANGULAR_Z = 1 << (PX_INTERNAL_LOCK_FLAG_START + 5)
};
PX_FORCE_INLINE PxsRigidBody(PxsBodyCore* core, PxReal freeze_count) :
// PT: TODO: unify naming conventions
mLastTransform (core->body2World),
mInternalFlags (0),
solverIterationCounts (core->solverIterationCounts),
mCCD (NULL),
mCore (core),
sleepLinVelAcc (PxVec3(0.0f)),
freezeCount (freeze_count),
sleepAngVelAcc (PxVec3(0.0f)),
accelScale (1.0f)
{}
PX_FORCE_INLINE ~PxsRigidBody() {}
PX_FORCE_INLINE const PxTransform& getPose() const { PX_ASSERT(mCore->body2World.isSane()); return mCore->body2World; }
PX_FORCE_INLINE const PxVec3& getLinearVelocity() const { PX_ASSERT(mCore->linearVelocity.isFinite()); return mCore->linearVelocity; }
PX_FORCE_INLINE const PxVec3& getAngularVelocity() const { PX_ASSERT(mCore->angularVelocity.isFinite()); return mCore->angularVelocity; }
PX_FORCE_INLINE void setVelocity(const PxVec3& linear,
const PxVec3& angular) { PX_ASSERT(linear.isFinite()); PX_ASSERT(angular.isFinite());
mCore->linearVelocity = linear;
mCore->angularVelocity = angular; }
PX_FORCE_INLINE void setLinearVelocity(const PxVec3& linear) { PX_ASSERT(linear.isFinite()); mCore->linearVelocity = linear; }
PX_FORCE_INLINE void setAngularVelocity(const PxVec3& angular) { PX_ASSERT(angular.isFinite()); mCore->angularVelocity = angular; }
PX_FORCE_INLINE void constrainLinearVelocity();
PX_FORCE_INLINE void constrainAngularVelocity();
PX_FORCE_INLINE PxU32 getIterationCounts() { return mCore->solverIterationCounts; }
PX_FORCE_INLINE PxReal getReportThreshold() const { return mCore->contactReportThreshold; }
PX_FORCE_INLINE const PxTransform& getLastCCDTransform() const { return mLastTransform; }
PX_FORCE_INLINE void saveLastCCDTransform() { mLastTransform = mCore->body2World; }
PX_FORCE_INLINE bool isKinematic() const { return mCore->inverseMass == 0.0f; }
PX_FORCE_INLINE void setPose(const PxTransform& pose) { mCore->body2World = pose; }
PX_FORCE_INLINE void setPosition(const PxVec3& position) { mCore->body2World.p = position; }
PX_FORCE_INLINE PxReal getInvMass() const { return mCore->inverseMass; }
PX_FORCE_INLINE PxVec3 getInvInertia() const { return mCore->inverseInertia; }
PX_FORCE_INLINE PxReal getMass() const { return 1.0f/mCore->inverseMass; }
PX_FORCE_INLINE PxVec3 getInertia() const { return PxVec3(1.0f/mCore->inverseInertia.x,
1.0f/mCore->inverseInertia.y,
1.0f/mCore->inverseInertia.z); }
PX_FORCE_INLINE PxsBodyCore& getCore() { return *mCore; }
PX_FORCE_INLINE const PxsBodyCore& getCore() const { return *mCore; }
PX_FORCE_INLINE PxU32 isActivateThisFrame() const { return PxU32(mInternalFlags & eACTIVATE_THIS_FRAME); }
PX_FORCE_INLINE PxU32 isDeactivateThisFrame() const { return PxU32(mInternalFlags & eDEACTIVATE_THIS_FRAME); }
PX_FORCE_INLINE PxU32 isFreezeThisFrame() const { return PxU32(mInternalFlags & eFREEZE_THIS_FRAME); }
PX_FORCE_INLINE PxU32 isUnfreezeThisFrame() const { return PxU32(mInternalFlags & eUNFREEZE_THIS_FRAME); }
PX_FORCE_INLINE void clearFreezeFlag() { mInternalFlags &= ~eFREEZE_THIS_FRAME; }
PX_FORCE_INLINE void clearUnfreezeFlag() { mInternalFlags &= ~eUNFREEZE_THIS_FRAME; }
PX_FORCE_INLINE void clearAllFrameFlags() { mInternalFlags &= eFROZEN; }
// PT: implemented in PxsCCD.cpp:
void advanceToToi(PxReal toi, PxReal dt, bool clip);
void advancePrevPoseToToi(PxReal toi);
// PxTransform getAdvancedTransform(PxReal toi) const;
Cm::SpatialVector getPreSolverVelocities() const;
PxTransform mLastTransform; //28 (28)
PxU16 mInternalFlags; //30 (30)
PxU16 solverIterationCounts; //32 (32)
PxsCCDBody* mCCD; //36 (40) // only valid during CCD
PxsBodyCore* mCore; //40 (48)
#if !PX_P64_FAMILY
PxU32 alignmentPad[2]; //48 (48)
#endif
PxVec3 sleepLinVelAcc; //60 (60)
PxReal freezeCount; //64 (64)
PxVec3 sleepAngVelAcc; //76 (76)
PxReal accelScale; //80 (80)
}
PX_ALIGN_SUFFIX(16);
PX_COMPILE_TIME_ASSERT(0 == (sizeof(PxsRigidBody) & 0x0f));
void PxsRigidBody::constrainLinearVelocity()
{
const PxU32 lockFlags = mCore->lockFlags;
if(lockFlags)
{
if(lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_X)
mCore->linearVelocity.x = 0.0f;
if(lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_Y)
mCore->linearVelocity.y = 0.0f;
if(lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_Z)
mCore->linearVelocity.z = 0.0f;
}
}
void PxsRigidBody::constrainAngularVelocity()
{
const PxU32 lockFlags = mCore->lockFlags;
if(lockFlags)
{
if(lockFlags & PxRigidDynamicLockFlag::eLOCK_ANGULAR_X)
mCore->angularVelocity.x = 0.0f;
if(lockFlags & PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y)
mCore->angularVelocity.y = 0.0f;
if(lockFlags & PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z)
mCore->angularVelocity.z = 0.0f;
}
}
}
#endif

View File

@ -0,0 +1,54 @@
//
// 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 PXS_SHAPESIM_H
#define PXS_SHAPESIM_H
#include "PxsBodySim.h"
#include "PxsIslandNodeIndex.h"
namespace physx
{
struct PxsShapeCore;
//PxsBodySim is 12 or 16 bytes
struct PxsShapeSim// : public PxsBodySim
{
PxsShapeCore* mShapeCore; // 4 or 8
IG::NodeIndex mBodySimIndex; // 8 or 12
PxU32 mElementIndex; // 12 or 16 transform cache and bound index
PxU32 mShapeIndex; // 16 or 20
#if PX_P64_FAMILY
PxU32 mPad[3];
#endif
};
}//physx
#endif

View File

@ -0,0 +1,202 @@
//
// 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 PXS_SIMPLE_ISLAND_GEN_H
#define PXS_SIMPLE_ISLAND_GEN_H
#include "PxsIslandSim.h"
#include "CmTask.h"
namespace physx
{
namespace Sc
{
class Interaction;
}
namespace IG
{
class SimpleIslandManager;
class ThirdPassTask : public Cm::Task
{
SimpleIslandManager& mIslandManager;
IslandSim& mIslandSim;
public:
ThirdPassTask(PxU64 contextID, SimpleIslandManager& islandManager, IslandSim& islandSim);
virtual void runInternal();
virtual const char* getName() const
{
return "ThirdPassIslandGenTask";
}
private:
PX_NOCOPY(ThirdPassTask)
};
class PostThirdPassTask : public Cm::Task
{
SimpleIslandManager& mIslandManager;
public:
PostThirdPassTask(PxU64 contextID, SimpleIslandManager& islandManager);
virtual void runInternal();
virtual const char* getName() const
{
return "PostThirdPassTask";
}
private:
PX_NOCOPY(PostThirdPassTask)
};
class SimpleIslandManager
{
HandleManager<PxU32> mNodeHandles; //! Handle manager for nodes
HandleManager<EdgeIndex> mEdgeHandles; //! Handle manager for edges
//An array of destroyed nodes
Ps::Array<NodeIndex> mDestroyedNodes;
Cm::BlockArray<Sc::Interaction*> mInteractions;
//Edges destroyed this frame
Ps::Array<EdgeIndex> mDestroyedEdges;
Ps::Array<PartitionEdge*> mFirstPartitionEdges;
Ps::Array<PartitionEdge*> mDestroyedPartitionEdges;
//KS - stores node indices for a given edge. Node index 0 is at 2* edgeId and NodeIndex1 is at 2*edgeId + 1
//can also be used for edgeInstance indexing so there's no need to figure out outboundNode ID either!
Cm::BlockArray<NodeIndex> mEdgeNodeIndices;
Cm::BlockArray<void*> mConstraintOrCm; //! Pointers to either the constraint or Cm for this pair
Cm::BitMap mConnectedMap;
IslandSim mIslandManager;
IslandSim mSpeculativeIslandManager;
ThirdPassTask mSpeculativeThirdPassTask;
ThirdPassTask mAccurateThirdPassTask;
PostThirdPassTask mPostThirdPassTask;
PxU32 mMaxDirtyNodesPerFrame;
PxU64 mContextID;
public:
SimpleIslandManager(bool useEnhancedDeterminism, PxU64 contextID);
~SimpleIslandManager();
NodeIndex addRigidBody(PxsRigidBody* body, bool isKinematic, bool isActive);
void removeNode(const NodeIndex index);
NodeIndex addArticulation(Sc::ArticulationSim* articulation, Dy::ArticulationV* llArtic, bool isActive);
EdgeIndex addContactManager(PxsContactManager* manager, NodeIndex nodeHandle1, NodeIndex nodeHandle2, Sc::Interaction* interaction);
EdgeIndex addConstraint(Dy::Constraint* constraint, NodeIndex nodeHandle1, NodeIndex nodeHandle2, Sc::Interaction* interaction);
bool isConnected(EdgeIndex edgeIndex) const { return !!mConnectedMap.test(edgeIndex); }
PX_FORCE_INLINE NodeIndex getEdgeIndex(EdgeInstanceIndex edgeIndex) const { return mEdgeNodeIndices[edgeIndex]; }
void activateNode(NodeIndex index);
void deactivateNode(NodeIndex index);
void putNodeToSleep(NodeIndex index);
void removeConnection(EdgeIndex edgeIndex);
void firstPassIslandGen();
void additionalSpeculativeActivation();
void secondPassIslandGen();
void thirdPassIslandGen(PxBaseTask* continuation);
void clearDestroyedEdges();
void setEdgeConnected(EdgeIndex edgeIndex);
void setEdgeDisconnected(EdgeIndex edgeIndex);
bool getIsEdgeConnected(EdgeIndex edgeIndex);
void setEdgeRigidCM(const EdgeIndex edgeIndex, PxsContactManager* cm);
void clearEdgeRigidCM(const EdgeIndex edgeIndex);
void setKinematic(IG::NodeIndex nodeIndex);
void setDynamic(IG::NodeIndex nodeIndex);
const IslandSim& getSpeculativeIslandSim() const { return mSpeculativeIslandManager; }
const IslandSim& getAccurateIslandSim() const { return mIslandManager; }
IslandSim& getAccurateIslandSim() { return mIslandManager; }
PX_FORCE_INLINE PxU32 getNbEdgeHandles() const { return mEdgeHandles.getTotalHandles(); }
PX_FORCE_INLINE PxU32 getNbNodeHandles() const { return mNodeHandles.getTotalHandles(); }
void deactivateEdge(const EdgeIndex edge);
PX_FORCE_INLINE PxsContactManager* getContactManager(IG::EdgeIndex edgeId) const { return reinterpret_cast<PxsContactManager*>(mConstraintOrCm[edgeId]); }
PX_FORCE_INLINE PxsContactManager* getContactManagerUnsafe(IG::EdgeIndex edgeId) const { return reinterpret_cast<PxsContactManager*>(mConstraintOrCm[edgeId]); }
PX_FORCE_INLINE Dy::Constraint* getConstraint(IG::EdgeIndex edgeId) const { return reinterpret_cast<Dy::Constraint*>(mConstraintOrCm[edgeId]); }
PX_FORCE_INLINE Dy::Constraint* getConstraintUnsafe(IG::EdgeIndex edgeId) const { return reinterpret_cast<Dy::Constraint*>(mConstraintOrCm[edgeId]); }
PX_FORCE_INLINE Sc::Interaction* getInteraction(IG::EdgeIndex edgeId) const { return mInteractions[edgeId]; }
PX_FORCE_INLINE PxU64 getContextId() const { return mContextID; }
bool checkInternalConsistency();
private:
friend class ThirdPassTask;
friend class PostThirdPassTask;
bool validateDeactivations() const;
PX_NOCOPY(SimpleIslandManager)
};
}
}
#endif

View File

@ -0,0 +1,144 @@
//
// 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 PXS_SIMULATION_CONTROLLER_H
#define PXS_SIMULATION_CONTROLLER_H
#include "foundation/PxSimpleTypes.h"
#include "foundation/PxPreprocessor.h"
#include "foundation/PxTransform.h"
#include "CmBitMap.h"
#include "PsArray.h"
namespace physx
{
namespace Dy
{
class Context;
struct Constraint;
class ArticulationV;
class FeatherstoneArticulation;
struct ArticulationJointCore;
}
namespace Cm
{
class EventProfiler;
}
namespace Bp
{
class BoundsArray;
class BroadPhase;
}
namespace IG
{
class SimpleIslandManager;
class IslandSim;
class NodeIndex;
}
class PxsTransformCache;
class PxvNphaseImplementationContext;
class PxBaseTask;
struct PxsBodySim;
struct PxsShapeSim;
class PxsRigidBody;
class PxsKernelWranglerManager;
class PxsHeapMemoryAllocatorManager;
template<typename T> class PxgIterator;
struct PxgSolverConstraintManagerConstants;
class PxsSimulationControllerCallback
{
public:
virtual void updateScBodyAndShapeSim(PxBaseTask* continuation) = 0;
virtual PxU32 getNbCcdBodies() = 0;
virtual ~PxsSimulationControllerCallback() {}
};
class PxsSimulationController
{
public:
PxsSimulationController(PxsSimulationControllerCallback* callback): mCallback(callback){}
virtual ~PxsSimulationController(){}
virtual void addJoint(const PxU32 edgeIndex, Dy::Constraint* constraint, IG::IslandSim& islandSim, Ps::Array<PxU32>& jointIndices,
Ps::Array<PxgSolverConstraintManagerConstants, Ps::VirtualAllocator>& managerIter, PxU32 uniqueId) = 0;
virtual void removeJoint(const PxU32 edgeIndex, Dy::Constraint* constraint, Ps::Array<PxU32>& jointIndices, IG::IslandSim& islandSim) = 0;
virtual void addShape(PxsShapeSim* shapeSim, const PxU32 index) = 0;
virtual void removeShape(const PxU32 index) = 0;
virtual void addDynamic(PxsRigidBody* rigidBody, const IG::NodeIndex& nodeIndex) = 0;
virtual void addDynamics(PxsRigidBody** rigidBody, const PxU32* nodeIndex, PxU32 nbToProcess) = 0;
virtual void addArticulation(Dy::ArticulationV* articulation, const IG::NodeIndex& nodeIndex) = 0;
virtual void releaseArticulation(Dy::ArticulationV* articulation, const IG::NodeIndex& nodeIndex) = 0;
virtual void releaseDeferredArticulationIds() = 0;
virtual void updateDynamic(const bool isArticulationLink, const IG::NodeIndex&) = 0;
virtual void updateJoint(const PxU32 edgeIndex, Dy::Constraint* constraint) = 0;
virtual void updateBodies(PxsRigidBody** rigidBodies, PxU32* nodeIndices, const PxU32 nbBodies) = 0;
virtual void updateBodiesAndShapes(PxBaseTask* continuation) = 0;
virtual void update(const PxU32 bitMapWordCounts) = 0;
virtual void updateArticulation(Dy::ArticulationV* articulation, const IG::NodeIndex& nodeIndex) = 0;
virtual void updateArticulationJoint(Dy::ArticulationV* articulation, const IG::NodeIndex& nodeIndex) = 0;
virtual void gpuDmabackData(PxsTransformCache& cache, Bp::BoundsArray& boundArray, Cm::BitMapPinned& changedAABBMgrHandles) = 0;
virtual void udpateScBodyAndShapeSim(PxsTransformCache& cache, Bp::BoundsArray& boundArray, PxBaseTask* continuation) = 0;
virtual PxU32* getActiveBodies() = 0;
virtual PxU32* getDeactiveBodies() = 0;
virtual void** getRigidBodies() = 0;
virtual PxU32 getNbBodies() = 0;
virtual PxU32* getUnfrozenShapes() = 0;
virtual PxU32* getFrozenShapes() = 0;
virtual PxsShapeSim** getShapeSims() = 0;
virtual PxU32 getNbFrozenShapes() = 0;
virtual PxU32 getNbUnfrozenShapes() = 0;
virtual void clear() = 0;
virtual void setBounds(Bp::BoundsArray* boundArray) = 0;
virtual void reserve(const PxU32 nbBodies) = 0;
virtual PxU32 getArticulationRemapIndex(const PxU32 nodeIndex) = 0;
protected:
PxsSimulationControllerCallback* mCallback;
};
PxsSimulationController* createSimulationController(PxsSimulationControllerCallback* callback);
}
#endif

View File

@ -0,0 +1,144 @@
//
// 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 PXS_TRANSFORM_CACHE_H
#define PXS_TRANSFORM_CACHE_H
#include "CmPhysXCommon.h"
#include "CmIDPool.h"
#include "CmBitMap.h"
#include "PsUserAllocated.h"
#include "PsAllocator.h"
#define PX_DEFAULT_CACHE_SIZE 512
namespace physx
{
struct PxsTransformFlag
{
enum Flags
{
eFROZEN = (1 << 0)
};
};
struct PX_ALIGN_PREFIX(16) PxsCachedTransform
{
PxTransform transform;
PxU32 flags;
PX_FORCE_INLINE PxU32 isFrozen() const { return flags & PxsTransformFlag::eFROZEN; }
}
PX_ALIGN_SUFFIX(16);
class PxsTransformCache : public Ps::UserAllocated
{
typedef PxU32 RefCountType;
public:
PxsTransformCache(Ps::VirtualAllocatorCallback& allocatorCallback) : mTransformCache(Ps::VirtualAllocator(&allocatorCallback)), mHasAnythingChanged(true)
{
/*mTransformCache.reserve(PX_DEFAULT_CACHE_SIZE);
mTransformCache.forceSize_Unsafe(PX_DEFAULT_CACHE_SIZE);*/
mUsedSize = 0;
}
void initEntry(PxU32 index)
{
PxU32 oldCapacity = mTransformCache.capacity();
if (index >= oldCapacity)
{
PxU32 newCapacity = Ps::nextPowerOfTwo(index);
mTransformCache.reserve(newCapacity);
mTransformCache.forceSize_Unsafe(newCapacity);
}
mUsedSize = PxMax(mUsedSize, index + 1u);
}
PX_FORCE_INLINE void setTransformCache(const PxTransform& transform, const PxU32 flags, const PxU32 index)
{
mTransformCache[index].transform = transform;
mTransformCache[index].flags = flags;
mHasAnythingChanged = true;
}
PX_FORCE_INLINE const PxsCachedTransform& getTransformCache(const PxU32 index) const
{
return mTransformCache[index];
}
PX_FORCE_INLINE PxsCachedTransform& getTransformCache(const PxU32 index)
{
return mTransformCache[index];
}
PX_FORCE_INLINE void shiftTransforms(const PxVec3& shift)
{
for (PxU32 i = 0; i < mTransformCache.capacity(); i++)
{
mTransformCache[i].transform.p += shift;
}
mHasAnythingChanged = true;
}
PX_FORCE_INLINE PxU32 getTotalSize() const
{
return mUsedSize;
}
PX_FORCE_INLINE const PxsCachedTransform* getTransforms() const
{
return mTransformCache.begin();
}
PX_FORCE_INLINE PxsCachedTransform* getTransforms()
{
return mTransformCache.begin();
}
PX_FORCE_INLINE Ps::Array<PxsCachedTransform, Ps::VirtualAllocator>* getCachedTransformArray()
{
return &mTransformCache;
}
PX_FORCE_INLINE void resetChangedState() { mHasAnythingChanged = false; }
PX_FORCE_INLINE void setChangedState() { mHasAnythingChanged = true; }
PX_FORCE_INLINE bool hasChanged() const { return mHasAnythingChanged; }
private:
Ps::Array<PxsCachedTransform, Ps::VirtualAllocator> mTransformCache;
PxU32 mUsedSize;
bool mHasAnythingChanged;
};
}
#endif

View File

@ -0,0 +1,223 @@
//
// 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 PXV_NPHASE_IMPLEMENTATION_CONTEXT_H
#define PXV_NPHASE_IMPLEMENTATION_CONTEXT_H
#include "PxSceneDesc.h"
#include "PxsContactManagerState.h"
#include "PsArray.h"
namespace physx
{
namespace IG
{
class SimpleIslandManager;
class IslandSim;
typedef PxU32 EdgeIndex;
}
namespace Dy
{
class Context;
}
class PxBaseTask;
class PxsContext;
struct PxsShapeCore;
class PxsMaterialCore;
struct PxgDynamicsMemoryConfig;
class PxsContactManager;
struct PxsContactManagerOutput;
class PxsKernelWranglerManager;
class PxsHeapMemoryAllocatorManager;
struct PxsContactManagerBase
{
static const PxU32 NEW_CONTACT_MANAGER_MASK = 0x80000000;
static const PxU32 GPU_NP_OFFSET = 0x4;
static const PxU32 MaxBucketBits = 3;
const PxU32 mBucketId;
PxsContactManagerBase(const PxU32 bucketId) : mBucketId(bucketId)
{
PX_ASSERT(bucketId < (1<<MaxBucketBits));
}
PX_FORCE_INLINE PxU32 computeId(const PxU32 index) const { PX_ASSERT(index < PxU32(1 << (32 - (MaxBucketBits-1)))); return (index << MaxBucketBits) | (mBucketId); }
static PX_FORCE_INLINE PxU32 computeIndexFromId(const PxU32 id) { return id >> MaxBucketBits; }
static PX_FORCE_INLINE PxU32 computeBucketIndexFromId(const PxU32 id) { return id & ((1<<MaxBucketBits)-1); }
private:
PX_NOCOPY(PxsContactManagerBase)
};
class PxsContactManagerOutputIterator
{
PxU32 mOffsets[1<<PxsContactManagerBase::MaxBucketBits];
PxsContactManagerOutput* mOutputs;
public:
PxsContactManagerOutputIterator() : mOutputs(NULL)
{
}
PxsContactManagerOutputIterator(PxU32* offsets, PxU32 nbOffsets, PxsContactManagerOutput* outputs) : mOutputs(outputs)
{
PX_ASSERT(nbOffsets <= (1<<PxsContactManagerBase::MaxBucketBits));
for(PxU32 a = 0; a < nbOffsets; ++a)
{
mOffsets[a] = offsets[a];
}
}
PX_FORCE_INLINE PxsContactManagerOutput& getContactManager(PxU32 id)
{
PX_ASSERT((id & PxsContactManagerBase::NEW_CONTACT_MANAGER_MASK) == 0);
PxU32 bucketId = PxsContactManagerBase::computeBucketIndexFromId(id);
PxU32 cmOutId = PxsContactManagerBase::computeIndexFromId(id);
return mOutputs[mOffsets[bucketId] + cmOutId];
}
PxU32 getIndex(PxU32 id)
{
PX_ASSERT((id & PxsContactManagerBase::NEW_CONTACT_MANAGER_MASK) == 0);
PxU32 bucketId = PxsContactManagerBase::computeBucketIndexFromId(id);
PxU32 cmOutId = PxsContactManagerBase::computeIndexFromId(id);
return mOffsets[bucketId] + cmOutId;
}
};
class PxvNphaseImplementationContext
{
private:
PX_NOCOPY(PxvNphaseImplementationContext)
public:
PxvNphaseImplementationContext(PxsContext& context): mContext(context) {}
virtual ~PxvNphaseImplementationContext() {}
virtual void destroy() = 0;
virtual void updateContactManager(PxReal dt, bool hasBoundsArrayChanged, bool hasContactDistanceChanged, PxBaseTask* continuation, PxBaseTask* firstPassContinuation) = 0;
virtual void postBroadPhaseUpdateContactManager() = 0;
virtual void secondPassUpdateContactManager(PxReal dt, PxBaseTask* continuation) = 0;
virtual void fetchUpdateContactManager() = 0;
virtual void registerContactManager(PxsContactManager* cm, PxI32 touching, PxU32 patchCount) = 0;
virtual void registerContactManagers(PxsContactManager** cm, PxU32 nbContactManagers, PxU32 maxContactManagerId) = 0;
virtual void unregisterContactManager(PxsContactManager* cm) = 0;
virtual void refreshContactManager(PxsContactManager* cm) = 0;
virtual void registerShape(const PxsShapeCore& shapeCore) = 0;
virtual void unregisterShape(const PxsShapeCore& shapeCore) = 0;
virtual void registerMaterial(const PxsMaterialCore& materialCore) = 0;
virtual void updateMaterial(const PxsMaterialCore& materialCore) = 0;
virtual void unregisterMaterial(const PxsMaterialCore& materialCore) = 0;
virtual void updateShapeMaterial(const PxsShapeCore& shapeCore) = 0;
virtual PxsContactManagerOutput* getGPUContactManagerOutputBase() = 0;
virtual void startNarrowPhaseTasks() = 0;
virtual void appendContactManagers() = 0;
virtual PxsContactManagerOutput& getNewContactManagerOutput(PxU32 index) = 0;
virtual PxsContactManagerOutputIterator getContactManagerOutputs() = 0;
virtual void setContactModifyCallback(PxContactModifyCallback* callback) = 0;
virtual void acquireContext() = 0;
virtual void releaseContext() = 0;
virtual void preallocateNewBuffers(PxU32 nbNewPairs, PxU32 maxIndex) = 0;
virtual void lock() = 0;
virtual void unlock() = 0;
protected:
PxsContext& mContext;
};
class PxvNphaseImplementationFallback
{
private:
PX_NOCOPY(PxvNphaseImplementationFallback)
public:
PxvNphaseImplementationFallback() {}
virtual ~PxvNphaseImplementationFallback() {}
virtual void processContactManager(PxReal dt, PxsContactManagerOutput* cmOutputs, PxBaseTask* continuation) = 0;
virtual void processContactManagerSecondPass(PxReal dt, PxBaseTask* continuation) = 0;
virtual void registerContactManager(PxsContactManager* cm, PxI32 touching, PxU32 numPatches) = 0;
virtual void unregisterContactManagerFallback(PxsContactManager* cm, PxsContactManagerOutput* cmOutputs) = 0;
virtual void refreshContactManagerFallback(PxsContactManager* cm, PxsContactManagerOutput* cmOutputs) = 0;
virtual PxsContactManagerOutput& getNewContactManagerOutput(PxU32 npId) = 0;
virtual void appendContactManagersFallback(PxsContactManagerOutput* outputs) = 0;
virtual void setContactModifyCallback(PxContactModifyCallback* callback) = 0;
virtual void removeContactManagersFallback(PxsContactManagerOutput* cmOutputs) = 0;
virtual void lock() = 0;
virtual void unlock() = 0;
};
class PxvNphaseImplementationContextUsableAsFallback: public PxvNphaseImplementationContext, public PxvNphaseImplementationFallback
{
private:
PX_NOCOPY(PxvNphaseImplementationContextUsableAsFallback)
public:
PxvNphaseImplementationContextUsableAsFallback(PxsContext& context): PxvNphaseImplementationContext(context) {}
virtual ~PxvNphaseImplementationContextUsableAsFallback() {}
};
PxvNphaseImplementationContextUsableAsFallback* createNphaseImplementationContext(PxsContext& context, IG::IslandSim* islandSim);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -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.
#include "PxsContactManager.h"
#include "PxsRigidBody.h"
#include "PxcContactMethodImpl.h"
#include "PxvManager.h"
#include "PxsIslandSim.h"
using namespace physx;
PxsContactManager::PxsContactManager(PxsContext*, PxU32 index) /*:
mUserData (NULL)*/
{
mFlags = 0;
// PT: TODO: any reason why we don't initialize all members here, e.g. shapeCore pointers?
mNpUnit.index = index;
mNpUnit.rigidCore0 = NULL;
mNpUnit.rigidCore1 = NULL;
mNpUnit.restDistance = 0;
mNpUnit.dominance0 = 1u;
mNpUnit.dominance1 = 1u;
mNpUnit.frictionDataPtr = NULL;
mNpUnit.frictionPatchCount = 0;
}
PxsContactManager::~PxsContactManager()
{
}
void PxsContactManager::setCCD(bool enable)
{
PxU32 flags = mFlags & (~PXS_CM_CCD_CONTACT);
if (enable)
flags |= PXS_CM_CCD_LINEAR;
else
flags &= ~PXS_CM_CCD_LINEAR;
mFlags = flags;
}
void PxsContactManager::resetCachedState()
{
// happens when the body transform or shape relative transform changes.
PxcNpWorkUnitClearCachedState(mNpUnit);
}
void PxsContactManager::resetFrictionCachedState()
{
// happens when the body transform or shape relative transform changes.
PxcNpWorkUnitClearFrictionCachedState(mNpUnit);
}

View File

@ -0,0 +1,623 @@
//
// 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 "common/PxProfileZone.h"
#include "PxvConfig.h"
#include "PxcContactCache.h"
#include "PxsRigidBody.h"
#include "PxsContactManager.h"
#include "PxsContext.h"
#include "PxPhysXConfig.h"
#include "CmBitMap.h"
#include "CmFlushPool.h"
#include "PxsMaterialManager.h"
#include "PxSceneDesc.h"
#include "PxsCCD.h"
#include "PxvGeometry.h"
#include "PxvManager.h"
#include "PxsSimpleIslandManager.h"
#if PX_SUPPORT_GPU_PHYSX
#include "PxPhysXGpu.h"
#endif
#include "PxcNpContactPrepShared.h"
#include "PxcNpCache.h"
using namespace physx;
using namespace physx::shdfnd;
#define PXS_CONTACTMANAGER_SLABSIZE 1024
#define PXS_MAX_CONTACTMANAGER_SLABS 64
#define PXS_BODYSHAPE_SLABSIZE 1024
#define PXS_MAX_BODYSHAPE_SLABS 16
PxsContext::PxsContext(const PxSceneDesc& desc, PxTaskManager* taskManager, Cm::FlushPool& taskPool, PxCudaContextManager* cudaContextManager, PxU64 contextID) :
mNpThreadContextPool (this),
mContactManagerPool ("mContactManagerPool", this, 256),
mManifoldPool ("mManifoldPool", 256),
mSphereManifoldPool ("mSphereManifoldPool", 256),
mContactModifyCallback (NULL),
mNpImplementationContext (NULL),
mNpFallbackImplementationContext(NULL),
mTaskManager (taskManager),
mTaskPool (taskPool),
mCudaContextManager (cudaContextManager),
mPCM (desc.flags & PxSceneFlag::eENABLE_PCM),
mContactCache (false),
mCreateAveragePoint (desc.flags & PxSceneFlag::eENABLE_AVERAGE_POINT),
mContextID (contextID)
{
clearManagerTouchEvents();
mVisualizationCullingBox.setMaximal();
PxMemZero(mVisualizationParams, sizeof(PxReal) * PxVisualizationParameter::eNUM_VALUES);
mNpMemBlockPool.init(desc.nbContactDataBlocks, desc.maxNbContactDataBlocks);
}
PxsContext::~PxsContext()
{
if(mTransformCache)
{
mTransformCache->~PxsTransformCache();
PX_FREE(mTransformCache);
}
mTransformCache = NULL;
mContactManagerPool.destroy(); //manually destroy the contact manager pool, otherwise pool deletion order is random and we can get into trouble with references into other pools needed during destruction.
}
// =========================== Create methods
namespace physx
{
bool gEnablePCMCaching[PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT] =
{
//eSPHERE,
{
false, //eSPHERE
false, //ePLANE
false, //eCAPSULE
false, //eBOX
true, //eCONVEXMESH
true, //eTRIANGLEMESH
true //eHEIGHTFIELD
},
//ePLANE
{
false, //eSPHERE
false, //ePLANE
true, //eCAPSULE
true, //eBOX
true, //eCONVEXMESH
false, //eTRIANGLEMESH
false //eHEIGHTFIELD
},
//eCAPSULE,
{
false, //eSPHERE
true, //ePLANE
false, //eCAPSULE
true, //eBOX
true, //eCONVEXMESH
true, //eTRIANGLEMESH
true //eHEIGHTFIELD
},
//eBOX,
{
false, //eSPHERE
true, //ePLANE
true, //eCAPSULE
true, //eBOX
true, //eCONVEXMESH
true, //eTRIANGLEMESH
true //eHEIGHTFIELD
},
//eCONVEXMESH,
{
true, //eSPHERE
true, //ePLANE
true, //eCAPSULE
true, //eBOX
true, //eCONVEXMESH
true, //eTRIANGLEMESH
true //eHEIGHTFIELD
},
//eTRIANGLEMESH,
{
true, //eSPHERE
false, //ePLANE
true, //eCAPSULE
true, //eBOX
true, //eCONVEXMESH
false, //eTRIANGLEMESH
false //eHEIGHTFIELD
},
//eHEIGHTFIELD,
{
true, //eSPHERE
false, //ePLANE
true, //eCAPSULE
true, //eBOX
true, //eCONVEXMESH
false, //eTRIANGLEMESH
false //eHEIGHTFIELD
}
};
}
void PxsContext::createTransformCache(Ps::VirtualAllocatorCallback& allocatorCallback)
{
mTransformCache = PX_PLACEMENT_NEW(PX_ALLOC(sizeof(PxsTransformCache), PX_DEBUG_EXP("PxsTransformCache")), PxsTransformCache(allocatorCallback));
}
PxsContactManager* PxsContext::createContactManager(PxsContactManager* contactManager, const bool useCCD)
{
PxsContactManager* cm = contactManager? contactManager : mContactManagerPool.get();
if(cm)
{
PxcNpWorkUnitClearContactState(cm->getWorkUnit());
PxcNpWorkUnitClearCachedState(cm->getWorkUnit());
if (contactManager == NULL)
{
if (cm->getIndex() >= mActiveContactManager.size())
{
PxU32 newSize = (2 * cm->getIndex() + 256)&~255;
mActiveContactManager.resize(newSize);
}
mActiveContactManager.set(cm->getIndex());
if (useCCD)
{
if (cm->getIndex() >= mActiveContactManagersWithCCD.size())
{
PxU32 newSize = (2 * cm->getIndex() + 256)&~255;
mActiveContactManagersWithCCD.resize(newSize);
}
mActiveContactManagersWithCCD.set(cm->getIndex());
}
}
}
else
{
PX_WARN_ONCE("Reached limit of contact pairs.");
}
return cm;
}
void PxsContext::createCache(Gu::Cache& cache, PxsContactManager* cm, PxU8 geomType0, PxU8 geomType1)
{
if(cm)
{
if(mPCM)
{
if(gEnablePCMCaching[geomType0][geomType1])
{
if(geomType0 <= PxGeometryType::eCONVEXMESH &&
geomType1 <= PxGeometryType::eCONVEXMESH)
{
if(geomType0 == PxGeometryType::eSPHERE || geomType1 == PxGeometryType::eSPHERE)
{
Gu::PersistentContactManifold* manifold = mSphereManifoldPool.allocate();
new(manifold) Gu::SpherePersistentContactManifold();
cache.setManifold(manifold);
}
else
{
Gu::PersistentContactManifold* manifold = mManifoldPool.allocate();
new(manifold) Gu::LargePersistentContactManifold();
cache.setManifold(manifold);
}
cache.getManifold().clearManifold();
}
else
{
//ML: raised 1 to indicate the manifold is multiManifold which is for contact gen in mesh/height field
//cache.manifold = 1;
cache.setMultiManifold(NULL);
}
}
else
{
//cache.manifold = 0;
cache.mCachedData = NULL;
cache.mManifoldFlags = 0;
}
}
}
}
void PxsContext::destroyContactManager(PxsContactManager* cm)
{
const PxU32 idx = cm->getIndex();
if (cm->getCCD())
mActiveContactManagersWithCCD.growAndReset(idx);
mActiveContactManager.growAndReset(idx);
mContactManagerTouchEvent.growAndReset(idx);
mContactManagerPatchChangeEvent.growAndReset(idx);
mContactManagerPool.put(cm);
}
void PxsContext::destroyCache(Gu::Cache& cache)
{
if(cache.isManifold())
{
if(!cache.isMultiManifold())
{
Gu::PersistentContactManifold& manifold = cache.getManifold();
if (manifold.mCapacity == GU_SPHERE_MANIFOLD_CACHE_SIZE)
{
mSphereManifoldPool.deallocate(static_cast<Gu::SpherePersistentContactManifold*>(&manifold));
}
else
{
mManifoldPool.deallocate(static_cast<Gu::LargePersistentContactManifold*>(&manifold));
}
}
cache.mCachedData = NULL;
cache.mManifoldFlags = 0;
}
}
void PxsContext::setScratchBlock(void* addr, PxU32 size)
{
mScratchAllocator.setBlock(addr, size);
}
void PxsContext::setContactDistance(Ps::Array<PxReal, Ps::VirtualAllocator>* contactDistance)
{
mContactDistance = contactDistance;
}
void PxsContext::shiftOrigin(const PxVec3& shift)
{
// transform cache
mTransformCache->shiftTransforms(-shift);
#if 0
if (getContactCacheFlag())
{
//Iterate all active contact managers
Cm::BitMap::Iterator it(mActiveContactManager);
PxU32 index = it.getNext();
while(index != Cm::BitMap::Iterator::DONE)
{
PxsContactManager* cm = mContactManagerPool.findByIndexFast(index);
PxcNpWorkUnit& npwUnit = cm->getWorkUnit();
// contact cache
if(!npwUnit.pairCache.isManifold())
{
PxU8* contactCachePtr = npwUnit.pairCache.mCachedData;
if (contactCachePtr)
{
PxcLocalContactsCache* lcc;
PxU8* contacts = PxcNpCacheRead(npwUnit.pairCache, lcc);
#ifdef _DEBUG
PxcLocalContactsCache testCache;
PxU32 testBytes;
const PxU8* testPtr = PxcNpCacheRead2(npwUnit.pairCache, testCache, testBytes);
#endif
lcc->mTransform0.p -= shift;
lcc->mTransform1.p -= shift;
const PxU32 nbContacts = lcc->mNbCachedContacts;
const bool sameNormal = lcc->mSameNormal;
const bool useFaceIndices = lcc->mUseFaceIndices;
for(PxU32 i=0; i < nbContacts; i++)
{
if (i != nbContacts-1)
Ps::prefetchLine(contacts, 128);
if(!i || !sameNormal)
contacts += sizeof(PxVec3);
PxVec3* cachedPoint = reinterpret_cast<PxVec3*>(contacts);
*cachedPoint -= shift;
contacts += sizeof(PxVec3);
contacts += sizeof(PxReal);
if(useFaceIndices)
contacts += 2 * sizeof(PxU32);
}
#ifdef _DEBUG
PX_ASSERT(contacts == (testPtr + testBytes));
#endif
}
}
index = it.getNext();
}
}
#endif
//
// adjust visualization culling box
//
PxBounds3 maximalBounds;
maximalBounds.setMaximal();
if ((mVisualizationCullingBox.minimum != maximalBounds.minimum) || (mVisualizationCullingBox.maximum != maximalBounds.maximum))
{
mVisualizationCullingBox.minimum -= shift;
mVisualizationCullingBox.maximum -= shift;
}
}
void PxsContext::swapStreams()
{
mNpMemBlockPool.swapNpCacheStreams();
}
void PxsContext::mergeCMDiscreteUpdateResults(PxBaseTask* /*continuation*/)
{
PX_PROFILE_ZONE("Sim.narrowPhaseMerge", mContextID);
this->mNpImplementationContext->appendContactManagers();
//Note: the iterator extracts all the items and returns them to the cache on destruction(for thread safety).
PxcThreadCoherentCacheIterator<PxcNpThreadContext, PxcNpContext> threadContextIt(mNpThreadContextPool);
for(PxcNpThreadContext* threadContext = threadContextIt.getNext(); threadContext; threadContext = threadContextIt.getNext())
{
mCMTouchEventCount[PXS_LOST_TOUCH_COUNT] += threadContext->getLocalLostTouchCount();
mCMTouchEventCount[PXS_NEW_TOUCH_COUNT] += threadContext->getLocalNewTouchCount();
mCMTouchEventCount[PXS_PATCH_FOUND_COUNT] += threadContext->getLocalFoundPatchCount();
mCMTouchEventCount[PXS_PATCH_LOST_COUNT] += threadContext->getLocalLostPatchCount();
#if PX_ENABLE_SIM_STATS
for(PxU32 i=0;i<PxGeometryType::eGEOMETRY_COUNT;i++)
{
#if PX_DEBUG
for(PxU32 j=0; j<i; j++)
PX_ASSERT(!threadContext->mDiscreteContactPairs[i][j]);
#endif
for(PxU32 j=i; j<PxGeometryType::eGEOMETRY_COUNT; j++)
{
const PxU32 nb = threadContext->mDiscreteContactPairs[i][j];
const PxU32 nbModified = threadContext->mModifiedContactPairs[i][j];
mSimStats.mNbDiscreteContactPairs[i][j] += nb;
mSimStats.mNbModifiedContactPairs[i][j] += nbModified;
mSimStats.mNbDiscreteContactPairsTotal += nb;
}
}
mSimStats.mNbDiscreteContactPairsWithCacheHits += threadContext->mNbDiscreteContactPairsWithCacheHits;
mSimStats.mNbDiscreteContactPairsWithContacts += threadContext->mNbDiscreteContactPairsWithContacts;
mSimStats.mTotalCompressedContactSize += threadContext->mCompressedCacheSize;
//KS - this data is not available yet
//mSimStats.mTotalConstraintSize += threadContext->mConstraintSize;
threadContext->clearStats();
#endif
mContactManagerTouchEvent.combineInPlace<Cm::BitMap::OR>(threadContext->getLocalChangeTouch());
mContactManagerPatchChangeEvent.combineInPlace<Cm::BitMap::OR>(threadContext->getLocalPatchChangeMap());
mTotalCompressedCacheSize += threadContext->mTotalCompressedCacheSize;
mMaxPatches = PxMax(mMaxPatches, threadContext->mMaxPatches);
threadContext->mTotalCompressedCacheSize = threadContext->mMaxPatches = 0;
}
}
void PxsContext::setCreateContactStream(bool to)
{
mCreateContactStream = to;
PxcThreadCoherentCacheIterator<PxcNpThreadContext, PxcNpContext> threadContextIt(mNpThreadContextPool);
for(PxcNpThreadContext* threadContext = threadContextIt.getNext(); threadContext; threadContext = threadContextIt.getNext())
{
threadContext->setCreateContactStream(to);
}
}
void PxsContext::updateContactManager(PxReal dt, bool hasBoundsArrayChanged, bool hasContactDistanceChanged, PxBaseTask* continuation, PxBaseTask* firstPassContinuation)
{
PX_ASSERT(mNpImplementationContext);
mNpImplementationContext->updateContactManager(dt, hasBoundsArrayChanged, hasContactDistanceChanged, continuation, firstPassContinuation);
}
void PxsContext::secondPassUpdateContactManager(PxReal dt, PxBaseTask* continuation)
{
PX_ASSERT(mNpImplementationContext);
mNpImplementationContext->secondPassUpdateContactManager(dt, continuation);
}
void PxsContext::fetchUpdateContactManager()
{
PX_ASSERT(mNpImplementationContext);
mNpImplementationContext->fetchUpdateContactManager();
mergeCMDiscreteUpdateResults(NULL);
}
void PxsContext::resetThreadContexts()
{
//Note: the iterator extracts all the items and returns them to the cache on destruction(for thread safety).
PxcThreadCoherentCacheIterator<PxcNpThreadContext, PxcNpContext> threadContextIt(mNpThreadContextPool);
PxcNpThreadContext* threadContext = threadContextIt.getNext();
while(threadContext != NULL)
{
threadContext->reset(mContactManagerTouchEvent.size());
threadContext = threadContextIt.getNext();
}
}
bool PxsContext::getManagerTouchEventCount(int* newTouch, int* lostTouch, int* ccdTouch) const
{
if(newTouch)
*newTouch = int(mCMTouchEventCount[PXS_NEW_TOUCH_COUNT]);
if(lostTouch)
*lostTouch = int(mCMTouchEventCount[PXS_LOST_TOUCH_COUNT]);
if(ccdTouch)
*ccdTouch = int(mCMTouchEventCount[PXS_CCD_RETOUCH_COUNT]);
return true;
}
bool PxsContext::fillManagerTouchEvents(PxvContactManagerTouchEvent* newTouch, PxI32& newTouchCount, PxvContactManagerTouchEvent* lostTouch, PxI32& lostTouchCount,
PxvContactManagerTouchEvent* ccdTouch, PxI32& ccdTouchCount)
{
PxU32 index;
const PxvContactManagerTouchEvent* newTouchStart = newTouch;
const PxvContactManagerTouchEvent* lostTouchStart = lostTouch;
const PxvContactManagerTouchEvent* ccdTouchStart = ccdTouch;
const PxvContactManagerTouchEvent* newTouchEnd = newTouch + newTouchCount;
const PxvContactManagerTouchEvent* lostTouchEnd = lostTouch + lostTouchCount;
const PxvContactManagerTouchEvent* ccdTouchEnd = ccdTouch + ccdTouchCount;
PX_UNUSED(newTouchEnd);
PX_UNUSED(lostTouchEnd);
PX_UNUSED(ccdTouchEnd);
Cm::BitMap::Iterator it(mContactManagerTouchEvent);
while((index = it.getNext()) != Cm::BitMap::Iterator::DONE)
{
PxsContactManager* cm = mContactManagerPool.findByIndexFast(index);
if(cm->getTouchStatus())
{
if (!cm->getHasCCDRetouch())
{
PX_ASSERT(newTouch < newTouchEnd);
newTouch->manager = cm;
newTouch->userData = cm->getUserData();
newTouch++;
}
else
{
PX_ASSERT(ccdTouch);
PX_ASSERT(ccdTouch < ccdTouchEnd);
ccdTouch->manager = cm;
ccdTouch->userData = cm->getUserData();
cm->clearCCDRetouch();
ccdTouch++;
}
}
else
{
PX_ASSERT(lostTouch < lostTouchEnd);
lostTouch->manager = cm;
lostTouch->userData = cm->getUserData();
lostTouch++;
}
}
newTouchCount = PxI32(newTouch - newTouchStart);
lostTouchCount = PxI32(lostTouch - lostTouchStart);
ccdTouchCount = PxI32(ccdTouch - ccdTouchStart);
return true;
}
bool PxsContext::fillManagerPatchChangedEvents(PxsContactManager** foundPatch, PxU32& foundPatchCount,
PxsContactManager** lostPatch, PxU32& lostPatchCount)
{
Cm::BitMap::Iterator it(mContactManagerPatchChangeEvent);
PxsContactManagerOutputIterator outputs = mNpImplementationContext->getContactManagerOutputs();
PxU32 index;
PxsContactManager** currFoundPatch = foundPatch;
PxsContactManager** currLostPatch = lostPatch;
while((index = it.getNext()) != Cm::BitMap::Iterator::DONE)
{
PxsContactManager* cm = mContactManagerPool.findByIndexFast(index);
PxcNpWorkUnit& workUnit = cm->getWorkUnit();
PxsContactManagerOutput& output = outputs.getContactManager(workUnit.mNpIndex);
if(output.nbPatches > output.prevPatches)
{
PX_ASSERT(PxU32(currFoundPatch - foundPatch) < foundPatchCount);
*currFoundPatch = cm;
currFoundPatch++;
}
else if(output.nbPatches < output.prevPatches)
{
PX_ASSERT(PxU32(currLostPatch - lostPatch) < lostPatchCount);
*currLostPatch = cm;
currLostPatch++;
}
}
foundPatchCount = PxU32(currFoundPatch - foundPatch);
lostPatchCount = PxU32(currLostPatch - lostPatch);
return true;
}
void PxsContext::beginUpdate()
{
#if PX_ENABLE_SIM_STATS
mSimStats.clearAll();
#endif
}
// Contact manager related
PxReal PxsContext::getVisualizationParameter(PxVisualizationParameter::Enum param) const
{
PX_ASSERT(param < PxVisualizationParameter::eNUM_VALUES);
return mVisualizationParams[param];
}
void PxsContext::setVisualizationParameter(PxVisualizationParameter::Enum param, PxReal value)
{
PX_ASSERT(param < PxVisualizationParameter::eNUM_VALUES);
PX_ASSERT(value >= 0.0f);
mVisualizationParams[param] = value;
}

View File

@ -0,0 +1,74 @@
//
// 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 "PxsDefaultMemoryManager.h"
namespace physx
{
PxsDefaultMemoryManager::~PxsDefaultMemoryManager()
{
for (PxU32 i = 0; i < mAllocators.size(); ++i)
{
mAllocators[i]->~VirtualAllocatorCallback();
PX_FREE(mAllocators[i]);
}
}
Ps::VirtualAllocatorCallback* PxsDefaultMemoryManager::createHostMemoryAllocator(const PxU32 gpuComputeVersion)
{
PX_UNUSED(gpuComputeVersion);
Ps::VirtualAllocatorCallback* allocator = PX_PLACEMENT_NEW(PX_ALLOC(sizeof(PxsDefaultMemoryAllocator), "PxsDefaultMemoryAllocator"), PxsDefaultMemoryAllocator());
mAllocators.pushBack(allocator);
return allocator;
}
//this is an empty stub
Ps::VirtualAllocatorCallback* PxsDefaultMemoryManager::createDeviceMemoryAllocator(const PxU32 gpuComputeVersion)
{
PX_UNUSED(gpuComputeVersion);
return NULL;
}
void PxsDefaultMemoryManager::destroyMemoryAllocator()
{
for (PxU32 i = 0; i < mAllocators.size(); ++i)
{
mAllocators[i]->~VirtualAllocatorCallback();
PX_FREE(mAllocators[i]);
}
}
PxsMemoryManager* createMemoryManager()
{
return PX_PLACEMENT_NEW(PX_ALLOC(sizeof(PxsDefaultMemoryManager), PX_DEBUG_EXP("PxsDefaultMemoryManager")), PxsDefaultMemoryManager());
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,102 @@
//
// 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 "PxsMaterialCombiner.h"
#include "PsMathUtils.h"
#include "CmPhysXCommon.h"
#include "PsFoundation.h"
namespace physx
{
PxsMaterialCombiner::PxsMaterialCombiner(PxReal staticFrictionScaling, PxReal dynamicFrictionScaling)
: mStaticFrictionScaling(staticFrictionScaling), mDynamicFrictionScaling(dynamicFrictionScaling)
{}
PxReal PxsMaterialCombiner::combineRestitution(const PxsMaterialData& mat0, const PxsMaterialData& mat1)
{
/*return combineScalars(mat0.restitution, mat1.restitution, PxMax(mat0.restitutionCombineMode, mat1.restitutionCombineMode));*/
return combineScalars(mat0.restitution, mat1.restitution, PxMax(mat0.getRestitutionCombineMode(), mat1.getRestitutionCombineMode()));
}
PxsMaterialCombiner::PxsCombinedMaterial PxsMaterialCombiner::combineIsotropicFriction(const PxsMaterialData& mat0, const PxsMaterialData& mat1)
{
PxsCombinedMaterial dest;
dest.flags = (mat0.flags | mat1.flags); //& (PxMaterialFlag::eDISABLE_STRONG_FRICTION|PxMaterialFlag::eDISABLE_FRICTION); //eventually set DisStrongFric flag, lower all others.
if (!(dest.flags & PxMaterialFlag::eDISABLE_FRICTION))
{
const PxI32 fictionCombineMode = PxMax(mat0.getFrictionCombineMode(), mat1.getFrictionCombineMode());
PxReal dynFriction = 0.f;
PxReal staFriction = 0.f;
switch (fictionCombineMode)
{
case PxCombineMode::eAVERAGE:
dynFriction = 0.5f * (mat0.dynamicFriction + mat1.dynamicFriction);
staFriction = 0.5f * (mat0.staticFriction + mat1.staticFriction);
break;
case PxCombineMode::eMIN:
dynFriction = PxMin(mat0.dynamicFriction, mat1.dynamicFriction);
staFriction = PxMin(mat0.staticFriction, mat1.staticFriction);
break;
case PxCombineMode::eMULTIPLY:
dynFriction = (mat0.dynamicFriction * mat1.dynamicFriction);
staFriction = (mat0.staticFriction * mat1.staticFriction);
break;
case PxCombineMode::eMAX:
dynFriction = PxMax(mat0.dynamicFriction, mat1.dynamicFriction);
staFriction = PxMax(mat0.staticFriction, mat1.staticFriction);
break;
}
dynFriction*=mDynamicFrictionScaling;
staFriction*=mStaticFrictionScaling;
//isotropic case
const PxReal fDynFriction = PxMax(dynFriction, 0.f);
const PxReal fStaFriction = physx::intrinsics::fsel(staFriction - fDynFriction, staFriction, fDynFriction);
dest.dynFriction = fDynFriction;
dest.staFriction = fStaFriction;
}
else
{
dest.flags |= PxMaterialFlag::eDISABLE_STRONG_FRICTION;
dest.staFriction = 0.0f;
dest.dynFriction = 0.0f;
}
return dest;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,377 @@
//
// 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 "common/PxProfileZone.h"
#include "PxsSimpleIslandManager.h"
#include "PsSort.h"
#include "PxsContactManager.h"
#include "CmTask.h"
#include "DyVArticulation.h"
#define IG_SANITY_CHECKS 0
namespace physx
{
namespace IG
{
ThirdPassTask::ThirdPassTask(PxU64 contextID, SimpleIslandManager& islandManager, IslandSim& islandSim) : Cm::Task(contextID), mIslandManager(islandManager), mIslandSim(islandSim)
{
}
PostThirdPassTask::PostThirdPassTask(PxU64 contextID, SimpleIslandManager& islandManager) : Cm::Task(contextID), mIslandManager(islandManager)
{
}
SimpleIslandManager::SimpleIslandManager(bool useEnhancedDeterminism, PxU64 contextID) :
mDestroyedNodes (PX_DEBUG_EXP("mDestroyedNodes")),
mDestroyedEdges (PX_DEBUG_EXP("mDestroyedEdges")),
mFirstPartitionEdges (PX_DEBUG_EXP("mFirstPartitionEdges")),
mDestroyedPartitionEdges (PX_DEBUG_EXP("IslandSim::mDestroyedPartitionEdges")),
mIslandManager (&mFirstPartitionEdges, mEdgeNodeIndices, &mDestroyedPartitionEdges, contextID),
mSpeculativeIslandManager (NULL, mEdgeNodeIndices, NULL, contextID),
mSpeculativeThirdPassTask (contextID, *this, mSpeculativeIslandManager),
mAccurateThirdPassTask (contextID, *this, mIslandManager),
mPostThirdPassTask (contextID, *this),
mContextID (contextID)
{
mFirstPartitionEdges.resize(1024);
mMaxDirtyNodesPerFrame = useEnhancedDeterminism ? 0xFFFFFFFF : 1000u;
}
SimpleIslandManager::~SimpleIslandManager()
{
}
NodeIndex SimpleIslandManager::addRigidBody(PxsRigidBody* body, bool isKinematic, bool isActive)
{
PxU32 handle = mNodeHandles.getHandle();
NodeIndex nodeIndex(handle);
mIslandManager.addRigidBody(body, isKinematic, isActive, nodeIndex);
mSpeculativeIslandManager.addRigidBody(body, isKinematic, isActive, nodeIndex);
return nodeIndex;
}
void SimpleIslandManager::removeNode(const NodeIndex index)
{
PX_ASSERT(mNodeHandles.isValidHandle(index.index()));
mDestroyedNodes.pushBack(index);
}
NodeIndex SimpleIslandManager::addArticulation(Sc::ArticulationSim* articulation, Dy::ArticulationV* llArtic, bool isActive)
{
PxU32 handle = mNodeHandles.getHandle();
NodeIndex nodeIndex(handle);
mIslandManager.addArticulation(articulation, llArtic, isActive, nodeIndex);
mSpeculativeIslandManager.addArticulation(articulation, llArtic, isActive, nodeIndex);
return nodeIndex;
}
EdgeIndex SimpleIslandManager::addContactManager(PxsContactManager* manager, NodeIndex nodeHandle1, NodeIndex nodeHandle2, Sc::Interaction* interaction)
{
EdgeIndex handle = mEdgeHandles.getHandle();
PxU32 nodeIds = 2 * handle;
if (mEdgeNodeIndices.size() == nodeIds)
{
PX_PROFILE_ZONE("ReserveEdges", getContextId());
const PxU32 newSize = nodeIds + 2048;
mEdgeNodeIndices.resize(newSize);
mConstraintOrCm.resize(newSize);
mInteractions.resize(newSize);
}
mEdgeNodeIndices[nodeIds] = nodeHandle1;
mEdgeNodeIndices[nodeIds+1] = nodeHandle2;
mConstraintOrCm[handle] = manager;
mInteractions[handle] = interaction;
mSpeculativeIslandManager.addContactManager(manager, nodeHandle1, nodeHandle2, handle);
if (manager)
manager->getWorkUnit().mEdgeIndex = handle;
if(mConnectedMap.size() == handle)
{
mConnectedMap.resize(2 * (handle + 1));
}
if (mFirstPartitionEdges.capacity() == handle)
{
mFirstPartitionEdges.resize(2 * (handle + 1));
}
mConnectedMap.reset(handle);
return handle;
}
EdgeIndex SimpleIslandManager::addConstraint(Dy::Constraint* constraint, NodeIndex nodeHandle1, NodeIndex nodeHandle2, Sc::Interaction* interaction)
{
EdgeIndex handle = mEdgeHandles.getHandle();
PxU32 nodeIds = 2 * handle;
if (mEdgeNodeIndices.size() == nodeIds)
{
mEdgeNodeIndices.resize(2 * (mEdgeNodeIndices.size() + 2));
mConstraintOrCm.resize(2 * (handle + 1));
mInteractions.resize(2 * (handle + 1));
}
mEdgeNodeIndices[nodeIds] = nodeHandle1;
mEdgeNodeIndices[nodeIds + 1] = nodeHandle2;
mConstraintOrCm[handle] = constraint;
mInteractions[handle] = interaction;
mIslandManager.addConstraint(constraint, nodeHandle1, nodeHandle2, handle);
mSpeculativeIslandManager.addConstraint(constraint, nodeHandle1, nodeHandle2, handle);
if(mConnectedMap.size() == handle)
{
mConnectedMap.resize(2*(mConnectedMap.size()+1));
}
if (mFirstPartitionEdges.capacity() == handle)
{
mFirstPartitionEdges.resize(2 * (mFirstPartitionEdges.capacity() + 1));
}
mConnectedMap.set(handle);
return handle;
}
void SimpleIslandManager::activateNode(NodeIndex index)
{
mIslandManager.activateNode(index);
mSpeculativeIslandManager.activateNode(index);
}
void SimpleIslandManager::deactivateNode(NodeIndex index)
{
mIslandManager.deactivateNode(index);
mSpeculativeIslandManager.deactivateNode(index);
}
void SimpleIslandManager::putNodeToSleep(NodeIndex index)
{
mIslandManager.putNodeToSleep(index);
mSpeculativeIslandManager.putNodeToSleep(index);
}
void SimpleIslandManager::removeConnection(EdgeIndex edgeIndex)
{
if(edgeIndex == IG_INVALID_EDGE)
return;
mDestroyedEdges.pushBack(edgeIndex);
mSpeculativeIslandManager.removeConnection(edgeIndex);
if(mConnectedMap.test(edgeIndex))
{
mIslandManager.removeConnection(edgeIndex);
mConnectedMap.reset(edgeIndex);
}
mConstraintOrCm[edgeIndex] = NULL;
mInteractions[edgeIndex] = NULL;
}
void SimpleIslandManager::firstPassIslandGen()
{
PX_PROFILE_ZONE("Basic.firstPassIslandGen", getContextId());
mSpeculativeIslandManager.clearDeactivations();
mSpeculativeIslandManager.wakeIslands();
mSpeculativeIslandManager.processNewEdges();
mSpeculativeIslandManager.removeDestroyedEdges();
mSpeculativeIslandManager.processLostEdges(mDestroyedNodes, false, false, mMaxDirtyNodesPerFrame);
}
void SimpleIslandManager::additionalSpeculativeActivation()
{
mSpeculativeIslandManager.wakeIslands2();
}
void SimpleIslandManager::secondPassIslandGen()
{
PX_PROFILE_ZONE("Basic.secondPassIslandGen", getContextId());
mIslandManager.wakeIslands();
mIslandManager.processNewEdges();
mIslandManager.removeDestroyedEdges();
mIslandManager.processLostEdges(mDestroyedNodes, false, false, mMaxDirtyNodesPerFrame);
for(PxU32 a = 0; a < mDestroyedNodes.size(); ++a)
{
mNodeHandles.freeHandle(mDestroyedNodes[a].index());
}
mDestroyedNodes.clear();
//mDestroyedEdges.clear();
}
bool SimpleIslandManager::validateDeactivations() const
{
//This method sanity checks the deactivations produced by third-pass island gen. Specifically, it ensures that any bodies that
//the speculative IG wants to deactivate are also candidates for deactivation in the accurate island gen. In practice, both should be the case. If this fails, something went wrong...
const NodeIndex* const nodeIndices = mSpeculativeIslandManager.getNodesToDeactivate(Node::eRIGID_BODY_TYPE);
const PxU32 nbNodesToDeactivate = mSpeculativeIslandManager.getNbNodesToDeactivate(Node::eRIGID_BODY_TYPE);
for(PxU32 i = 0; i < nbNodesToDeactivate; ++i)
{
//Node is active in accurate sim => mismatch between accurate and inaccurate sim!
const Node& node = mIslandManager.getNode(nodeIndices[i]);
const Node& speculativeNode = mSpeculativeIslandManager.getNode(nodeIndices[i]);
//KS - we need to verify that the bodies in the "deactivating" list are still candidates for deactivation. There are cases where they may not no longer be candidates, e.g. if the application
//put bodies to sleep and activated them
if(node.isActive() && !speculativeNode.isActive())
return false;
}
return true;
}
void ThirdPassTask::runInternal()
{
PX_PROFILE_ZONE("Basic.thirdPassIslandGen", mIslandSim.getContextId());
mIslandSim.removeDestroyedEdges();
mIslandSim.processLostEdges(mIslandManager.mDestroyedNodes, true, true, mIslandManager.mMaxDirtyNodesPerFrame);
}
void PostThirdPassTask::runInternal()
{
for (PxU32 a = 0; a < mIslandManager.mDestroyedNodes.size(); ++a)
{
mIslandManager.mNodeHandles.freeHandle(mIslandManager.mDestroyedNodes[a].index());
}
mIslandManager.mDestroyedNodes.clear();
for (PxU32 a = 0; a < mIslandManager.mDestroyedEdges.size(); ++a)
{
mIslandManager.mEdgeHandles.freeHandle(mIslandManager.mDestroyedEdges[a]);
}
mIslandManager.mDestroyedEdges.clear();
PX_ASSERT(mIslandManager.validateDeactivations());
}
void SimpleIslandManager::thirdPassIslandGen(PxBaseTask* continuation)
{
mIslandManager.clearDeactivations();
mPostThirdPassTask.setContinuation(continuation);
mSpeculativeThirdPassTask.setContinuation(&mPostThirdPassTask);
mAccurateThirdPassTask.setContinuation(&mPostThirdPassTask);
mSpeculativeThirdPassTask.removeReference();
mAccurateThirdPassTask.removeReference();
mPostThirdPassTask.removeReference();
//PX_PROFILE_ZONE("Basic.thirdPassIslandGen", getContextId());
//mSpeculativeIslandManager.removeDestroyedEdges();
//mSpeculativeIslandManager.processLostEdges(mDestroyedNodes, true, true);
//mIslandManager.removeDestroyedEdges();
//mIslandManager.processLostEdges(mDestroyedNodes, true, true);
}
bool SimpleIslandManager::checkInternalConsistency()
{
return mIslandManager.checkInternalConsistency() && mSpeculativeIslandManager.checkInternalConsistency();
}
void SimpleIslandManager::clearDestroyedEdges()
{
mDestroyedPartitionEdges.forceSize_Unsafe(0);
}
void SimpleIslandManager::setEdgeConnected(EdgeIndex edgeIndex)
{
if(!mConnectedMap.test(edgeIndex))
{
mIslandManager.addContactManager(reinterpret_cast<PxsContactManager*>(mConstraintOrCm[edgeIndex]), mEdgeNodeIndices[edgeIndex * 2], mEdgeNodeIndices[edgeIndex * 2 + 1], edgeIndex);
mConnectedMap.set(edgeIndex);
}
}
bool SimpleIslandManager::getIsEdgeConnected(EdgeIndex edgeIndex)
{
return !!mConnectedMap.test(edgeIndex);
}
void SimpleIslandManager::deactivateEdge(const EdgeIndex edgeIndex)
{
if (mFirstPartitionEdges[edgeIndex])
{
mDestroyedPartitionEdges.pushBack(mFirstPartitionEdges[edgeIndex]);
mFirstPartitionEdges[edgeIndex] = NULL;
}
}
void SimpleIslandManager::setEdgeDisconnected(EdgeIndex edgeIndex)
{
if(mConnectedMap.test(edgeIndex))
{
//PX_ASSERT(!mIslandManager.getEdge(edgeIndex).isInDirtyList());
mIslandManager.removeConnection(edgeIndex);
mConnectedMap.reset(edgeIndex);
}
}
void SimpleIslandManager::setEdgeRigidCM(const EdgeIndex edgeIndex, PxsContactManager* cm)
{
mConstraintOrCm[edgeIndex] = cm;
cm->getWorkUnit().mEdgeIndex = edgeIndex;
}
void SimpleIslandManager::clearEdgeRigidCM(const EdgeIndex edgeIndex)
{
mConstraintOrCm[edgeIndex] = NULL;
if (mFirstPartitionEdges[edgeIndex])
{
//this is the partition edges created/updated by the gpu solver
mDestroyedPartitionEdges.pushBack(mFirstPartitionEdges[edgeIndex]);
mFirstPartitionEdges[edgeIndex] = NULL;
}
}
void SimpleIslandManager::setKinematic(IG::NodeIndex nodeIndex)
{
mIslandManager.setKinematic(nodeIndex);
mSpeculativeIslandManager.setKinematic(nodeIndex);
}
void SimpleIslandManager::setDynamic(IG::NodeIndex nodeIndex)
{
mIslandManager.setDynamic(nodeIndex);
mSpeculativeIslandManager.setDynamic(nodeIndex);
}
}
}