Init
This commit is contained in:
127
physx/source/lowlevel/api/include/PxsMaterialCore.h
Normal file
127
physx/source/lowlevel/api/include/PxsMaterialCore.h
Normal 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
|
||||
149
physx/source/lowlevel/api/include/PxsMaterialManager.h
Normal file
149
physx/source/lowlevel/api/include/PxsMaterialManager.h
Normal 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
|
||||
47
physx/source/lowlevel/api/include/PxvConfig.h
Normal file
47
physx/source/lowlevel/api/include/PxvConfig.h
Normal 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
|
||||
183
physx/source/lowlevel/api/include/PxvDynamics.h
Normal file
183
physx/source/lowlevel/api/include/PxvDynamics.h
Normal 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
|
||||
80
physx/source/lowlevel/api/include/PxvGeometry.h
Normal file
80
physx/source/lowlevel/api/include/PxvGeometry.h
Normal 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
|
||||
116
physx/source/lowlevel/api/include/PxvGlobals.h
Normal file
116
physx/source/lowlevel/api/include/PxvGlobals.h
Normal 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
|
||||
213
physx/source/lowlevel/api/include/PxvManager.h
Normal file
213
physx/source/lowlevel/api/include/PxvManager.h
Normal 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
|
||||
|
||||
114
physx/source/lowlevel/api/include/PxvSimStats.h
Normal file
114
physx/source/lowlevel/api/include/PxvSimStats.h
Normal 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
|
||||
94
physx/source/lowlevel/api/src/px_globals.cpp
Normal file
94
physx/source/lowlevel/api/src/px_globals.cpp
Normal 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
|
||||
@ -0,0 +1,87 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#ifndef PXC_CONTACTMETHODIMPL_H
|
||||
#define PXC_CONTACTMETHODIMPL_H
|
||||
|
||||
#include "GuGeometryUnion.h"
|
||||
#include "CmPhysXCommon.h"
|
||||
#include "GuContactMethodImpl.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Cm
|
||||
{
|
||||
class RenderOutput;
|
||||
}
|
||||
|
||||
namespace Gu
|
||||
{
|
||||
class ContactBuffer;
|
||||
struct Cache;
|
||||
struct NarrowPhaseParams;
|
||||
}
|
||||
|
||||
namespace Cm
|
||||
{
|
||||
class FastVertex2ShapeScaling;
|
||||
}
|
||||
|
||||
/*!\file
|
||||
This file contains forward declarations of all implemented contact methods.
|
||||
*/
|
||||
|
||||
|
||||
/*! Parameter list without names to avoid unused parameter warnings
|
||||
*/
|
||||
#define CONTACT_METHOD_ARGS_UNUSED \
|
||||
const Gu::GeometryUnion&, \
|
||||
const Gu::GeometryUnion&, \
|
||||
const PxTransform&, \
|
||||
const PxTransform&, \
|
||||
const Gu::NarrowPhaseParams&, \
|
||||
Gu::Cache&, \
|
||||
Gu::ContactBuffer&, \
|
||||
Cm::RenderOutput*
|
||||
|
||||
/*!
|
||||
Method prototype for contact generation routines
|
||||
*/
|
||||
typedef bool (*PxcContactMethod) (GU_CONTACT_METHOD_ARGS);
|
||||
|
||||
// Matrix of types
|
||||
extern PxcContactMethod g_ContactMethodTable[][PxGeometryType::eGEOMETRY_COUNT];
|
||||
extern const bool g_CanUseContactCache[][PxGeometryType::eGEOMETRY_COUNT];
|
||||
extern PxcContactMethod g_PCMContactMethodTable[][PxGeometryType::eGEOMETRY_COUNT];
|
||||
|
||||
extern bool gEnablePCMCaching[][PxGeometryType::eGEOMETRY_COUNT];
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,156 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#ifndef PXC_CONSTRAINTBLOCKPOOL_H
|
||||
#define PXC_CONSTRAINTBLOCKPOOL_H
|
||||
|
||||
#include "PxvConfig.h"
|
||||
#include "PsArray.h"
|
||||
#include "PsMutex.h"
|
||||
#include "PxcNpMemBlockPool.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxsConstraintBlockManager
|
||||
{
|
||||
public:
|
||||
PxsConstraintBlockManager(PxcNpMemBlockPool & blockPool):
|
||||
mBlockPool(blockPool)
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void reset()
|
||||
{
|
||||
mBlockPool.releaseConstraintBlocks(mTrackingArray);
|
||||
}
|
||||
|
||||
PxcNpMemBlockArray mTrackingArray;
|
||||
PxcNpMemBlockPool& mBlockPool;
|
||||
|
||||
private:
|
||||
PxsConstraintBlockManager& operator=(const PxsConstraintBlockManager&);
|
||||
};
|
||||
|
||||
class PxcConstraintBlockStream
|
||||
{
|
||||
PX_NOCOPY(PxcConstraintBlockStream)
|
||||
public:
|
||||
PxcConstraintBlockStream(PxcNpMemBlockPool & blockPool) :
|
||||
mBlockPool (blockPool),
|
||||
mBlock (NULL),
|
||||
mUsed (0)
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxU8* reserve(PxU32 size, PxsConstraintBlockManager& manager)
|
||||
{
|
||||
size = (size+15)&~15;
|
||||
if(size>PxcNpMemBlock::SIZE)
|
||||
return mBlockPool.acquireExceptionalConstraintMemory(size);
|
||||
|
||||
if(mBlock == NULL || size+mUsed>PxcNpMemBlock::SIZE)
|
||||
{
|
||||
mBlock = mBlockPool.acquireConstraintBlock(manager.mTrackingArray);
|
||||
PX_ASSERT(0==mBlock || mBlock->data == reinterpret_cast<PxU8*>(mBlock));
|
||||
mUsed = size;
|
||||
return reinterpret_cast<PxU8*>(mBlock);
|
||||
}
|
||||
PX_ASSERT(mBlock && mBlock->data == reinterpret_cast<PxU8*>(mBlock));
|
||||
PxU8* PX_RESTRICT result = mBlock->data+mUsed;
|
||||
mUsed += size;
|
||||
return result;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void reset()
|
||||
{
|
||||
mBlock = NULL;
|
||||
mUsed = 0;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxcNpMemBlockPool& getMemBlockPool() { return mBlockPool; }
|
||||
|
||||
private:
|
||||
PxcNpMemBlockPool& mBlockPool;
|
||||
PxcNpMemBlock* mBlock; // current constraint block
|
||||
PxU32 mUsed; // number of bytes used in constraint block
|
||||
//Tracking peak allocations
|
||||
PxU32 mPeakUsed;
|
||||
};
|
||||
|
||||
class PxcContactBlockStream
|
||||
{
|
||||
PX_NOCOPY(PxcContactBlockStream)
|
||||
public:
|
||||
PxcContactBlockStream(PxcNpMemBlockPool & blockPool):
|
||||
mBlockPool(blockPool),
|
||||
mBlock(NULL),
|
||||
mUsed(0)
|
||||
{
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxU8* reserve(PxU32 size)
|
||||
{
|
||||
size = (size+15)&~15;
|
||||
|
||||
if(size>PxcNpMemBlock::SIZE)
|
||||
return mBlockPool.acquireExceptionalConstraintMemory(size);
|
||||
|
||||
PX_ASSERT(size <= PxcNpMemBlock::SIZE);
|
||||
|
||||
if(mBlock == NULL || size+mUsed>PxcNpMemBlock::SIZE)
|
||||
{
|
||||
mBlock = mBlockPool.acquireContactBlock();
|
||||
PX_ASSERT(0==mBlock || mBlock->data == reinterpret_cast<PxU8*>(mBlock));
|
||||
mUsed = size;
|
||||
return reinterpret_cast<PxU8*>(mBlock);
|
||||
}
|
||||
PX_ASSERT(mBlock && mBlock->data == reinterpret_cast<PxU8*>(mBlock));
|
||||
PxU8* PX_RESTRICT result = mBlock->data+mUsed;
|
||||
mUsed += size;
|
||||
return result;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void reset()
|
||||
{
|
||||
mBlock = NULL;
|
||||
mUsed = 0;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxcNpMemBlockPool& getMemBlockPool() { return mBlockPool; }
|
||||
|
||||
private:
|
||||
PxcNpMemBlockPool& mBlockPool;
|
||||
PxcNpMemBlock* mBlock; // current constraint block
|
||||
PxU32 mUsed; // number of bytes used in constraint block
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,66 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef PXC_CONTACT_CACHE_H
|
||||
#define PXC_CONTACT_CACHE_H
|
||||
|
||||
#include "foundation/PxTransform.h"
|
||||
#include "PxvConfig.h"
|
||||
#include "PxcContactMethodImpl.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxcNpThreadContext;
|
||||
|
||||
bool PxcCacheLocalContacts( PxcNpThreadContext& context, Gu::Cache& pairContactCache,
|
||||
const PxTransform& tm0, const PxTransform& tm1,
|
||||
const PxcContactMethod conMethod,
|
||||
const Gu::GeometryUnion& shape0, const Gu::GeometryUnion& shape1);
|
||||
|
||||
struct PxcLocalContactsCache
|
||||
{
|
||||
PxTransform mTransform0;
|
||||
PxTransform mTransform1;
|
||||
PxU16 mNbCachedContacts;
|
||||
bool mUseFaceIndices;
|
||||
bool mSameNormal;
|
||||
|
||||
PX_FORCE_INLINE void operator = (const PxcLocalContactsCache& other)
|
||||
{
|
||||
mTransform0 = other.mTransform0;
|
||||
mTransform1 = other.mTransform1;
|
||||
mNbCachedContacts = other.mNbCachedContacts;
|
||||
mUseFaceIndices = other.mUseFaceIndices;
|
||||
mSameNormal = other.mSameNormal;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PXC_CONTACT_CACHE_H
|
||||
@ -0,0 +1,69 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef PXC_MATERIALMETHOD_H
|
||||
#define PXC_MATERIALMETHOD_H
|
||||
|
||||
#include "geometry/PxGeometry.h"
|
||||
#include "CmPhysXCommon.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
struct PxsShapeCore;
|
||||
struct PxsMaterialInfo;
|
||||
class PxcNpThreadContext;
|
||||
|
||||
#define MATERIAL_METHOD_ARGS \
|
||||
const PxsShapeCore* shape0, \
|
||||
const PxsShapeCore* shape1, \
|
||||
PxcNpThreadContext& pairContext, \
|
||||
PxsMaterialInfo* materialInfo
|
||||
|
||||
|
||||
#define SINGLE_MATERIAL_METHOD_ARGS \
|
||||
const PxsShapeCore* shape, \
|
||||
const PxU32 index, \
|
||||
PxcNpThreadContext& pairContext, \
|
||||
PxsMaterialInfo* materialInfo
|
||||
|
||||
/*!
|
||||
Method prototype for fetch material routines
|
||||
*/
|
||||
typedef bool (*PxcGetMaterialMethod) (MATERIAL_METHOD_ARGS);
|
||||
|
||||
typedef bool (*PxcGetSingleMaterialMethod) (SINGLE_MATERIAL_METHOD_ARGS);
|
||||
|
||||
extern PxcGetMaterialMethod g_GetMaterialMethodTable[][PxGeometryType::eGEOMETRY_COUNT];
|
||||
|
||||
extern PxcGetSingleMaterialMethod g_GetSingleMaterialMethodTable[PxGeometryType::eGEOMETRY_COUNT];
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
50
physx/source/lowlevel/common/include/pipeline/PxcNpBatch.h
Normal file
50
physx/source/lowlevel/common/include/pipeline/PxcNpBatch.h
Normal file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef PXC_NP_BATCH_H
|
||||
#define PXC_NP_BATCH_H
|
||||
|
||||
#include "PxvConfig.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxcNpWorkUnit;
|
||||
class PxcNpThreadContext;
|
||||
struct PxsContactManagerOutput;
|
||||
|
||||
namespace Gu
|
||||
{
|
||||
struct Cache;
|
||||
}
|
||||
|
||||
void PxcDiscreteNarrowPhase(PxcNpThreadContext& context, const PxcNpWorkUnit& cmInput, Gu::Cache& cache, PxsContactManagerOutput& output);
|
||||
void PxcDiscreteNarrowPhasePCM(PxcNpThreadContext& context, const PxcNpWorkUnit& cmInput, Gu::Cache& cache, PxsContactManagerOutput& output);
|
||||
}
|
||||
|
||||
#endif
|
||||
154
physx/source/lowlevel/common/include/pipeline/PxcNpCache.h
Normal file
154
physx/source/lowlevel/common/include/pipeline/PxcNpCache.h
Normal file
@ -0,0 +1,154 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef PXC_NPCACHE_H
|
||||
#define PXC_NPCACHE_H
|
||||
|
||||
#include "foundation/PxMemory.h"
|
||||
|
||||
#include "PsIntrinsics.h"
|
||||
#include "PxcNpCacheStreamPair.h"
|
||||
|
||||
#include "PsPool.h"
|
||||
#include "PsFoundation.h"
|
||||
#include "GuContactMethodImpl.h"
|
||||
#include "PsUtilities.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
void PxcNpCacheWrite(PxcNpCacheStreamPair& streams,
|
||||
Gu::Cache& cache,
|
||||
const T& payload,
|
||||
PxU32 bytes,
|
||||
const PxU8* data)
|
||||
{
|
||||
const PxU32 payloadSize = (sizeof(payload)+3)&~3;
|
||||
cache.mCachedSize = Ps::to16((payloadSize + 4 + bytes + 0xF)&~0xF);
|
||||
|
||||
PxU8* ls = streams.reserve(cache.mCachedSize);
|
||||
cache.mCachedData = ls;
|
||||
if(ls==NULL || (reinterpret_cast<PxU8*>(-1))==ls)
|
||||
{
|
||||
if(ls==NULL)
|
||||
{
|
||||
PX_WARN_ONCE(
|
||||
"Reached limit set by PxSceneDesc::maxNbContactDataBlocks - ran out of buffer space for narrow phase. "
|
||||
"Either accept dropped contacts or increase buffer size allocated for narrow phase by increasing PxSceneDesc::maxNbContactDataBlocks.");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
PX_WARN_ONCE(
|
||||
"Attempting to allocate more than 16K of contact data for a single contact pair in narrowphase. "
|
||||
"Either accept dropped contacts or simplify collision geometry.");
|
||||
cache.mCachedData = NULL;
|
||||
ls = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*reinterpret_cast<T*>(ls) = payload;
|
||||
*reinterpret_cast<PxU32*>(ls+payloadSize) = bytes;
|
||||
if(data)
|
||||
PxMemCopy(ls+payloadSize+sizeof(PxU32), data, bytes);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
PxU8* PxcNpCacheWriteInitiate(PxcNpCacheStreamPair& streams, Gu::Cache& cache, const T& payload, PxU32 bytes)
|
||||
{
|
||||
PX_UNUSED(payload);
|
||||
|
||||
const PxU32 payloadSize = (sizeof(payload)+3)&~3;
|
||||
cache.mCachedSize = Ps::to16((payloadSize + 4 + bytes + 0xF)&~0xF);
|
||||
|
||||
PxU8* ls = streams.reserve(cache.mCachedSize);
|
||||
cache.mCachedData = ls;
|
||||
if(NULL==ls || reinterpret_cast<PxU8*>(-1)==ls)
|
||||
{
|
||||
if(NULL==ls)
|
||||
{
|
||||
PX_WARN_ONCE(
|
||||
"Reached limit set by PxSceneDesc::maxNbContactDataBlocks - ran out of buffer space for narrow phase. "
|
||||
"Either accept dropped contacts or increase buffer size allocated for narrow phase by increasing PxSceneDesc::maxNbContactDataBlocks.");
|
||||
}
|
||||
else
|
||||
{
|
||||
PX_WARN_ONCE(
|
||||
"Attempting to allocate more than 16K of contact data for a single contact pair in narrowphase. "
|
||||
"Either accept dropped contacts or simplify collision geometry.");
|
||||
cache.mCachedData = NULL;
|
||||
ls = NULL;
|
||||
}
|
||||
}
|
||||
return ls;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PX_FORCE_INLINE void PxcNpCacheWriteFinalize(PxU8* ls, const T& payload, PxU32 bytes, const PxU8* data)
|
||||
{
|
||||
const PxU32 payloadSize = (sizeof(payload)+3)&~3;
|
||||
*reinterpret_cast<T*>(ls) = payload;
|
||||
*reinterpret_cast<PxU32*>(ls+payloadSize) = bytes;
|
||||
if(data)
|
||||
PxMemCopy(ls+payloadSize+sizeof(PxU32), data, bytes);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
PX_FORCE_INLINE PxU8* PxcNpCacheRead(Gu::Cache& cache, T*& payload)
|
||||
{
|
||||
PxU8* ls = cache.mCachedData;
|
||||
payload = reinterpret_cast<T*>(ls);
|
||||
const PxU32 payloadSize = (sizeof(T)+3)&~3;
|
||||
return reinterpret_cast<PxU8*>(ls+payloadSize+sizeof(PxU32));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const PxU8* PxcNpCacheRead2(Gu::Cache& cache, T& payload, PxU32& bytes)
|
||||
{
|
||||
const PxU8* ls = cache.mCachedData;
|
||||
if(ls==NULL)
|
||||
{
|
||||
bytes = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const PxU32 payloadSize = (sizeof(payload)+3)&~3;
|
||||
payload = *reinterpret_cast<const T*>(ls);
|
||||
bytes = *reinterpret_cast<const PxU32*>(ls+payloadSize);
|
||||
PX_ASSERT(cache.mCachedSize == ((payloadSize + 4 + bytes+0xF)&~0xF));
|
||||
return reinterpret_cast<const PxU8*>(ls+payloadSize+sizeof(PxU32));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // #ifndef PXC_NPCACHE_H
|
||||
@ -0,0 +1,63 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
|
||||
#ifndef PXC_NPCACHESTREAMPAIR_H
|
||||
#define PXC_NPCACHESTREAMPAIR_H
|
||||
|
||||
#include "foundation/PxSimpleTypes.h"
|
||||
#include "PxvConfig.h"
|
||||
#include "PxcNpMemBlockPool.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
static const PxU32 PXC_NPCACHE_BLOCK_SIZE = 16384;
|
||||
|
||||
|
||||
struct PxcNpCacheStreamPair
|
||||
{
|
||||
public:
|
||||
PxcNpCacheStreamPair(PxcNpMemBlockPool& blockPool);
|
||||
|
||||
// reserve can fail and return null.
|
||||
PxU8* reserve(PxU32 byteCount);
|
||||
void reset();
|
||||
private:
|
||||
PxcNpMemBlockPool& mBlockPool;
|
||||
PxcNpMemBlock* mBlock;
|
||||
PxU32 mUsed;
|
||||
private:
|
||||
PxcNpCacheStreamPair& operator=(const PxcNpCacheStreamPair&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,57 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef PXC_NPCONTACTPREPSHARED_H
|
||||
#define PXC_NPCONTACTPREPSHARED_H
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxcNpThreadContext;
|
||||
struct PxsMaterialInfo;
|
||||
class PxsMaterialManager;
|
||||
class PxsConstraintBlockManager;
|
||||
class PxcConstraintBlockStream;
|
||||
struct PxsContactManagerOutput;
|
||||
|
||||
namespace Gu
|
||||
{
|
||||
struct ContactPoint;
|
||||
}
|
||||
|
||||
static const PxReal PXC_SAME_NORMAL = 0.999f; //Around 6 degrees
|
||||
|
||||
PxU32 writeCompressedContact(const Gu::ContactPoint* const PX_RESTRICT contactPoints, const PxU32 numContactPoints, PxcNpThreadContext* threadContext,
|
||||
PxU8& writtenContactCount, PxU8*& outContactPatches, PxU8*& outContactPoints, PxU16& compressedContactSize, PxReal*& contactForces, PxU32 contactForceByteSize,
|
||||
const PxsMaterialManager* materialManager, bool hasModifiableContacts, bool forceNoResponse, PxsMaterialInfo* PX_RESTRICT pMaterial, PxU8& numPatches,
|
||||
PxU32 additionalHeaderSize = 0, PxsConstraintBlockManager* manager = NULL, PxcConstraintBlockStream* blockStream = NULL, bool insertAveragePoint = false,
|
||||
PxcDataStreamPool* pool = NULL, PxcDataStreamPool* patchStreamPool = NULL, PxcDataStreamPool* forcePool = NULL, const bool isMeshType = false);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,119 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
|
||||
#ifndef PXC_NP_MEM_BLOCK_POOL_H
|
||||
#define PXC_NP_MEM_BLOCK_POOL_H
|
||||
|
||||
#include "PxvConfig.h"
|
||||
#include "PsArray.h"
|
||||
#include "PxcScratchAllocator.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxcNpMemBlock
|
||||
{
|
||||
enum
|
||||
{
|
||||
SIZE = 16384
|
||||
};
|
||||
PxU8 data[SIZE];
|
||||
};
|
||||
|
||||
typedef Ps::Array<PxcNpMemBlock*> PxcNpMemBlockArray;
|
||||
|
||||
class PxcNpMemBlockPool
|
||||
{
|
||||
PX_NOCOPY(PxcNpMemBlockPool)
|
||||
public:
|
||||
PxcNpMemBlockPool(PxcScratchAllocator& allocator);
|
||||
~PxcNpMemBlockPool();
|
||||
|
||||
void init(PxU32 initial16KDataBlocks, PxU32 maxBlocks);
|
||||
void flush();
|
||||
void setBlockCount(PxU32 count);
|
||||
PxU32 getUsedBlockCount() const;
|
||||
PxU32 getMaxUsedBlockCount() const;
|
||||
PxU32 getPeakConstraintBlockCount() const;
|
||||
void releaseUnusedBlocks();
|
||||
|
||||
PxcNpMemBlock* acquireConstraintBlock();
|
||||
PxcNpMemBlock* acquireConstraintBlock(PxcNpMemBlockArray& memBlocks);
|
||||
PxcNpMemBlock* acquireContactBlock();
|
||||
PxcNpMemBlock* acquireFrictionBlock();
|
||||
PxcNpMemBlock* acquireNpCacheBlock();
|
||||
|
||||
PxU8* acquireExceptionalConstraintMemory(PxU32 size);
|
||||
|
||||
void acquireConstraintMemory();
|
||||
void releaseConstraintMemory();
|
||||
void releaseConstraintBlocks(PxcNpMemBlockArray& memBlocks);
|
||||
void releaseContacts();
|
||||
void swapFrictionStreams();
|
||||
void swapNpCacheStreams();
|
||||
|
||||
void flushUnused();
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Ps::Mutex mLock;
|
||||
PxcNpMemBlockArray mConstraints;
|
||||
PxcNpMemBlockArray mContacts[2];
|
||||
PxcNpMemBlockArray mFriction[2];
|
||||
PxcNpMemBlockArray mNpCache[2];
|
||||
PxcNpMemBlockArray mScratchBlocks;
|
||||
Ps::Array<PxU8*> mExceptionalConstraints;
|
||||
|
||||
PxcNpMemBlockArray mUnused;
|
||||
|
||||
PxU32 mNpCacheActiveStream;
|
||||
PxU32 mFrictionActiveStream;
|
||||
PxU32 mCCDCacheActiveStream;
|
||||
PxU32 mContactIndex;
|
||||
PxU32 mAllocatedBlocks;
|
||||
PxU32 mMaxBlocks;
|
||||
PxU32 mInitialBlocks;
|
||||
PxU32 mUsedBlocks;
|
||||
PxU32 mMaxUsedBlocks;
|
||||
PxcNpMemBlock* mScratchBlockAddr;
|
||||
PxU32 mNbScratchBlocks;
|
||||
PxcScratchAllocator& mScratchAllocator;
|
||||
|
||||
PxU32 mPeakConstraintAllocations;
|
||||
PxU32 mConstraintAllocations;
|
||||
|
||||
PxcNpMemBlock* acquire(PxcNpMemBlockArray& trackingArray, PxU32* allocationCount = NULL, PxU32* peakAllocationCount = NULL, bool isScratchAllocation = false);
|
||||
void release(PxcNpMemBlockArray& deadArray, PxU32* allocationCount = NULL);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,212 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#ifndef PXC_NPTHREADCONTEXT_H
|
||||
#define PXC_NPTHREADCONTEXT_H
|
||||
|
||||
#include "geometry/PxGeometry.h"
|
||||
#include "geomutils/GuContactBuffer.h"
|
||||
|
||||
#include "PxvConfig.h"
|
||||
#include "CmScaling.h"
|
||||
#include "CmRenderOutput.h"
|
||||
#include "PxcNpCacheStreamPair.h"
|
||||
#include "PxcConstraintBlockStream.h"
|
||||
#include "PxcThreadCoherentCache.h"
|
||||
#include "CmBitMap.h"
|
||||
#include "../pcm/GuPersistentContactManifold.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
class PxsTransformCache;
|
||||
class PxsMaterialManager;
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
class BodySim;
|
||||
}
|
||||
|
||||
/*!
|
||||
Per-thread context used by contact generation routines.
|
||||
*/
|
||||
|
||||
struct PxcDataStreamPool
|
||||
{
|
||||
PxU8* mDataStream;
|
||||
PxI32 mSharedDataIndex;
|
||||
PxU32 mDataStreamSize;
|
||||
PxU32 mSharedDataIndexGPU;
|
||||
|
||||
bool isOverflown() const
|
||||
{
|
||||
//FD: my expectaton is that reading those variables is atomic, shared indices are non-decreasing,
|
||||
//so we can only get a false overflow alert because of concurrency issues, which is not a big deal as it means
|
||||
//it did overflow a bit later
|
||||
return mSharedDataIndex + mSharedDataIndexGPU >= mDataStreamSize;
|
||||
}
|
||||
};
|
||||
|
||||
struct PxcNpContext
|
||||
{
|
||||
private:
|
||||
PX_NOCOPY(PxcNpContext)
|
||||
public:
|
||||
|
||||
PxcNpContext() :
|
||||
mNpMemBlockPool (mScratchAllocator),
|
||||
mMeshContactMargin (0.0f),
|
||||
mToleranceLength (0.0f),
|
||||
mCreateContactStream (false),
|
||||
mContactStreamPool (NULL),
|
||||
mPatchStreamPool (NULL),
|
||||
mForceAndIndiceStreamPool(NULL),
|
||||
mMaterialManager (NULL)
|
||||
{
|
||||
}
|
||||
|
||||
PxcScratchAllocator mScratchAllocator;
|
||||
PxcNpMemBlockPool mNpMemBlockPool;
|
||||
PxReal mMeshContactMargin;
|
||||
PxReal mToleranceLength;
|
||||
Cm::RenderBuffer mRenderBuffer;
|
||||
bool mCreateContactStream; // flag to enforce that contacts are stored persistently per workunit. Used for PVD.
|
||||
PxcDataStreamPool* mContactStreamPool;
|
||||
PxcDataStreamPool* mPatchStreamPool;
|
||||
PxcDataStreamPool* mForceAndIndiceStreamPool;
|
||||
PxcDataStreamPool* mConstraintWriteBackStreamPool;
|
||||
PxsMaterialManager* mMaterialManager;
|
||||
|
||||
PX_FORCE_INLINE PxReal getToleranceLength() const { return mToleranceLength; }
|
||||
PX_FORCE_INLINE void setToleranceLength(PxReal x) { mToleranceLength = x; }
|
||||
PX_FORCE_INLINE PxReal getMeshContactMargin() const { return mMeshContactMargin; }
|
||||
PX_FORCE_INLINE void setMeshContactMargin(PxReal x) { mMeshContactMargin = x; }
|
||||
PX_FORCE_INLINE bool getCreateContactStream() { return mCreateContactStream; }
|
||||
|
||||
PX_FORCE_INLINE PxcNpMemBlockPool& getNpMemBlockPool() { return mNpMemBlockPool; }
|
||||
PX_FORCE_INLINE const PxcNpMemBlockPool& getNpMemBlockPool() const { return mNpMemBlockPool; }
|
||||
PX_FORCE_INLINE void setMaterialManager(PxsMaterialManager* m){ mMaterialManager = m; }
|
||||
PX_FORCE_INLINE PxsMaterialManager* getMaterialManager() const { return mMaterialManager; }
|
||||
|
||||
Cm::RenderOutput getRenderOutput() { return Cm::RenderOutput(mRenderBuffer); }
|
||||
};
|
||||
|
||||
class PxcNpThreadContext : public PxcThreadCoherentCache<PxcNpThreadContext, PxcNpContext>::EntryBase
|
||||
{
|
||||
PX_NOCOPY(PxcNpThreadContext)
|
||||
public:
|
||||
PxcNpThreadContext(PxcNpContext* params);
|
||||
~PxcNpThreadContext();
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
void clearStats();
|
||||
#endif
|
||||
|
||||
PX_FORCE_INLINE void setCreateContactStream(bool to) { mCreateContactStream = to; }
|
||||
|
||||
PX_FORCE_INLINE void addLocalNewTouchCount(PxU32 newTouchCMCount) { mLocalNewTouchCount += newTouchCMCount; }
|
||||
PX_FORCE_INLINE void addLocalLostTouchCount(PxU32 lostTouchCMCount) { mLocalLostTouchCount += lostTouchCMCount; }
|
||||
PX_FORCE_INLINE PxU32 getLocalNewTouchCount() const { return mLocalNewTouchCount; }
|
||||
PX_FORCE_INLINE PxU32 getLocalLostTouchCount() const { return mLocalLostTouchCount; }
|
||||
|
||||
PX_FORCE_INLINE void addLocalFoundPatchCount(PxU32 foundPatchCount) { mLocalFoundPatchCount += foundPatchCount; }
|
||||
PX_FORCE_INLINE void addLocalLostPatchCount(PxU32 lostPatchCount) { mLocalLostPatchCount += lostPatchCount; }
|
||||
PX_FORCE_INLINE PxU32 getLocalFoundPatchCount() const { return mLocalFoundPatchCount; }
|
||||
PX_FORCE_INLINE PxU32 getLocalLostPatchCount() const { return mLocalLostPatchCount; }
|
||||
|
||||
PX_FORCE_INLINE Cm::BitMap& getLocalChangeTouch() { return mLocalChangeTouch; }
|
||||
|
||||
PX_FORCE_INLINE Cm::BitMap& getLocalPatchChangeMap() { return mLocalPatchCountChange; }
|
||||
|
||||
void reset(PxU32 cmCount);
|
||||
// debugging
|
||||
Cm::RenderOutput mRenderOutput;
|
||||
|
||||
// dsequeira: Need to think about this block pool allocation a bit more. Ideally we'd be
|
||||
// taking blocks from a single pool, except that we want to be able to selectively reclaim
|
||||
// blocks if the user needs to defragment, depending on which artifacts they're willing
|
||||
// to tolerate, such that the blocks we don't reclaim are contiguous.
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
PxU32 mDiscreteContactPairs [PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT];
|
||||
PxU32 mModifiedContactPairs [PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT];
|
||||
#endif
|
||||
PxcContactBlockStream mContactBlockStream; // constraint block pool
|
||||
PxcNpCacheStreamPair mNpCacheStreamPair; // narrow phase pairwise data cache
|
||||
|
||||
// Everything below here is scratch state. Most of it can even overlap.
|
||||
|
||||
// temporary contact buffer
|
||||
Gu::ContactBuffer mContactBuffer;
|
||||
|
||||
PX_ALIGN(16, Gu::MultiplePersistentContactManifold mTempManifold);
|
||||
|
||||
Gu::NarrowPhaseParams mNarrowPhaseParams;
|
||||
|
||||
// DS: this stuff got moved here from the PxcNpPairContext. As Pierre says:
|
||||
////////// PT: those members shouldn't be there in the end, it's not necessary
|
||||
Ps::Array<Sc::BodySim*> mBodySimPool;
|
||||
PxsTransformCache* mTransformCache;
|
||||
PxReal* mContactDistance;
|
||||
bool mPCM;
|
||||
bool mContactCache;
|
||||
bool mCreateContactStream; // flag to enforce that contacts are stored persistently per workunit. Used for PVD.
|
||||
bool mCreateAveragePoint; // flag to enforce whether we create average points
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
PxU32 mCompressedCacheSize;
|
||||
PxU32 mNbDiscreteContactPairsWithCacheHits;
|
||||
PxU32 mNbDiscreteContactPairsWithContacts;
|
||||
#endif
|
||||
PxReal mDt; // AP: still needed for ccd
|
||||
PxU32 mCCDPass;
|
||||
PxU32 mCCDFaceIndex;
|
||||
|
||||
PxU32 mMaxPatches;
|
||||
//PxU32 mTotalContactCount;
|
||||
PxU32 mTotalCompressedCacheSize;
|
||||
//PxU32 mTotalPatchCount;
|
||||
|
||||
PxcDataStreamPool* mContactStreamPool;
|
||||
PxcDataStreamPool* mPatchStreamPool;
|
||||
PxcDataStreamPool* mForceAndIndiceStreamPool; //this stream is used to store the force buffer and triangle index if we are performing mesh/heightfield contact gen
|
||||
PxcDataStreamPool* mConstraintWriteBackStreamPool;
|
||||
PxsMaterialManager* mMaterialManager;
|
||||
private:
|
||||
// change touch handling.
|
||||
Cm::BitMap mLocalChangeTouch;
|
||||
Cm::BitMap mLocalPatchCountChange;
|
||||
PxU32 mLocalNewTouchCount;
|
||||
PxU32 mLocalLostTouchCount;
|
||||
PxU32 mLocalFoundPatchCount;
|
||||
PxU32 mLocalLostPatchCount;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
155
physx/source/lowlevel/common/include/pipeline/PxcNpWorkUnit.h
Normal file
155
physx/source/lowlevel/common/include/pipeline/PxcNpWorkUnit.h
Normal file
@ -0,0 +1,155 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#ifndef PXC_NPWORKUNIT_H
|
||||
#define PXC_NPWORKUNIT_H
|
||||
|
||||
#include "PxcNpThreadContext.h"
|
||||
#include "PxcMaterialMethodImpl.h"
|
||||
#include "PxcNpCache.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
struct PxsRigidCore;
|
||||
struct PxsShapeCore;
|
||||
|
||||
struct PxcNpWorkUnitFlag
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eOUTPUT_CONTACTS = 1,
|
||||
eOUTPUT_CONSTRAINTS = 2,
|
||||
eDISABLE_STRONG_FRICTION = 4,
|
||||
eARTICULATION_BODY0 = 8,
|
||||
eARTICULATION_BODY1 = 16,
|
||||
eDYNAMIC_BODY0 = 32,
|
||||
eDYNAMIC_BODY1 = 64,
|
||||
eMODIFIABLE_CONTACT = 128,
|
||||
eFORCE_THRESHOLD = 256,
|
||||
eDETECT_DISCRETE_CONTACT = 512,
|
||||
eHAS_KINEMATIC_ACTOR = 1024,
|
||||
eDISABLE_RESPONSE = 2048,
|
||||
eDETECT_CCD_CONTACTS = 4096
|
||||
};
|
||||
};
|
||||
|
||||
struct PxcNpWorkUnitStatusFlag
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eHAS_NO_TOUCH = (1 << 0),
|
||||
eHAS_TOUCH = (1 << 1),
|
||||
//eHAS_SOLVER_CONSTRAINTS = (1 << 2),
|
||||
eREQUEST_CONSTRAINTS = (1 << 3),
|
||||
eHAS_CCD_RETOUCH = (1 << 4), // Marks pairs that are touching at a CCD pass and were touching at discrete collision or at a previous CCD pass already
|
||||
// but we can not tell whether they lost contact in a pass before. We send them as pure eNOTIFY_TOUCH_CCD events to the
|
||||
// contact report callback if requested.
|
||||
eDIRTY_MANAGER = (1 << 5),
|
||||
eREFRESHED_WITH_TOUCH = (1 << 6),
|
||||
eTOUCH_KNOWN = eHAS_NO_TOUCH | eHAS_TOUCH // The touch status is known (if narrowphase never ran for a pair then no flag will be set)
|
||||
};
|
||||
};
|
||||
|
||||
// PT: TODO: fix the inconsistent namings (mXXX) in this class
|
||||
struct PxcNpWorkUnit
|
||||
{
|
||||
const PxsRigidCore* rigidCore0; // INPUT //4 //8
|
||||
const PxsRigidCore* rigidCore1; // INPUT //8 //16
|
||||
|
||||
const PxsShapeCore* shapeCore0; // INPUT //12 //24
|
||||
const PxsShapeCore* shapeCore1; // INPUT //16 //32
|
||||
|
||||
PxU8* ccdContacts; // OUTPUT //20 //40
|
||||
|
||||
PxU8* frictionDataPtr; // INOUT //24 //48
|
||||
|
||||
PxU16 flags; // INPUT //26 //50
|
||||
PxU8 frictionPatchCount; // INOUT //27 //51
|
||||
PxU8 statusFlags; // OUTPUT (see PxcNpWorkUnitStatusFlag) //28 //52
|
||||
|
||||
PxU8 dominance0; // INPUT //29 //53
|
||||
PxU8 dominance1; // INPUT //30 //54
|
||||
PxU8 geomType0; // INPUT //31 //55
|
||||
PxU8 geomType1; // INPUT //32 //56
|
||||
|
||||
PxU32 index; // INPUT //36 //60
|
||||
|
||||
PxReal restDistance; // INPUT //40 //64
|
||||
|
||||
PxU32 mTransformCache0; // //44 //68
|
||||
PxU32 mTransformCache1; // //48 //72
|
||||
|
||||
PxU32 mEdgeIndex; //inout the island gen edge index //52 //76
|
||||
PxU32 mNpIndex; //INPUT //56 //80
|
||||
|
||||
PxReal mTorsionalPatchRadius; //60 //84
|
||||
PxReal mMinTorsionalPatchRadius; //64 //88
|
||||
};
|
||||
|
||||
/*
|
||||
* A struct to record the number of work units a particular constraint pointer references.
|
||||
* This is created at the beginning of the constriant data and is used to bypass constraint preparation when the
|
||||
* bodies are not moving a lot. In this case, we can recycle the constraints and save ourselves some cycles.
|
||||
*/
|
||||
struct PxcNpWorkUnitBatch
|
||||
{
|
||||
PxcNpWorkUnit* mUnits[4];
|
||||
PxU32 mSize;
|
||||
};
|
||||
|
||||
//#if !defined(PX_P64)
|
||||
//PX_COMPILE_TIME_ASSERT(0 == (sizeof(PxcNpWorkUnit) & 0x0f));
|
||||
//#endif
|
||||
|
||||
PX_FORCE_INLINE void PxcNpWorkUnitClearContactState(PxcNpWorkUnit& n)
|
||||
{
|
||||
n.ccdContacts = NULL;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void PxcNpWorkUnitClearCachedState(PxcNpWorkUnit& n)
|
||||
{
|
||||
n.frictionDataPtr = 0;
|
||||
n.frictionPatchCount = 0;
|
||||
n.ccdContacts = NULL;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void PxcNpWorkUnitClearFrictionCachedState(PxcNpWorkUnit& n)
|
||||
{
|
||||
n.frictionDataPtr = 0;
|
||||
n.frictionPatchCount = 0;
|
||||
n.ccdContacts = NULL;
|
||||
}
|
||||
|
||||
#if !defined(PX_P64)
|
||||
//PX_COMPILE_TIME_ASSERT(sizeof(PxcNpWorkUnit)==128);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
138
physx/source/lowlevel/common/include/utils/PxcScratchAllocator.h
Normal file
138
physx/source/lowlevel/common/include/utils/PxcScratchAllocator.h
Normal file
@ -0,0 +1,138 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#ifndef PXC_SCRATCHALLOCATOR_H
|
||||
#define PXC_SCRATCHALLOCATOR_H
|
||||
|
||||
#include "foundation/PxAssert.h"
|
||||
#include "PxvConfig.h"
|
||||
#include "PsMutex.h"
|
||||
#include "PsArray.h"
|
||||
#include "PsAllocator.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxcScratchAllocator
|
||||
{
|
||||
PX_NOCOPY(PxcScratchAllocator)
|
||||
public:
|
||||
PxcScratchAllocator() : mStack(PX_DEBUG_EXP("PxcScratchAllocator")), mStart(NULL), mSize(0)
|
||||
{
|
||||
mStack.reserve(64);
|
||||
mStack.pushBack(0);
|
||||
}
|
||||
|
||||
void setBlock(void* addr, PxU32 size)
|
||||
{
|
||||
// if the stack is not empty then some scratch memory was not freed on the previous frame. That's
|
||||
// likely indicative of a problem, because when the scratch block is too small the memory will have
|
||||
// come from the heap
|
||||
|
||||
PX_ASSERT(mStack.size()==1);
|
||||
mStack.popBack();
|
||||
|
||||
mStart = reinterpret_cast<PxU8*>(addr);
|
||||
mSize = size;
|
||||
mStack.pushBack(mStart + size);
|
||||
}
|
||||
|
||||
void* allocAll(PxU32& size)
|
||||
{
|
||||
Ps::Mutex::ScopedLock lock(mLock);
|
||||
PX_ASSERT(mStack.size()>0);
|
||||
size = PxU32(mStack.back()-mStart);
|
||||
|
||||
if(size==0)
|
||||
return NULL;
|
||||
|
||||
mStack.pushBack(mStart);
|
||||
return mStart;
|
||||
}
|
||||
|
||||
|
||||
void* alloc(PxU32 requestedSize, bool fallBackToHeap = false)
|
||||
{
|
||||
requestedSize = (requestedSize+15)&~15;
|
||||
|
||||
Ps::Mutex::ScopedLock lock(mLock);
|
||||
PX_ASSERT(mStack.size()>=1);
|
||||
|
||||
PxU8* top = mStack.back();
|
||||
|
||||
if(top - mStart >= ptrdiff_t(requestedSize))
|
||||
{
|
||||
PxU8* addr = top - requestedSize;
|
||||
mStack.pushBack(addr);
|
||||
return addr;
|
||||
}
|
||||
|
||||
if(!fallBackToHeap)
|
||||
return NULL;
|
||||
|
||||
return PX_ALLOC(requestedSize, "Scratch Block Fallback");
|
||||
}
|
||||
|
||||
void free(void* addr)
|
||||
{
|
||||
PX_ASSERT(addr!=NULL);
|
||||
if(!isScratchAddr(addr))
|
||||
{
|
||||
PX_FREE(addr);
|
||||
return;
|
||||
}
|
||||
|
||||
Ps::Mutex::ScopedLock lock(mLock);
|
||||
PX_ASSERT(mStack.size()>1);
|
||||
|
||||
PxU32 i=mStack.size()-1;
|
||||
while(mStack[i]<addr)
|
||||
i--;
|
||||
|
||||
PX_ASSERT(mStack[i]==addr);
|
||||
mStack.remove(i);
|
||||
}
|
||||
|
||||
|
||||
bool isScratchAddr(void* addr) const
|
||||
{
|
||||
PxU8* a = reinterpret_cast<PxU8*>(addr);
|
||||
return a>= mStart && a<mStart+mSize;
|
||||
}
|
||||
|
||||
private:
|
||||
Ps::Mutex mLock;
|
||||
Ps::Array<PxU8*> mStack;
|
||||
PxU8* mStart;
|
||||
PxU32 mSize;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,150 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#ifndef PXC_THREADCOHERENTCACHE_H
|
||||
#define PXC_THREADCOHERENTCACHE_H
|
||||
|
||||
#include "PsMutex.h"
|
||||
#include "PsAllocator.h"
|
||||
#include "PsSList.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
class PxsContext;
|
||||
/*!
|
||||
Controls a pool of large objects which must be thread safe.
|
||||
Tries to return the object most recently used by the thread(for better cache coherancy).
|
||||
Assumes the object has a default contructor.
|
||||
|
||||
(Note the semantics are different to a pool because we dont want to construct/destroy each time
|
||||
an object is requested, which may be expensive).
|
||||
|
||||
TODO: add thread coherancy.
|
||||
*/
|
||||
template<class T, class Params>
|
||||
class PxcThreadCoherentCache : public Ps::AlignedAllocator<16, Ps::ReflectionAllocator<T> >
|
||||
{
|
||||
typedef Ps::AlignedAllocator<16, Ps::ReflectionAllocator<T> > Allocator;
|
||||
PX_NOCOPY(PxcThreadCoherentCache)
|
||||
public:
|
||||
|
||||
typedef Ps::SListEntry EntryBase;
|
||||
|
||||
PX_INLINE PxcThreadCoherentCache(Params* params, const Allocator& alloc = Allocator()) : Allocator(alloc), mParams(params)
|
||||
{
|
||||
}
|
||||
|
||||
PX_INLINE ~PxcThreadCoherentCache()
|
||||
{
|
||||
T* np = static_cast<T*>(root.pop());
|
||||
|
||||
while(np!=NULL)
|
||||
{
|
||||
np->~T();
|
||||
Allocator::deallocate(np);
|
||||
np = static_cast<T*>(root.pop());
|
||||
}
|
||||
}
|
||||
|
||||
PX_INLINE T* get()
|
||||
{
|
||||
T* rv = static_cast<T*>(root.pop());
|
||||
if(rv==NULL)
|
||||
{
|
||||
rv = reinterpret_cast<T*>(Allocator::allocate(sizeof(T), __FILE__, __LINE__));
|
||||
new (rv) T(mParams);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
PX_INLINE void put(T* item)
|
||||
{
|
||||
root.push(*item);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Ps::SList root;
|
||||
Params* mParams;
|
||||
|
||||
template<class T2, class P2>
|
||||
friend class PxcThreadCoherentCacheIterator;
|
||||
};
|
||||
|
||||
/*!
|
||||
Used to iterate over all objects controlled by the cache.
|
||||
|
||||
Note: The iterator flushes the cache(extracts all items on construction and adds them back on
|
||||
destruction so we can iterate the list in a safe manner).
|
||||
*/
|
||||
template<class T, class Params>
|
||||
class PxcThreadCoherentCacheIterator
|
||||
{
|
||||
public:
|
||||
PxcThreadCoherentCacheIterator(PxcThreadCoherentCache<T, Params>& cache) : mCache(cache)
|
||||
{
|
||||
mNext = cache.root.flush();
|
||||
mFirst = mNext;
|
||||
}
|
||||
~PxcThreadCoherentCacheIterator()
|
||||
{
|
||||
Ps::SListEntry* np = mFirst;
|
||||
while(np != NULL)
|
||||
{
|
||||
Ps::SListEntry* npNext = np->next();
|
||||
mCache.root.push(*np);
|
||||
np = npNext;
|
||||
}
|
||||
}
|
||||
|
||||
PX_INLINE T* getNext()
|
||||
{
|
||||
if(mNext == NULL)
|
||||
return NULL;
|
||||
|
||||
T* rv = static_cast<T*>(mNext);
|
||||
mNext = mNext->next();
|
||||
|
||||
return rv;
|
||||
}
|
||||
private:
|
||||
|
||||
PxcThreadCoherentCacheIterator<T, Params>& operator=(const PxcThreadCoherentCacheIterator<T, Params>&);
|
||||
PxcThreadCoherentCache<T, Params> &mCache;
|
||||
Ps::SListEntry* mNext;
|
||||
Ps::SListEntry* mFirst;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
393
physx/source/lowlevel/common/src/pipeline/PxcContactCache.cpp
Normal file
393
physx/source/lowlevel/common/src/pipeline/PxcContactCache.cpp
Normal file
@ -0,0 +1,393 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "PxcContactCache.h"
|
||||
#include "PxsContactManager.h"
|
||||
#include "PsUtilities.h"
|
||||
#include "PxcNpCache.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
//#define ENABLE_CONTACT_CACHE_STATS
|
||||
|
||||
#ifdef ENABLE_CONTACT_CACHE_STATS
|
||||
static PxU32 gNbCalls;
|
||||
static PxU32 gNbHits;
|
||||
#endif
|
||||
|
||||
void PxcClearContactCacheStats()
|
||||
{
|
||||
#ifdef ENABLE_CONTACT_CACHE_STATS
|
||||
gNbCalls = 0;
|
||||
gNbHits = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void PxcDisplayContactCacheStats()
|
||||
{
|
||||
#ifdef ENABLE_CONTACT_CACHE_STATS
|
||||
pxPrintf("%d|%d (%f)\n", gNbHits, gNbCalls, gNbCalls ? float(gNbHits)/float(gNbCalls) : 0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace physx
|
||||
{
|
||||
const bool g_CanUseContactCache[][PxGeometryType::eGEOMETRY_COUNT] =
|
||||
{
|
||||
//PxGeometryType::eSPHERE
|
||||
{
|
||||
false, //PxcContactSphereSphere
|
||||
false, //PxcContactSpherePlane
|
||||
true, //PxcContactSphereCapsule
|
||||
false, //PxcContactSphereBox
|
||||
true, //PxcContactSphereConvex
|
||||
true, //PxcContactSphereMesh
|
||||
true, //PxcContactSphereHeightField
|
||||
},
|
||||
|
||||
//PxGeometryType::ePLANE
|
||||
{
|
||||
false, //-
|
||||
false, //PxcInvalidContactPair
|
||||
true, //PxcContactPlaneCapsule
|
||||
true, //PxcContactPlaneBox
|
||||
true, //PxcContactPlaneConvex
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
},
|
||||
|
||||
//PxGeometryType::eCAPSULE
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
true, //PxcContactCapsuleCapsule
|
||||
true, //PxcContactCapsuleBox
|
||||
true, //PxcContactCapsuleConvex
|
||||
true, //PxcContactCapsuleMesh
|
||||
true, //PxcContactCapsuleHeightField
|
||||
},
|
||||
|
||||
//PxGeometryType::eBOX
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
true, //PxcContactBoxBox
|
||||
true, //PxcContactBoxConvex
|
||||
true, //PxcContactBoxMesh
|
||||
true, //PxcContactBoxHeightField
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXMESH
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
true, //PxcContactConvexConvex
|
||||
true, //PxcContactConvexMesh2
|
||||
true, //PxcContactConvexHeightField
|
||||
},
|
||||
|
||||
//PxGeometryType::eTRIANGLEMESH
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //PxcInvalidContactPair
|
||||
false, //PxcInvalidContactPair
|
||||
},
|
||||
|
||||
//PxGeometryType::eHEIGHTFIELD
|
||||
{
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //-
|
||||
false, //PxcInvalidContactPair
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void updateContact( Gu::ContactPoint& dst, const PxcLocalContactsCache& contactsData,
|
||||
const Cm::Matrix34& world0, const Cm::Matrix34& world1,
|
||||
const PxVec3& point, const PxVec3& normal, float separation)
|
||||
{
|
||||
const PxVec3 tmp0 = contactsData.mTransform0.transformInv(point);
|
||||
const PxVec3 worldpt0 = world0.transform(tmp0);
|
||||
|
||||
const PxVec3 tmp1 = contactsData.mTransform1.transformInv(point);
|
||||
const PxVec3 worldpt1 = world1.transform(tmp1);
|
||||
|
||||
const PxVec3 motion = worldpt0 - worldpt1;
|
||||
dst.normal = normal;
|
||||
dst.point = (worldpt0 + worldpt1)*0.5f;
|
||||
//dst.point = point;
|
||||
dst.separation = separation + motion.dot(normal);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void prefetchData128(PxU8* PX_RESTRICT ptr, PxU32 size)
|
||||
{
|
||||
// PT: always prefetch the cache line containing our address (which unfortunately won't be aligned to 128 most of the time)
|
||||
Ps::prefetchLine(ptr, 0);
|
||||
// PT: compute start offset of our data within its cache line
|
||||
const PxU32 startOffset = PxU32(size_t(ptr)&127);
|
||||
// PT: prefetch next cache line if needed
|
||||
if(startOffset+size>128)
|
||||
Ps::prefetchLine(ptr+128, 0);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxU8* outputToCache(PxU8* PX_RESTRICT bytes, const PxVec3& v)
|
||||
{
|
||||
*reinterpret_cast<PxVec3*>(bytes) = v;
|
||||
return bytes + sizeof(PxVec3);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxU8* outputToCache(PxU8* PX_RESTRICT bytes, PxReal v)
|
||||
{
|
||||
*reinterpret_cast<PxReal*>(bytes) = v;
|
||||
return bytes + sizeof(PxReal);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxU8* outputToCache(PxU8* PX_RESTRICT bytes, PxU32 v)
|
||||
{
|
||||
*reinterpret_cast<PxU32*>(bytes) = v;
|
||||
return bytes + sizeof(PxU32);
|
||||
}
|
||||
|
||||
//PxU32 gContactCache_NbCalls = 0;
|
||||
//PxU32 gContactCache_NbHits = 0;
|
||||
|
||||
static PX_FORCE_INLINE PxReal maxComponentDeltaPos(const PxTransform& t0, const PxTransform& t1)
|
||||
{
|
||||
PxReal delta = PxAbs(t0.p.x - t1.p.x);
|
||||
delta = PxMax(delta, PxAbs(t0.p.y - t1.p.y));
|
||||
delta = PxMax(delta, PxAbs(t0.p.z - t1.p.z));
|
||||
return delta;
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE PxReal maxComponentDeltaRot(const PxTransform& t0, const PxTransform& t1)
|
||||
{
|
||||
PxReal delta = PxAbs(t0.q.x - t1.q.x);
|
||||
delta = PxMax(delta, PxAbs(t0.q.y - t1.q.y));
|
||||
delta = PxMax(delta, PxAbs(t0.q.z - t1.q.z));
|
||||
delta = PxMax(delta, PxAbs(t0.q.w - t1.q.w));
|
||||
return delta;
|
||||
}
|
||||
|
||||
bool physx::PxcCacheLocalContacts( PxcNpThreadContext& context, Gu::Cache& pairContactCache,
|
||||
const PxTransform& tm0, const PxTransform& tm1,
|
||||
const PxcContactMethod conMethod,
|
||||
const Gu::GeometryUnion& shape0, const Gu::GeometryUnion& shape1)
|
||||
{
|
||||
const Gu::NarrowPhaseParams& params = context.mNarrowPhaseParams;
|
||||
|
||||
// gContactCache_NbCalls++;
|
||||
|
||||
if(pairContactCache.mCachedData)
|
||||
prefetchData128(pairContactCache.mCachedData, pairContactCache.mCachedSize);
|
||||
|
||||
ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
contactBuffer.reset();
|
||||
|
||||
PxcLocalContactsCache contactsData;
|
||||
PxU32 nbCachedBytes;
|
||||
const PxU8* cachedBytes = PxcNpCacheRead2(pairContactCache, contactsData, nbCachedBytes);
|
||||
|
||||
pairContactCache.mCachedData = NULL;
|
||||
pairContactCache.mCachedSize = 0;
|
||||
|
||||
#ifdef ENABLE_CONTACT_CACHE_STATS
|
||||
gNbCalls++;
|
||||
#endif
|
||||
|
||||
const PxU32 payloadSize = (sizeof(PxcLocalContactsCache)+3)&~3;
|
||||
|
||||
if(cachedBytes)
|
||||
{
|
||||
// PT: we used to store the relative TM but it's better to save memory and recompute it
|
||||
const PxTransform t0to1 = tm1.transformInv(tm0);
|
||||
const PxTransform relTM = contactsData.mTransform1.transformInv(contactsData.mTransform0);
|
||||
|
||||
const PxReal epsilon = 0.01f;
|
||||
if( maxComponentDeltaPos(t0to1, relTM)<epsilon*params.mToleranceLength
|
||||
&& maxComponentDeltaRot(t0to1, relTM)<epsilon)
|
||||
{
|
||||
// gContactCache_NbHits++;
|
||||
const PxU32 nbContacts = contactsData.mNbCachedContacts;
|
||||
|
||||
PxU8* ls = PxcNpCacheWriteInitiate(context.mNpCacheStreamPair, pairContactCache, contactsData, nbCachedBytes);
|
||||
prefetchData128(ls, (payloadSize + 4 + nbCachedBytes + 0xF)&~0xF);
|
||||
|
||||
contactBuffer.count = nbContacts;
|
||||
if(nbContacts)
|
||||
{
|
||||
Gu::ContactPoint* PX_RESTRICT dst = contactBuffer.contacts;
|
||||
|
||||
const Cm::Matrix34 world1(tm1);
|
||||
const Cm::Matrix34 world0(tm0);
|
||||
|
||||
const bool sameNormal = contactsData.mSameNormal;
|
||||
|
||||
const PxU8* contacts = reinterpret_cast<const PxU8*>(cachedBytes);
|
||||
const PxVec3* normal0 = NULL;
|
||||
for(PxU32 i=0;i<nbContacts;i++)
|
||||
{
|
||||
if(i!=nbContacts-1)
|
||||
Ps::prefetchLine(contacts, 128);
|
||||
|
||||
const PxVec3* cachedNormal;
|
||||
if(!i || !sameNormal)
|
||||
{
|
||||
cachedNormal = reinterpret_cast<const PxVec3*>(contacts); contacts += sizeof(PxVec3);
|
||||
normal0 = cachedNormal;
|
||||
}
|
||||
else
|
||||
{
|
||||
cachedNormal = normal0;
|
||||
}
|
||||
|
||||
const PxVec3* cachedPoint = reinterpret_cast<const PxVec3*>(contacts); contacts += sizeof(PxVec3);
|
||||
const PxReal* cachedPD = reinterpret_cast<const PxReal*>(contacts); contacts += sizeof(PxReal);
|
||||
|
||||
updateContact(*dst, contactsData, world0, world1, *cachedPoint, *cachedNormal, *cachedPD);
|
||||
|
||||
if(contactsData.mUseFaceIndices)
|
||||
{
|
||||
const PxU32* cachedIndex1 = reinterpret_cast<const PxU32*>(contacts); contacts += sizeof(PxU32);
|
||||
|
||||
dst->internalFaceIndex1 = *cachedIndex1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst->internalFaceIndex1 = PXC_CONTACT_NO_FACE_INDEX;
|
||||
}
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
if(ls)
|
||||
PxcNpCacheWriteFinalize(ls, contactsData, nbCachedBytes, cachedBytes);
|
||||
#ifdef ENABLE_CONTACT_CACHE_STATS
|
||||
gNbHits++;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// PT: if we reach this point we cached the contacts but we couldn't use them next frame
|
||||
// => waste of time and memory
|
||||
}
|
||||
}
|
||||
|
||||
conMethod(shape0, shape1, tm0, tm1, params, pairContactCache, context.mContactBuffer, &context.mRenderOutput);
|
||||
|
||||
//if(contactBuffer.count)
|
||||
{
|
||||
contactsData.mTransform0 = tm0;
|
||||
contactsData.mTransform1 = tm1;
|
||||
|
||||
PxU32 nbBytes = 0;
|
||||
const PxU8* bytes = NULL;
|
||||
const PxU32 count = contactBuffer.count;
|
||||
if(count)
|
||||
{
|
||||
const bool useFaceIndices = contactBuffer.contacts[0].internalFaceIndex1!=PXC_CONTACT_NO_FACE_INDEX;
|
||||
contactsData.mNbCachedContacts = Ps::to16(count);
|
||||
contactsData.mUseFaceIndices = useFaceIndices;
|
||||
|
||||
const Gu::ContactPoint* PX_RESTRICT srcContacts = contactBuffer.contacts;
|
||||
// PT: this loop should not be here. We should output the contacts directly compressed, as we used to.
|
||||
bool sameNormal = true;
|
||||
{
|
||||
const PxVec3 normal0 = srcContacts->normal;
|
||||
for(PxU32 i=1;i<count;i++)
|
||||
{
|
||||
if(srcContacts[i].normal!=normal0)
|
||||
{
|
||||
sameNormal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
contactsData.mSameNormal = sameNormal;
|
||||
|
||||
if(!sameNormal)
|
||||
{
|
||||
const PxU32 sizeof_CachedContactPoint = sizeof(PxVec3) + sizeof(PxVec3) + sizeof(PxReal);
|
||||
const PxU32 sizeof_CachedContactPointAndFaceIndices = sizeof_CachedContactPoint + sizeof(PxU32);
|
||||
const PxU32 sizeOfItem = useFaceIndices ? sizeof_CachedContactPointAndFaceIndices : sizeof_CachedContactPoint;
|
||||
nbBytes = count * sizeOfItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU32 sizeof_CachedContactPoint = sizeof(PxVec3) + sizeof(PxReal);
|
||||
const PxU32 sizeof_CachedContactPointAndFaceIndices = sizeof_CachedContactPoint + sizeof(PxU32);
|
||||
const PxU32 sizeOfItem = useFaceIndices ? sizeof_CachedContactPointAndFaceIndices : sizeof_CachedContactPoint;
|
||||
nbBytes = sizeof(PxVec3) + count * sizeOfItem;
|
||||
}
|
||||
PxU8* ls = PxcNpCacheWriteInitiate(context.mNpCacheStreamPair, pairContactCache, contactsData, nbBytes);
|
||||
if(ls)
|
||||
{
|
||||
*reinterpret_cast<PxcLocalContactsCache*>(ls) = contactsData;
|
||||
*reinterpret_cast<PxU32*>(ls+payloadSize) = nbBytes;
|
||||
bytes = ls+payloadSize+sizeof(PxU32);
|
||||
PxU8* dest = const_cast<PxU8*>(bytes);
|
||||
for(PxU32 i=0;i<count;i++)
|
||||
{
|
||||
if(!i || !sameNormal)
|
||||
dest = outputToCache(dest, srcContacts[i].normal);
|
||||
dest = outputToCache(dest, srcContacts[i].point);
|
||||
dest = outputToCache(dest, srcContacts[i].separation);
|
||||
if(useFaceIndices)
|
||||
{
|
||||
dest = outputToCache(dest, srcContacts[i].internalFaceIndex1);
|
||||
}
|
||||
}
|
||||
PX_ASSERT(size_t(dest) - size_t(bytes)==nbBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
contactsData.mNbCachedContacts = 0;
|
||||
PxcNpCacheWrite(context.mNpCacheStreamPair, pairContactCache, contactsData, 0, bytes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
contactsData.mNbCachedContacts = 0;
|
||||
contactsData.mUseFaceIndices = false;
|
||||
PxcNpCacheWrite(context.mNpCacheStreamPair, pairContactCache, contactsData, nbBytes, bytes);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -0,0 +1,265 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "geometry/PxGeometry.h"
|
||||
#include "PxcContactMethodImpl.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
static bool PxcInvalidContactPair (CONTACT_METHOD_ARGS_UNUSED) { return false; }
|
||||
|
||||
// PT: IMPORTANT: do NOT remove the indirection! Using the Gu functions directly in the table produces massive perf problems.
|
||||
static bool PxcContactSphereSphere (GU_CONTACT_METHOD_ARGS) { return contactSphereSphere(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactSphereCapsule (GU_CONTACT_METHOD_ARGS) { return contactSphereCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactSphereBox (GU_CONTACT_METHOD_ARGS) { return contactSphereBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactSpherePlane (GU_CONTACT_METHOD_ARGS) { return contactSpherePlane(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactSphereConvex (GU_CONTACT_METHOD_ARGS) { return contactCapsuleConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactSphereMesh (GU_CONTACT_METHOD_ARGS) { return contactSphereMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactSphereHeightField (GU_CONTACT_METHOD_ARGS) { return contactSphereHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactPlaneBox (GU_CONTACT_METHOD_ARGS) { return contactPlaneBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactPlaneCapsule (GU_CONTACT_METHOD_ARGS) { return contactPlaneCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactPlaneConvex (GU_CONTACT_METHOD_ARGS) { return contactPlaneConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactCapsuleCapsule (GU_CONTACT_METHOD_ARGS) { return contactCapsuleCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactCapsuleBox (GU_CONTACT_METHOD_ARGS) { return contactCapsuleBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactCapsuleConvex (GU_CONTACT_METHOD_ARGS) { return contactCapsuleConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactCapsuleMesh (GU_CONTACT_METHOD_ARGS) { return contactCapsuleMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactCapsuleHeightField(GU_CONTACT_METHOD_ARGS) { return contactCapsuleHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactBoxBox (GU_CONTACT_METHOD_ARGS) { return contactBoxBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactBoxConvex (GU_CONTACT_METHOD_ARGS) { return contactBoxConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactBoxMesh (GU_CONTACT_METHOD_ARGS) { return contactBoxMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactBoxHeightField (GU_CONTACT_METHOD_ARGS) { return contactBoxHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactConvexConvex (GU_CONTACT_METHOD_ARGS) { return contactConvexConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactConvexMesh (GU_CONTACT_METHOD_ARGS) { return contactConvexMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcContactConvexHeightField (GU_CONTACT_METHOD_ARGS) { return contactConvexHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
|
||||
static bool PxcPCMContactSphereSphere (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereSphere(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactSpherePlane (GU_CONTACT_METHOD_ARGS) { return pcmContactSpherePlane(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactSphereBox (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactSphereCapsule (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactSphereConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactSphereMesh (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactSphereHeightField (GU_CONTACT_METHOD_ARGS) { return pcmContactSphereHeightField(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactPlaneCapsule (GU_CONTACT_METHOD_ARGS) { return pcmContactPlaneCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactPlaneBox (GU_CONTACT_METHOD_ARGS) { return pcmContactPlaneBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactPlaneConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactPlaneConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactCapsuleCapsule (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactCapsuleBox (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactCapsuleConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactCapsuleMesh (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactCapsuleHeightField (GU_CONTACT_METHOD_ARGS) { return pcmContactCapsuleHeightField(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactBoxBox (GU_CONTACT_METHOD_ARGS) { return pcmContactBoxBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactBoxConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactBoxConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactBoxMesh (GU_CONTACT_METHOD_ARGS) { return pcmContactBoxMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactBoxHeightField (GU_CONTACT_METHOD_ARGS) { return pcmContactBoxHeightField(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactConvexConvex (GU_CONTACT_METHOD_ARGS) { return pcmContactConvexConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactConvexMesh (GU_CONTACT_METHOD_ARGS) { return pcmContactConvexMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
static bool PxcPCMContactConvexHeightField (GU_CONTACT_METHOD_ARGS) { return pcmContactConvexHeightField(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput); }
|
||||
|
||||
#define DYNAMIC_CONTACT_REGISTRATION(x) PxcInvalidContactPair
|
||||
//#define DYNAMIC_CONTACT_REGISTRATION(x) x
|
||||
|
||||
//Table of contact methods for different shape-type combinations
|
||||
PxcContactMethod g_ContactMethodTable[][PxGeometryType::eGEOMETRY_COUNT] =
|
||||
{
|
||||
//PxGeometryType::eSPHERE
|
||||
{
|
||||
PxcContactSphereSphere, //PxGeometryType::eSPHERE
|
||||
PxcContactSpherePlane, //PxGeometryType::ePLANE
|
||||
PxcContactSphereCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcContactSphereBox, //PxGeometryType::eBOX
|
||||
PxcContactSphereConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcContactSphereMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcContactSphereHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::ePLANE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
PxcInvalidContactPair, //PxGeometryType::ePLANE
|
||||
PxcContactPlaneCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcContactPlaneBox, //PxGeometryType::eBOX
|
||||
PxcContactPlaneConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
//PxGeometryType::eCAPSULE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
PxcContactCapsuleCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcContactCapsuleBox, //PxGeometryType::eBOX
|
||||
PxcContactCapsuleConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcContactCapsuleMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcContactCapsuleHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eBOX
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
PxcContactBoxBox, //PxGeometryType::eBOX
|
||||
PxcContactBoxConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcContactBoxMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcContactBoxHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
PxcContactConvexConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcContactConvexMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcContactConvexHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eTRIANGLEMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
//PxGeometryType::eHEIGHTFIELD
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
//#if PERSISTENT_CONTACT_MANIFOLD
|
||||
//Table of contact methods for different shape-type combinations
|
||||
PxcContactMethod g_PCMContactMethodTable[][PxGeometryType::eGEOMETRY_COUNT] =
|
||||
{
|
||||
//PxGeometryType::eSPHERE
|
||||
{
|
||||
PxcPCMContactSphereSphere, //PxGeometryType::eSPHERE
|
||||
PxcPCMContactSpherePlane, //PxGeometryType::ePLANE
|
||||
PxcPCMContactSphereCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcPCMContactSphereBox, //PxGeometryType::eBOX
|
||||
PxcPCMContactSphereConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcPCMContactSphereMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcPCMContactSphereHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::ePLANE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
PxcInvalidContactPair, //PxGeometryType::ePLANE
|
||||
PxcPCMContactPlaneCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcPCMContactPlaneBox, //PxGeometryType::eBOX
|
||||
PxcPCMContactPlaneConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
//PxGeometryType::eCAPSULE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
PxcPCMContactCapsuleCapsule, //PxGeometryType::eCAPSULE
|
||||
PxcPCMContactCapsuleBox, //PxGeometryType::eBOX
|
||||
PxcPCMContactCapsuleConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcPCMContactCapsuleMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcPCMContactCapsuleHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eBOX
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
PxcPCMContactBoxBox, //PxGeometryType::eBOX
|
||||
PxcPCMContactBoxConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcPCMContactBoxMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcPCMContactBoxHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
PxcPCMContactConvexConvex, //PxGeometryType::eCONVEXMESH
|
||||
PxcPCMContactConvexMesh, //PxGeometryType::eTRIANGLEMESH
|
||||
DYNAMIC_CONTACT_REGISTRATION(PxcPCMContactConvexHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eTRIANGLEMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
//PxGeometryType::eHEIGHTFIELD
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
};
|
||||
|
||||
void PxvRegisterHeightFields()
|
||||
{
|
||||
g_ContactMethodTable[PxGeometryType::eSPHERE][PxGeometryType::eHEIGHTFIELD] = PxcContactSphereHeightField;
|
||||
g_ContactMethodTable[PxGeometryType::eCAPSULE][PxGeometryType::eHEIGHTFIELD] = PxcContactCapsuleHeightField;
|
||||
g_ContactMethodTable[PxGeometryType::eBOX][PxGeometryType::eHEIGHTFIELD] = PxcContactBoxHeightField;
|
||||
g_ContactMethodTable[PxGeometryType::eCONVEXMESH][PxGeometryType::eHEIGHTFIELD] = PxcContactConvexHeightField;
|
||||
|
||||
g_PCMContactMethodTable[PxGeometryType::eSPHERE][PxGeometryType::eHEIGHTFIELD] = PxcPCMContactSphereHeightField;
|
||||
g_PCMContactMethodTable[PxGeometryType::eCAPSULE][PxGeometryType::eHEIGHTFIELD] = PxcPCMContactCapsuleHeightField;
|
||||
g_PCMContactMethodTable[PxGeometryType::eBOX][PxGeometryType::eHEIGHTFIELD] = PxcPCMContactBoxHeightField;
|
||||
g_PCMContactMethodTable[PxGeometryType::eCONVEXMESH][PxGeometryType::eHEIGHTFIELD] = PxcPCMContactConvexHeightField;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "geometry/PxTriangleMesh.h"
|
||||
|
||||
#include "PxvGeometry.h"
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "PxcNpThreadContext.h"
|
||||
#include "GuHeightField.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
namespace physx
|
||||
{
|
||||
bool PxcGetMaterialShapeHeightField(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo);
|
||||
bool PxcGetMaterialHeightField(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo);
|
||||
PxU32 GetMaterialIndex(const Gu::HeightFieldData* hfData, PxU32 triangleIndex);
|
||||
}
|
||||
|
||||
physx::PxU32 physx::GetMaterialIndex(const Gu::HeightFieldData* hfData, PxU32 triangleIndex)
|
||||
{
|
||||
const PxU32 sampleIndex = triangleIndex >> 1;
|
||||
const bool isFirstTriangle = (triangleIndex & 0x1) == 0;
|
||||
|
||||
//get sample
|
||||
const PxHeightFieldSample* hf = &hfData->samples[sampleIndex];
|
||||
return isFirstTriangle ? hf->materialIndex0 : hf->materialIndex1;
|
||||
}
|
||||
|
||||
bool physx::PxcGetMaterialHeightField(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
PX_ASSERT(index == 1);
|
||||
PX_UNUSED(index);
|
||||
const ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
const PxHeightFieldGeometryLL& hfGeom = shape->geometry.get<const PxHeightFieldGeometryLL>();
|
||||
if(hfGeom.materials.numIndices <= 1)
|
||||
{
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = shape->materialIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU16* materialIndices = hfGeom.materials.indices;
|
||||
|
||||
const Gu::HeightFieldData* hf = hfGeom.heightFieldData;
|
||||
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
const Gu::ContactPoint& contact = contactBuffer.contacts[i];
|
||||
const PxU32 localMaterialIndex = GetMaterialIndex(hf, contact.internalFaceIndex1);
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = materialIndices[localMaterialIndex];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool physx::PxcGetMaterialShapeHeightField(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
const ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
const PxHeightFieldGeometryLL& hfGeom = shape1->geometry.get<const PxHeightFieldGeometryLL>();
|
||||
if(hfGeom.materials.numIndices <= 1)
|
||||
{
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
|
||||
materialInfo[i].mMaterialIndex1 = shape1->materialIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU16* materialIndices = hfGeom.materials.indices;
|
||||
|
||||
const Gu::HeightFieldData* hf = hfGeom.heightFieldData;
|
||||
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
const Gu::ContactPoint& contact = contactBuffer.contacts[i];
|
||||
materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
|
||||
//contact.featureIndex0 = shape0->materialIndex;
|
||||
const PxU32 localMaterialIndex = GetMaterialIndex(hf, contact.internalFaceIndex1);
|
||||
//contact.featureIndex1 = materialIndices[localMaterialIndex];
|
||||
PX_ASSERT(localMaterialIndex<hfGeom.materials.numIndices);
|
||||
materialInfo[i].mMaterialIndex1 = materialIndices[localMaterialIndex];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
108
physx/source/lowlevel/common/src/pipeline/PxcMaterialMesh.cpp
Normal file
108
physx/source/lowlevel/common/src/pipeline/PxcMaterialMesh.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "geometry/PxTriangleMesh.h"
|
||||
|
||||
#include "PxvGeometry.h"
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "PxcNpThreadContext.h"
|
||||
#include "GuHeightField.h"
|
||||
#include "GuTriangleMesh.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
namespace physx
|
||||
{
|
||||
bool PxcGetMaterialShapeMesh(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo);
|
||||
bool PxcGetMaterialMesh(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo);
|
||||
}
|
||||
|
||||
bool physx::PxcGetMaterialMesh(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
PX_ASSERT(index == 1);
|
||||
PX_UNUSED(index);
|
||||
ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
const PxTriangleMeshGeometryLL& shapeMesh = shape->geometry.get<const PxTriangleMeshGeometryLL>();
|
||||
if(shapeMesh.materials.numIndices <= 1)
|
||||
{
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = shape->materialIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
|
||||
Gu::ContactPoint& contact = contactBuffer.contacts[i];
|
||||
const PxU16* eaMaterialIndices = shapeMesh.materialIndices;
|
||||
|
||||
const PxU32 localMaterialIndex = eaMaterialIndices[contact.internalFaceIndex1];//shapeMesh.triangleMesh->getTriangleMaterialIndex(contact.featureIndex1);
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = shapeMesh.materials.indices[localMaterialIndex];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool physx::PxcGetMaterialShapeMesh(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
|
||||
ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
const PxTriangleMeshGeometryLL& shapeMesh = shape1->geometry.get<const PxTriangleMeshGeometryLL>();
|
||||
// const Gu::TriangleMesh* meshData = shapeMesh.meshData;
|
||||
if(shapeMesh.materials.numIndices <= 1)
|
||||
{
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
|
||||
materialInfo[i].mMaterialIndex1 = shape1->materialIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
|
||||
Gu::ContactPoint& contact = contactBuffer.contacts[i];
|
||||
//contact.featureIndex0 = shape0->materialIndex;
|
||||
materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
|
||||
const PxU16* eaMaterialIndices = shapeMesh.materialIndices;
|
||||
|
||||
const PxU32 localMaterialIndex = eaMaterialIndices[contact.internalFaceIndex1];//shapeMesh.triangleMesh->getTriangleMaterialIndex(contact.featureIndex1);
|
||||
//contact.featureIndex1 = shapeMesh.materials.indices[localMaterialIndex];
|
||||
materialInfo[i].mMaterialIndex1 = shapeMesh.materials.indices[localMaterialIndex];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -0,0 +1,140 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#include "geometry/PxGeometry.h"
|
||||
#include "PxcMaterialMethodImpl.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
bool PxcGetMaterialShapeShape (MATERIAL_METHOD_ARGS);
|
||||
bool PxcGetMaterialShapeMesh (MATERIAL_METHOD_ARGS);
|
||||
bool PxcGetMaterialShapeHeightField (MATERIAL_METHOD_ARGS);
|
||||
bool PxcGetMaterialShape (SINGLE_MATERIAL_METHOD_ARGS);
|
||||
bool PxcGetMaterialMesh (SINGLE_MATERIAL_METHOD_ARGS);
|
||||
bool PxcGetMaterialHeightField (SINGLE_MATERIAL_METHOD_ARGS);
|
||||
|
||||
|
||||
PxcGetSingleMaterialMethod g_GetSingleMaterialMethodTable[PxGeometryType::eGEOMETRY_COUNT] =
|
||||
{
|
||||
PxcGetMaterialShape, //PxGeometryType::eSPHERE
|
||||
PxcGetMaterialShape, //PxGeometryType::ePLANE
|
||||
PxcGetMaterialShape, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
|
||||
};
|
||||
|
||||
//Table of contact methods for different shape-type combinations
|
||||
PxcGetMaterialMethod g_GetMaterialMethodTable[][PxGeometryType::eGEOMETRY_COUNT] =
|
||||
{
|
||||
|
||||
//PxGeometryType::eSPHERE
|
||||
{
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eSPHERE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::ePLANE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
|
||||
},
|
||||
|
||||
//PxGeometryType::ePLANE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
0, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
//PxGeometryType::eCAPSULE
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eBOX
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eCONVEXMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
|
||||
PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
|
||||
PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
|
||||
},
|
||||
|
||||
//PxGeometryType::eTRIANGLEMESH
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
0, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
//PxGeometryType::eHEIGHTFIELD
|
||||
{
|
||||
0, //PxGeometryType::eSPHERE
|
||||
0, //PxGeometryType::ePLANE
|
||||
0, //PxGeometryType::eCAPSULE
|
||||
0, //PxGeometryType::eBOX
|
||||
0, //PxGeometryType::eCONVEXMESH
|
||||
0, //PxGeometryType::eTRIANGLEMESH
|
||||
0, //PxGeometryType::eHEIGHTFIELD
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "geometry/PxTriangleMesh.h"
|
||||
|
||||
#include "PxvGeometry.h"
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "PxcNpThreadContext.h"
|
||||
#include "GuHeightField.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
namespace physx
|
||||
{
|
||||
bool PxcGetMaterialShape(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
(&materialInfo[i].mMaterialIndex0)[index] = shape->materialIndex;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PxcGetMaterialShapeShape(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
|
||||
{
|
||||
ContactBuffer& contactBuffer = context.mContactBuffer;
|
||||
for(PxU32 i=0; i< contactBuffer.count; ++i)
|
||||
{
|
||||
materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
|
||||
materialInfo[i].mMaterialIndex1 = shape1->materialIndex;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
445
physx/source/lowlevel/common/src/pipeline/PxcNpBatch.cpp
Normal file
445
physx/source/lowlevel/common/src/pipeline/PxcNpBatch.cpp
Normal file
@ -0,0 +1,445 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#include "geometry/PxTriangleMesh.h"
|
||||
|
||||
#include "PxcNpBatch.h"
|
||||
#include "PxcNpWorkUnit.h"
|
||||
#include "PxcContactCache.h"
|
||||
#include "PxcMaterialMethodImpl.h"
|
||||
#include "PxcNpContactPrepShared.h"
|
||||
#include "PxvDynamics.h" // for PxsBodyCore
|
||||
#include "PxvGeometry.h" // for PxsShapeCore
|
||||
#include "CmFlushPool.h"
|
||||
#include "CmTask.h"
|
||||
#include "PxsContactManager.h"
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "PxsTransformCache.h"
|
||||
#include "PxsContactManagerState.h"
|
||||
#include "GuGeometryUnion.h"
|
||||
#include "GuPersistentContactManifold.h"
|
||||
#include "PsFoundation.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
|
||||
static void startContacts(PxsContactManagerOutput& output, PxcNpThreadContext& context)
|
||||
{
|
||||
context.mContactBuffer.reset();
|
||||
|
||||
output.contactForces = NULL;
|
||||
output.contactPatches = NULL;
|
||||
output.contactPoints = NULL;
|
||||
output.nbContacts = 0;
|
||||
output.nbPatches = 0;
|
||||
output.statusFlag = 0;
|
||||
}
|
||||
|
||||
static void flipContacts(PxcNpThreadContext& threadContext, PxsMaterialInfo* PX_RESTRICT materialInfo)
|
||||
{
|
||||
ContactBuffer& buffer = threadContext.mContactBuffer;
|
||||
for(PxU32 i=0; i<buffer.count; ++i)
|
||||
{
|
||||
Gu::ContactPoint& contactPoint = buffer.contacts[i];
|
||||
contactPoint.normal = -contactPoint.normal;
|
||||
Ps::swap(materialInfo[i].mMaterialIndex0, materialInfo[i].mMaterialIndex1);
|
||||
}
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void updateDiscreteContactStats(PxcNpThreadContext& context, PxGeometryType::Enum type0, PxGeometryType::Enum type1)
|
||||
{
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
PX_ASSERT(type0<=type1);
|
||||
context.mDiscreteContactPairs[type0][type1]++;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool copyBuffers(PxsContactManagerOutput& cmOutput, Gu::Cache& cache, PxcNpThreadContext& context, const bool useContactCache, const bool isMeshType)
|
||||
{
|
||||
bool ret = false;
|
||||
//Copy the contact stream from previous buffer to current buffer...
|
||||
PxU32 oldSize = sizeof(PxContact) * cmOutput.nbContacts + sizeof(PxContactPatch)*cmOutput.nbPatches;
|
||||
if(oldSize)
|
||||
{
|
||||
ret = true;
|
||||
PxU8* oldPatches = cmOutput.contactPatches;
|
||||
PxU8* oldContacts = cmOutput.contactPoints;
|
||||
PxReal* oldForces = cmOutput.contactForces;
|
||||
|
||||
PxU32 forceSize = cmOutput.nbContacts * sizeof(PxReal);
|
||||
if(isMeshType)
|
||||
forceSize += cmOutput.nbContacts * sizeof(PxU32);
|
||||
|
||||
PxU8* PX_RESTRICT contactPatches = NULL;
|
||||
PxU8* PX_RESTRICT contactPoints = NULL;
|
||||
|
||||
PxReal* forceBuffer = NULL;
|
||||
|
||||
bool isOverflown = false;
|
||||
|
||||
//ML: if we are using contactStreamPool, which means we are running the GPU codepath
|
||||
if(context.mContactStreamPool)
|
||||
{
|
||||
const PxU32 patchSize = cmOutput.nbPatches * sizeof(PxContactPatch);
|
||||
const PxU32 contactSize = cmOutput.nbContacts * sizeof(PxContact);
|
||||
|
||||
PxU32 index = PxU32(Ps::atomicAdd(&context.mContactStreamPool->mSharedDataIndex, PxI32(contactSize)));
|
||||
|
||||
if(context.mContactStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Contact buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
contactPoints = context.mContactStreamPool->mDataStream + context.mContactStreamPool->mDataStreamSize - index;
|
||||
|
||||
const PxU32 patchIndex = PxU32(Ps::atomicAdd(&context.mPatchStreamPool->mSharedDataIndex, PxI32(patchSize)));
|
||||
|
||||
if(context.mPatchStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Patch buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
contactPatches = context.mPatchStreamPool->mDataStream + context.mPatchStreamPool->mDataStreamSize - patchIndex;
|
||||
|
||||
if(forceSize)
|
||||
{
|
||||
index = PxU32(Ps::atomicAdd(&context.mForceAndIndiceStreamPool->mSharedDataIndex, PxI32(forceSize)));
|
||||
|
||||
if(context.mForceAndIndiceStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Force buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
forceBuffer = reinterpret_cast<PxReal*>(context.mForceAndIndiceStreamPool->mDataStream + context.mForceAndIndiceStreamPool->mDataStreamSize - index);
|
||||
}
|
||||
|
||||
if(isOverflown)
|
||||
{
|
||||
contactPatches = NULL;
|
||||
contactPoints = NULL;
|
||||
forceBuffer = NULL;
|
||||
cmOutput.nbContacts = cmOutput.nbPatches = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PxMemCopy(contactPatches, oldPatches, patchSize);
|
||||
PxMemCopy(contactPoints, oldContacts, contactSize);
|
||||
if (isMeshType)
|
||||
{
|
||||
PxMemCopy(forceBuffer + cmOutput.nbContacts, oldForces + cmOutput.nbContacts, sizeof(PxU32) * cmOutput.nbContacts);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxU32 alignedOldSize = (oldSize + 0xf) & 0xfffffff0;
|
||||
|
||||
PxU8* data = context.mContactBlockStream.reserve(alignedOldSize + forceSize);
|
||||
if(forceSize)
|
||||
forceBuffer = reinterpret_cast<PxReal*>(data + alignedOldSize);
|
||||
|
||||
contactPatches = data;
|
||||
contactPoints = data + cmOutput.nbPatches * sizeof(PxContactPatch);
|
||||
|
||||
PxMemCopy(data, oldPatches, oldSize);
|
||||
if (isMeshType)
|
||||
{
|
||||
PxMemCopy(forceBuffer + cmOutput.nbContacts, oldForces + cmOutput.nbContacts, sizeof(PxU32) * cmOutput.nbContacts);
|
||||
}
|
||||
}
|
||||
|
||||
if(forceSize)
|
||||
PxMemZero(forceBuffer, forceSize);
|
||||
|
||||
cmOutput.contactPatches= contactPatches;
|
||||
cmOutput.contactPoints = contactPoints;
|
||||
cmOutput.contactForces = forceBuffer;
|
||||
}
|
||||
|
||||
if(cache.mCachedSize)
|
||||
{
|
||||
if(cache.isMultiManifold())
|
||||
{
|
||||
PX_ASSERT((cache.mCachedSize & 0xF) == 0);
|
||||
PxU8* newData = context.mNpCacheStreamPair.reserve(cache.mCachedSize);
|
||||
PX_ASSERT((reinterpret_cast<uintptr_t>(newData)& 0xF) == 0);
|
||||
PxMemCopy(newData, & cache.getMultipleManifold(), cache.mCachedSize);
|
||||
cache.setMultiManifold(newData);
|
||||
}
|
||||
else if(useContactCache)
|
||||
{
|
||||
//Copy cache information as well...
|
||||
const PxU8* cachedData = cache.mCachedData;
|
||||
PxU8* newData = context.mNpCacheStreamPair.reserve(PxU32(cache.mCachedSize + 0xf) & 0xfff0);
|
||||
PxMemCopy(newData, cachedData, cache.mCachedSize);
|
||||
cache.mCachedData = newData;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//ML: isMeshType is used in the GPU codepath. If the collision pair is mesh/heightfield vs primitives, we need to allocate enough memory for the mForceAndIndiceStreamPool in the threadContext.
|
||||
static bool finishContacts(const PxcNpWorkUnit& input, PxsContactManagerOutput& npOutput, PxcNpThreadContext& threadContext, PxsMaterialInfo* PX_RESTRICT pMaterials, const bool isMeshType)
|
||||
{
|
||||
ContactBuffer& buffer = threadContext.mContactBuffer;
|
||||
|
||||
PX_ASSERT((npOutput.statusFlag & PxsContactManagerStatusFlag::eTOUCH_KNOWN) != PxsContactManagerStatusFlag::eTOUCH_KNOWN);
|
||||
PxU8 statusFlags = PxU16(npOutput.statusFlag & (~PxsContactManagerStatusFlag::eTOUCH_KNOWN));
|
||||
if(buffer.count)
|
||||
statusFlags |= PxsContactManagerStatusFlag::eHAS_TOUCH;
|
||||
else
|
||||
statusFlags |= PxsContactManagerStatusFlag::eHAS_NO_TOUCH;
|
||||
|
||||
npOutput.nbContacts = Ps::to8(buffer.count);
|
||||
|
||||
if(!buffer.count)
|
||||
{
|
||||
npOutput.statusFlag = statusFlags;
|
||||
npOutput.nbContacts = 0;
|
||||
npOutput.nbPatches = 0;
|
||||
return true;
|
||||
}
|
||||
PX_ASSERT(buffer.count);
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
threadContext.mNbDiscreteContactPairsWithContacts++;
|
||||
#endif
|
||||
|
||||
npOutput.statusFlag = statusFlags;
|
||||
|
||||
PxU32 contactForceByteSize = buffer.count * sizeof(PxReal);
|
||||
|
||||
//Regardless of the flags, we need to now record the compressed contact stream
|
||||
|
||||
PxU16 compressedContactSize;
|
||||
|
||||
const bool createReports =
|
||||
input.flags & PxcNpWorkUnitFlag::eOUTPUT_CONTACTS
|
||||
|| threadContext.mCreateContactStream
|
||||
|| (input.flags & PxcNpWorkUnitFlag::eFORCE_THRESHOLD);
|
||||
|
||||
if((!isMeshType && !createReports))
|
||||
contactForceByteSize = 0;
|
||||
|
||||
bool res = (writeCompressedContact(buffer.contacts, buffer.count, &threadContext, npOutput.nbContacts, npOutput.contactPatches, npOutput.contactPoints, compressedContactSize,
|
||||
reinterpret_cast<PxReal*&>(npOutput.contactForces), contactForceByteSize, threadContext.mMaterialManager, ((input.flags & PxcNpWorkUnitFlag::eMODIFIABLE_CONTACT) != 0),
|
||||
false, pMaterials, npOutput.nbPatches, 0, NULL, NULL, threadContext.mCreateAveragePoint, threadContext.mContactStreamPool,
|
||||
threadContext.mPatchStreamPool, threadContext.mForceAndIndiceStreamPool, isMeshType) != 0);
|
||||
|
||||
//handle buffer overflow
|
||||
if(!npOutput.nbContacts)
|
||||
{
|
||||
PxU8 thisStatusFlags = PxU16(npOutput.statusFlag & (~PxsContactManagerStatusFlag::eTOUCH_KNOWN));
|
||||
thisStatusFlags |= PxsContactManagerStatusFlag::eHAS_NO_TOUCH;
|
||||
|
||||
npOutput.statusFlag = thisStatusFlags;
|
||||
npOutput.nbContacts = 0;
|
||||
npOutput.nbPatches = 0;
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
threadContext.mNbDiscreteContactPairsWithContacts--;
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<bool useContactCacheT>
|
||||
static PX_FORCE_INLINE bool checkContactsMustBeGenerated(PxcNpThreadContext& context, const PxcNpWorkUnit& input, Gu::Cache& cache, PxsContactManagerOutput& output,
|
||||
const PxsCachedTransform* cachedTransform0, const PxsCachedTransform* cachedTransform1,
|
||||
const bool flip, PxGeometryType::Enum type0, PxGeometryType::Enum type1)
|
||||
{
|
||||
PX_ASSERT(cachedTransform0->transform.isSane() && cachedTransform1->transform.isSane());
|
||||
|
||||
//ML : if user doesn't raise the eDETECT_DISCRETE_CONTACT, we should not generate contacts
|
||||
if(!(input.flags & PxcNpWorkUnitFlag::eDETECT_DISCRETE_CONTACT))
|
||||
return false;
|
||||
|
||||
if(!(output.statusFlag & PxcNpWorkUnitStatusFlag::eDIRTY_MANAGER) && !(input.flags & PxcNpWorkUnitFlag::eMODIFIABLE_CONTACT))
|
||||
{
|
||||
const PxU32 body0Dynamic = PxU32(input.flags & PxcNpWorkUnitFlag::eDYNAMIC_BODY0);
|
||||
const PxU32 body1Dynamic = PxU32(input.flags & PxcNpWorkUnitFlag::eDYNAMIC_BODY1);
|
||||
|
||||
const PxU32 active0 = PxU32(body0Dynamic && !cachedTransform0->isFrozen());
|
||||
const PxU32 active1 = PxU32(body1Dynamic && !cachedTransform1->isFrozen());
|
||||
|
||||
if(!(active0 || active1))
|
||||
{
|
||||
if(flip)
|
||||
Ps::swap(type0, type1);
|
||||
|
||||
const bool useContactCache = useContactCacheT ? context.mContactCache && g_CanUseContactCache[type0][type1] : false;
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
if(output.nbContacts)
|
||||
context.mNbDiscreteContactPairsWithContacts++;
|
||||
#endif
|
||||
const bool isMeshType = type1 > PxGeometryType::eCONVEXMESH;
|
||||
copyBuffers(output, cache, context, useContactCache, isMeshType);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
output.statusFlag &= (~PxcNpWorkUnitStatusFlag::eDIRTY_MANAGER);
|
||||
|
||||
const PxReal contactDist0 = context.mContactDistance[input.mTransformCache0];
|
||||
const PxReal contactDist1 = context.mContactDistance[input.mTransformCache1];
|
||||
//context.mNarrowPhaseParams.mContactDistance = shape0->contactOffset + shape1->contactOffset;
|
||||
context.mNarrowPhaseParams.mContactDistance = contactDist0 + contactDist1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool useLegacyCodepath>
|
||||
static PX_FORCE_INLINE void discreteNarrowPhase(PxcNpThreadContext& context, const PxcNpWorkUnit& input, Gu::Cache& cache, PxsContactManagerOutput& output)
|
||||
{
|
||||
PxGeometryType::Enum type0 = static_cast<PxGeometryType::Enum>(input.geomType0);
|
||||
PxGeometryType::Enum type1 = static_cast<PxGeometryType::Enum>(input.geomType1);
|
||||
|
||||
const bool flip = (type1<type0);
|
||||
|
||||
const PxsCachedTransform* cachedTransform0 = &context.mTransformCache->getTransformCache(input.mTransformCache0);
|
||||
const PxsCachedTransform* cachedTransform1 = &context.mTransformCache->getTransformCache(input.mTransformCache1);
|
||||
|
||||
if(!checkContactsMustBeGenerated<useLegacyCodepath>(context, input, cache, output, cachedTransform0, cachedTransform1, flip, type0, type1))
|
||||
return;
|
||||
|
||||
PxsShapeCore* shape0 = const_cast<PxsShapeCore*>(input.shapeCore0);
|
||||
PxsShapeCore* shape1 = const_cast<PxsShapeCore*>(input.shapeCore1);
|
||||
|
||||
if(flip)
|
||||
{
|
||||
Ps::swap(type0, type1);
|
||||
Ps::swap(shape0, shape1);
|
||||
Ps::swap(cachedTransform0, cachedTransform1);
|
||||
}
|
||||
|
||||
PxsMaterialInfo materialInfo[ContactBuffer::MAX_CONTACTS];
|
||||
|
||||
Gu::MultiplePersistentContactManifold& manifold = context.mTempManifold;
|
||||
bool isMultiManifold = false;
|
||||
|
||||
if(!useLegacyCodepath)
|
||||
{
|
||||
if(cache.isMultiManifold())
|
||||
{
|
||||
//We are using a multi-manifold. This is cached in a reduced npCache...
|
||||
isMultiManifold = true;
|
||||
uintptr_t address = uintptr_t(&cache.getMultipleManifold());
|
||||
manifold.fromBuffer(reinterpret_cast<PxU8*>(address));
|
||||
cache.setMultiManifold(&manifold);
|
||||
}
|
||||
else if(cache.isManifold())
|
||||
{
|
||||
void* address = reinterpret_cast<void*>(&cache.getManifold());
|
||||
Ps::prefetch(address);
|
||||
Ps::prefetch(address, 128);
|
||||
Ps::prefetch(address, 256);
|
||||
}
|
||||
}
|
||||
|
||||
updateDiscreteContactStats(context, type0, type1);
|
||||
|
||||
startContacts(output, context);
|
||||
|
||||
const PxTransform* tm0 = &cachedTransform0->transform;
|
||||
const PxTransform* tm1 = &cachedTransform1->transform;
|
||||
PX_ASSERT(tm0->isSane() && tm1->isSane());
|
||||
|
||||
if(useLegacyCodepath)
|
||||
{
|
||||
// PT: many cache misses here...
|
||||
|
||||
Ps::prefetchLine(shape1, 0); // PT: at least get rid of L2s for shape1
|
||||
|
||||
const PxcContactMethod conMethod = g_ContactMethodTable[type0][type1];
|
||||
PX_ASSERT(conMethod);
|
||||
|
||||
const bool useContactCache = context.mContactCache && g_CanUseContactCache[type0][type1];
|
||||
if(useContactCache)
|
||||
{
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
if(PxcCacheLocalContacts(context, cache, *tm0, *tm1, conMethod, shape0->geometry, shape1->geometry))
|
||||
context.mNbDiscreteContactPairsWithCacheHits++;
|
||||
#else
|
||||
PxcCacheLocalContacts(context, n.pairCache, *tm0, *tm1, conMethod, shape0->geometry, shape1->geometry);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
conMethod(shape0->geometry, shape1->geometry, *tm0, *tm1, context.mNarrowPhaseParams, cache, context.mContactBuffer, &context.mRenderOutput);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxcContactMethod conMethod = g_PCMContactMethodTable[type0][type1];
|
||||
PX_ASSERT(conMethod);
|
||||
|
||||
conMethod(shape0->geometry, shape1->geometry, *tm0, *tm1, context.mNarrowPhaseParams, cache, context.mContactBuffer, &context.mRenderOutput);
|
||||
}
|
||||
|
||||
const PxcGetMaterialMethod materialMethod = g_GetMaterialMethodTable[type0][type1];
|
||||
// PX_ASSERT(materialMethod);
|
||||
if(materialMethod)
|
||||
materialMethod(shape0, shape1, context, materialInfo);
|
||||
|
||||
if(flip)
|
||||
flipContacts(context, materialInfo);
|
||||
|
||||
if(!useLegacyCodepath)
|
||||
{
|
||||
if(isMultiManifold)
|
||||
{
|
||||
//Store the manifold back...
|
||||
const PxU32 size = (sizeof(MultiPersistentManifoldHeader) +
|
||||
manifold.mNumManifolds * sizeof(SingleManifoldHeader) +
|
||||
manifold.mNumTotalContacts * sizeof(Gu::CachedMeshPersistentContact));
|
||||
|
||||
PxU8* buffer = context.mNpCacheStreamPair.reserve(size);
|
||||
|
||||
PX_ASSERT((reinterpret_cast<uintptr_t>(buffer)& 0xf) == 0);
|
||||
manifold.toBuffer(buffer);
|
||||
cache.setMultiManifold(buffer);
|
||||
cache.mCachedSize = Ps::to16(size);
|
||||
}
|
||||
}
|
||||
|
||||
const bool isMeshType = type1 > PxGeometryType::eCONVEXMESH;
|
||||
finishContacts(input, output, context, materialInfo, isMeshType);
|
||||
}
|
||||
|
||||
void physx::PxcDiscreteNarrowPhase(PxcNpThreadContext& context, const PxcNpWorkUnit& input, Gu::Cache& cache, PxsContactManagerOutput& output)
|
||||
{
|
||||
discreteNarrowPhase<true>(context, input, cache, output);
|
||||
}
|
||||
|
||||
void physx::PxcDiscreteNarrowPhasePCM(PxcNpThreadContext& context, const PxcNpWorkUnit& input, Gu::Cache& cache, PxsContactManagerOutput& output)
|
||||
{
|
||||
discreteNarrowPhase<false>(context, input, cache, output);
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#include "PxcNpCacheStreamPair.h"
|
||||
#include "PsUserAllocated.h"
|
||||
#include "PxcNpMemBlockPool.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
void PxcNpCacheStreamPair::reset()
|
||||
{
|
||||
mBlock = NULL;
|
||||
mUsed = 0;
|
||||
}
|
||||
|
||||
PxcNpCacheStreamPair::PxcNpCacheStreamPair(PxcNpMemBlockPool& blockPool):
|
||||
mBlockPool(blockPool), mBlock(NULL), mUsed(0)
|
||||
{
|
||||
}
|
||||
|
||||
// reserve can fail and return null. Read should never fail
|
||||
PxU8* PxcNpCacheStreamPair::reserve(PxU32 size)
|
||||
{
|
||||
size = (size+15)&~15;
|
||||
|
||||
if(size>PxcNpMemBlock::SIZE)
|
||||
{
|
||||
return reinterpret_cast<PxU8*>(-1);
|
||||
}
|
||||
|
||||
if(mBlock == NULL || mUsed + size > PxcNpMemBlock::SIZE)
|
||||
{
|
||||
mBlock = mBlockPool.acquireNpCacheBlock();
|
||||
mUsed = 0;
|
||||
}
|
||||
|
||||
PxU8* ptr;
|
||||
if(mBlock == NULL)
|
||||
ptr = 0;
|
||||
else
|
||||
{
|
||||
ptr = mBlock->data+mUsed;
|
||||
mUsed += size;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@ -0,0 +1,554 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#include "PsMathUtils.h"
|
||||
#include "PxcNpWorkUnit.h"
|
||||
#include "PxvDynamics.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
|
||||
#include "PxsMaterialManager.h"
|
||||
#include "PxsMaterialCombiner.h"
|
||||
|
||||
#include "PxcNpContactPrepShared.h"
|
||||
#include "PsAtomic.h"
|
||||
#include "PxsContactManagerState.h"
|
||||
|
||||
#include "PsVecMath.h"
|
||||
using namespace physx;
|
||||
using namespace Ps::aos;
|
||||
|
||||
static PX_FORCE_INLINE void copyContactPoint(PxContact* PX_RESTRICT point, const Gu::ContactPoint* PX_RESTRICT cp)
|
||||
{
|
||||
// PT: TODO: consider moving "separation" right after "point" in both structures, to copy both at the same time.
|
||||
// point->contact = cp->point;
|
||||
const Vec4V contactV = V4LoadA(&cp->point.x); // PT: V4LoadA safe because 'point' is aligned.
|
||||
V4StoreU(contactV, &point->contact.x);
|
||||
|
||||
point->separation = cp->separation;
|
||||
}
|
||||
|
||||
struct StridePatch
|
||||
{
|
||||
PxU8 startIndex;
|
||||
PxU8 endIndex;
|
||||
PxU8 nextIndex;
|
||||
PxU8 totalCount;
|
||||
bool isRoot;
|
||||
};
|
||||
|
||||
PxU32 physx::writeCompressedContact(const Gu::ContactPoint* const PX_RESTRICT contactPoints, const PxU32 numContactPoints, PxcNpThreadContext* threadContext,
|
||||
PxU8& writtenContactCount, PxU8*& outContactPatches, PxU8*& outContactPoints, PxU16& compressedContactSize, PxReal*& outContactForces, PxU32 contactForceByteSize,
|
||||
const PxsMaterialManager* materialManager, bool hasModifiableContacts, bool forceNoResponse, PxsMaterialInfo* PX_RESTRICT pMaterial, PxU8& numPatches,
|
||||
PxU32 additionalHeaderSize, PxsConstraintBlockManager* manager, PxcConstraintBlockStream* blockStream, bool insertAveragePoint,
|
||||
PxcDataStreamPool* contactStreamPool, PxcDataStreamPool* patchStreamPool, PxcDataStreamPool* forceStreamPool, const bool isMeshType)
|
||||
{
|
||||
if(numContactPoints == 0)
|
||||
{
|
||||
writtenContactCount = 0;
|
||||
outContactPatches = NULL;
|
||||
outContactPoints = NULL;
|
||||
outContactForces = NULL;
|
||||
compressedContactSize = 0;
|
||||
numPatches = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Calculate the size of the contact buffer...
|
||||
PX_ALLOCA(strPatches, StridePatch, numContactPoints);
|
||||
|
||||
StridePatch* stridePatches = &strPatches[0];
|
||||
|
||||
PxU32 numStrideHeaders = 1;
|
||||
|
||||
/*const bool hasInternalFaceIndex = contactPoints[0].internalFaceIndex0 != PXC_CONTACT_NO_FACE_INDEX ||
|
||||
contactPoints[0].internalFaceIndex1 != PXC_CONTACT_NO_FACE_INDEX;*/
|
||||
const bool isModifiable = !forceNoResponse && hasModifiableContacts;
|
||||
|
||||
PxU32 totalUniquePatches = 1;
|
||||
|
||||
PxU32 totalContactPoints = numContactPoints;
|
||||
|
||||
PxU32 strideStart = 0;
|
||||
bool root = true;
|
||||
StridePatch* parentRootPatch = NULL;
|
||||
{
|
||||
const PxReal closeNormalThresh = PXC_SAME_NORMAL;
|
||||
//Go through and tag how many patches we have...
|
||||
PxVec3 normal = contactPoints[0].normal;
|
||||
PxU16 mat0 = pMaterial[0].mMaterialIndex0;
|
||||
PxU16 mat1 = pMaterial[0].mMaterialIndex1;
|
||||
|
||||
for(PxU32 a = 1; a < numContactPoints; ++a)
|
||||
{
|
||||
if(normal.dot(contactPoints[a].normal) < closeNormalThresh ||
|
||||
pMaterial[a].mMaterialIndex0 != mat0 || pMaterial[a].mMaterialIndex1 != mat1)
|
||||
{
|
||||
StridePatch& patch = stridePatches[numStrideHeaders-1];
|
||||
|
||||
patch.startIndex = PxU8(strideStart);
|
||||
patch.endIndex = PxU8(a);
|
||||
patch.nextIndex = 0xFF;
|
||||
patch.totalCount = PxU8(a - strideStart);
|
||||
patch.isRoot = root;
|
||||
if(parentRootPatch)
|
||||
parentRootPatch->totalCount += PxU8(a - strideStart);
|
||||
|
||||
root = true;
|
||||
parentRootPatch = NULL;
|
||||
for(PxU32 b = 1; b < numStrideHeaders; ++b)
|
||||
{
|
||||
StridePatch& thisPatch = stridePatches[b-1];
|
||||
if(thisPatch.isRoot)
|
||||
{
|
||||
PxU32 ind = thisPatch.startIndex;
|
||||
PxReal dp2 = contactPoints[a].normal.dot(contactPoints[ind].normal);
|
||||
if(dp2 >= closeNormalThresh && pMaterial[a].mMaterialIndex0 == pMaterial[ind].mMaterialIndex0 &&
|
||||
pMaterial[a].mMaterialIndex1 == pMaterial[ind].mMaterialIndex1)
|
||||
{
|
||||
PxU32 nextInd = b-1;
|
||||
while(stridePatches[nextInd].nextIndex != 0xFF)
|
||||
nextInd = stridePatches[nextInd].nextIndex;
|
||||
stridePatches[nextInd].nextIndex = PxU8(numStrideHeaders);
|
||||
root = false;
|
||||
parentRootPatch = &stridePatches[b-1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
normal = contactPoints[a].normal;
|
||||
|
||||
mat0 = pMaterial[a].mMaterialIndex0;
|
||||
mat1 = pMaterial[a].mMaterialIndex1;
|
||||
totalContactPoints = insertAveragePoint && (a - strideStart) > 1 ? totalContactPoints + 1 : totalContactPoints;
|
||||
strideStart = a;
|
||||
numStrideHeaders++;
|
||||
if(root)
|
||||
totalUniquePatches++;
|
||||
}
|
||||
}
|
||||
totalContactPoints = insertAveragePoint &&(numContactPoints - strideStart) > 1 ? totalContactPoints + 1 : totalContactPoints;
|
||||
contactForceByteSize = insertAveragePoint && contactForceByteSize != 0 ? contactForceByteSize + sizeof(PxF32) * (totalContactPoints - numContactPoints) : contactForceByteSize;
|
||||
}
|
||||
{
|
||||
StridePatch& patch = stridePatches[numStrideHeaders-1];
|
||||
patch.startIndex = PxU8(strideStart);
|
||||
patch.endIndex = PxU8(numContactPoints);
|
||||
patch.nextIndex = 0xFF;
|
||||
patch.totalCount = PxU8(numContactPoints - strideStart);
|
||||
patch.isRoot = root;
|
||||
if(parentRootPatch)
|
||||
parentRootPatch->totalCount += PxU8(numContactPoints - strideStart);
|
||||
}
|
||||
|
||||
numPatches = PxU8(totalUniquePatches);
|
||||
|
||||
//Calculate the number of patches/points required
|
||||
|
||||
const PxU32 patchHeaderSize = sizeof(PxContactPatch) * (isModifiable ? totalContactPoints : totalUniquePatches) + additionalHeaderSize;
|
||||
const PxU32 pointSize = totalContactPoints * (isModifiable ? sizeof(PxModifiableContact) : sizeof(PxContact));
|
||||
|
||||
PxU32 requiredContactSize = pointSize;
|
||||
PxU32 requiredPatchSize = patchHeaderSize;
|
||||
PxU32 totalRequiredSize;
|
||||
|
||||
PxU8* PX_RESTRICT contactData = NULL;
|
||||
PxU8* PX_RESTRICT patchData = NULL;
|
||||
PxReal* PX_RESTRICT forceData = NULL;
|
||||
PxU32* PX_RESTRICT triangleIndice = NULL;
|
||||
|
||||
if(contactStreamPool && !isModifiable && additionalHeaderSize == 0) //If the contacts are modifiable, we **DON'T** allocate them in GPU pinned memory. This will be handled later when they're modified
|
||||
{
|
||||
bool isOverflown = false;
|
||||
|
||||
PxU32 contactIndex = PxU32(Ps::atomicAdd(&contactStreamPool->mSharedDataIndex, PxI32(requiredContactSize)));
|
||||
|
||||
if (contactStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Contact buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
|
||||
contactData = contactStreamPool->mDataStream + contactStreamPool->mDataStreamSize - contactIndex;
|
||||
|
||||
PxU32 patchIndex = PxU32(Ps::atomicAdd(&patchStreamPool->mSharedDataIndex, PxI32(requiredPatchSize)));
|
||||
|
||||
if (patchStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Patch buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
|
||||
patchData = patchStreamPool->mDataStream + patchStreamPool->mDataStreamSize - patchIndex;
|
||||
|
||||
if(contactForceByteSize)
|
||||
{
|
||||
contactForceByteSize = isMeshType ? contactForceByteSize * 2 : contactForceByteSize;
|
||||
contactIndex = PxU32(Ps::atomicAdd(&forceStreamPool->mSharedDataIndex, PxI32(contactForceByteSize)));
|
||||
|
||||
if (forceStreamPool->isOverflown())
|
||||
{
|
||||
PX_WARN_ONCE("Force buffer overflow detected, please increase its size in the scene desc!\n");
|
||||
isOverflown = true;
|
||||
}
|
||||
forceData = reinterpret_cast<PxReal*>(forceStreamPool->mDataStream + forceStreamPool->mDataStreamSize - contactIndex);
|
||||
if (isMeshType)
|
||||
triangleIndice = reinterpret_cast<PxU32*>(forceData + numContactPoints);
|
||||
}
|
||||
|
||||
totalRequiredSize = requiredContactSize + requiredPatchSize;
|
||||
|
||||
if (isOverflown)
|
||||
{
|
||||
patchData = NULL;
|
||||
contactData = NULL;
|
||||
forceData = NULL;
|
||||
triangleIndice = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PxU32 alignedRequiredSize = (requiredContactSize + requiredPatchSize + 0xf) & 0xfffffff0;
|
||||
contactForceByteSize = (isMeshType ? contactForceByteSize * 2 : contactForceByteSize);
|
||||
PxU32 totalSize = alignedRequiredSize + contactForceByteSize;
|
||||
PxU8* data = manager ? blockStream->reserve(totalSize, *manager) : threadContext->mContactBlockStream.reserve(totalSize);
|
||||
|
||||
patchData = data;
|
||||
contactData = patchData + requiredPatchSize;
|
||||
|
||||
if(contactForceByteSize)
|
||||
{
|
||||
forceData = reinterpret_cast<PxReal*>((data + alignedRequiredSize));
|
||||
|
||||
if (isMeshType)
|
||||
triangleIndice = reinterpret_cast<PxU32*>(forceData + numContactPoints);
|
||||
|
||||
if(data)
|
||||
{
|
||||
PxMemZero(forceData, contactForceByteSize);
|
||||
}
|
||||
}
|
||||
|
||||
totalRequiredSize = alignedRequiredSize;
|
||||
|
||||
}
|
||||
|
||||
Ps::prefetchLine(patchData);
|
||||
Ps::prefetchLine(contactData);
|
||||
|
||||
if(patchData == NULL)
|
||||
{
|
||||
writtenContactCount = 0;
|
||||
outContactPatches = NULL;
|
||||
outContactPoints = NULL;
|
||||
outContactForces = NULL;
|
||||
compressedContactSize = 0;
|
||||
numPatches = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
if(threadContext)
|
||||
{
|
||||
threadContext->mCompressedCacheSize += totalRequiredSize;
|
||||
threadContext->mTotalCompressedCacheSize += totalRequiredSize;
|
||||
}
|
||||
#endif
|
||||
compressedContactSize = Ps::to16(totalRequiredSize);
|
||||
|
||||
|
||||
|
||||
//PxU32 startIndex = 0;
|
||||
|
||||
//Extract first material
|
||||
PxU16 origMatIndex0 = pMaterial[0].mMaterialIndex0;
|
||||
PxU16 origMatIndex1 = pMaterial[0].mMaterialIndex1;
|
||||
|
||||
PxReal staticFriction, dynamicFriction, combinedRestitution;
|
||||
PxU32 materialFlags;
|
||||
{
|
||||
const PxsMaterialData& data0 = *materialManager->getMaterial(origMatIndex0);
|
||||
const PxsMaterialData& data1 = *materialManager->getMaterial(origMatIndex1);
|
||||
|
||||
combinedRestitution = PxsMaterialCombiner::combineRestitution(data0, data1);
|
||||
PxsMaterialCombiner combiner(1.0f, 1.0f);
|
||||
PxsMaterialCombiner::PxsCombinedMaterial combinedMat = combiner.combineIsotropicFriction(data0, data1);
|
||||
staticFriction = combinedMat.staFriction;
|
||||
dynamicFriction = combinedMat.dynFriction;
|
||||
materialFlags = combinedMat.flags;
|
||||
}
|
||||
|
||||
|
||||
PxU8* PX_RESTRICT dataPlusOffset = patchData + additionalHeaderSize;
|
||||
PxContactPatch* PX_RESTRICT patches = reinterpret_cast<PxContactPatch*>(dataPlusOffset);
|
||||
PxU32* PX_RESTRICT faceIndice = triangleIndice;
|
||||
|
||||
outContactPatches = patchData;
|
||||
outContactPoints = contactData;
|
||||
outContactForces = forceData;
|
||||
|
||||
if(isModifiable)
|
||||
{
|
||||
|
||||
PxU32 flags = PxU32(isModifiable ? PxContactPatch::eMODIFIABLE : 0) |
|
||||
(forceNoResponse ? PxContactPatch::eFORCE_NO_RESPONSE : 0) |
|
||||
(isMeshType ? PxContactPatch::eHAS_FACE_INDICES : 0);
|
||||
|
||||
PxU32 currentIndex = 0;
|
||||
|
||||
PxModifiableContact* PX_RESTRICT point = reinterpret_cast<PxModifiableContact*>(contactData);
|
||||
|
||||
for(PxU32 a = 0; a < numStrideHeaders; ++a)
|
||||
{
|
||||
StridePatch& rootPatch = stridePatches[a];
|
||||
if(rootPatch.isRoot)
|
||||
{
|
||||
PxContactPatch* PX_RESTRICT patch = patches++;
|
||||
|
||||
PxU32 startIndex = rootPatch.startIndex;
|
||||
|
||||
const PxU16 matIndex0 = pMaterial[startIndex].mMaterialIndex0;
|
||||
const PxU16 matIndex1 = pMaterial[startIndex].mMaterialIndex1;
|
||||
if(matIndex0 != origMatIndex0 || matIndex1 != origMatIndex1)
|
||||
{
|
||||
const PxsMaterialData& data0 = *materialManager->getMaterial(matIndex0);
|
||||
const PxsMaterialData& data1 = *materialManager->getMaterial(matIndex1);
|
||||
|
||||
combinedRestitution = PxsMaterialCombiner::combineRestitution(data0, data1);
|
||||
PxsMaterialCombiner combiner(1.0f, 1.0f);
|
||||
PxsMaterialCombiner::PxsCombinedMaterial combinedMat = combiner.combineIsotropicFriction(data0, data1);
|
||||
staticFriction = combinedMat.staFriction;
|
||||
dynamicFriction = combinedMat.dynFriction;
|
||||
materialFlags = combinedMat.flags;
|
||||
origMatIndex0 = matIndex0;
|
||||
origMatIndex1 = matIndex1;
|
||||
}
|
||||
|
||||
patch->nbContacts = rootPatch.totalCount;
|
||||
|
||||
patch->startContactIndex = Ps::to8(currentIndex);
|
||||
patch->materialFlags = PxU8(materialFlags);
|
||||
patch->staticFriction = staticFriction;
|
||||
patch->dynamicFriction = dynamicFriction;
|
||||
patch->restitution = combinedRestitution;
|
||||
patch->materialIndex0 = matIndex0;
|
||||
patch->materialIndex1 = matIndex1;
|
||||
patch->normal = contactPoints[0].normal;
|
||||
patch->mMassModification.mInvMassScale0 = 1.0f;
|
||||
patch->mMassModification.mInvMassScale1 = 1.0f;
|
||||
patch->mMassModification.mInvInertiaScale0 = 1.0f;
|
||||
patch->mMassModification.mInvInertiaScale1 = 1.0f;
|
||||
patch->internalFlags = PxU8(flags);
|
||||
|
||||
//const PxU32 endIndex = strideHeader[a];
|
||||
const PxU32 totalCountThisPatch = rootPatch.totalCount;
|
||||
if(insertAveragePoint && totalCountThisPatch > 1)
|
||||
{
|
||||
PxVec3 avgPt(0.0f);
|
||||
PxF32 avgPen(0.0f);
|
||||
PxF32 recipCount = 1.0f/(PxF32(rootPatch.totalCount));
|
||||
|
||||
PxU32 index = a;
|
||||
while(index != 0xFF)
|
||||
{
|
||||
StridePatch& p = stridePatches[index];
|
||||
for(PxU32 b = p.startIndex; b < p.endIndex; ++b)
|
||||
{
|
||||
avgPt += contactPoints[b].point;
|
||||
avgPen += contactPoints[b].separation;
|
||||
}
|
||||
index = p.nextIndex;
|
||||
}
|
||||
|
||||
if (faceIndice)
|
||||
{
|
||||
StridePatch& p = stridePatches[index];
|
||||
*faceIndice = contactPoints[p.startIndex].internalFaceIndex1;
|
||||
faceIndice++;
|
||||
}
|
||||
|
||||
patch->nbContacts++;
|
||||
point->contact = avgPt * recipCount;
|
||||
point->separation = avgPen * recipCount;
|
||||
point->normal = contactPoints[0].normal;
|
||||
point->maxImpulse = PX_MAX_REAL;
|
||||
point->targetVelocity = PxVec3(0.0f);
|
||||
point->staticFriction = staticFriction;
|
||||
point->dynamicFriction = dynamicFriction;
|
||||
point->restitution = combinedRestitution;
|
||||
point->materialFlags = materialFlags;
|
||||
point->materialIndex0 = matIndex0;
|
||||
point->materialIndex1 = matIndex1;
|
||||
point++;
|
||||
currentIndex++;
|
||||
Ps::prefetchLine(point, 128);
|
||||
}
|
||||
|
||||
PxU32 index = a;
|
||||
while(index != 0xFF)
|
||||
{
|
||||
StridePatch& p = stridePatches[index];
|
||||
|
||||
for(PxU32 b = p.startIndex; b < p.endIndex; ++b)
|
||||
{
|
||||
copyContactPoint(point, &contactPoints[b]);
|
||||
point->normal = contactPoints[b].normal;
|
||||
point->maxImpulse = PX_MAX_REAL;
|
||||
point->targetVelocity = PxVec3(0.0f);
|
||||
point->staticFriction = staticFriction;
|
||||
point->dynamicFriction = dynamicFriction;
|
||||
point->restitution = combinedRestitution;
|
||||
point->materialFlags = materialFlags;
|
||||
point->materialIndex0 = matIndex0;
|
||||
point->materialIndex1 = matIndex1;
|
||||
if (faceIndice)
|
||||
{
|
||||
*faceIndice = contactPoints[b].internalFaceIndex1;
|
||||
faceIndice++;
|
||||
}
|
||||
point++;
|
||||
currentIndex++;
|
||||
Ps::prefetchLine(point, 128);
|
||||
}
|
||||
index = p.nextIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PxU32 flags = PxU32(isMeshType ? PxContactPatch::eHAS_FACE_INDICES : 0);
|
||||
|
||||
PxContact* PX_RESTRICT point = reinterpret_cast<PxContact*>(contactData);
|
||||
|
||||
PxU32 currentIndex = 0;
|
||||
{
|
||||
for(PxU32 a = 0; a < numStrideHeaders; ++a)
|
||||
{
|
||||
StridePatch& rootPatch = stridePatches[a];
|
||||
|
||||
if(rootPatch.isRoot)
|
||||
{
|
||||
const PxU16 matIndex0 = pMaterial[rootPatch.startIndex].mMaterialIndex0;
|
||||
const PxU16 matIndex1 = pMaterial[rootPatch.startIndex].mMaterialIndex1;
|
||||
if(matIndex0 != origMatIndex0 || matIndex1 != origMatIndex1)
|
||||
{
|
||||
const PxsMaterialData& data0 = *materialManager->getMaterial(matIndex0);
|
||||
const PxsMaterialData& data1 = *materialManager->getMaterial(matIndex1);
|
||||
|
||||
combinedRestitution = PxsMaterialCombiner::combineRestitution(data0, data1);
|
||||
PxsMaterialCombiner combiner(1.0f, 1.0f);
|
||||
PxsMaterialCombiner::PxsCombinedMaterial combinedMat = combiner.combineIsotropicFriction(data0, data1);
|
||||
staticFriction = combinedMat.staFriction;
|
||||
dynamicFriction = combinedMat.dynFriction;
|
||||
materialFlags = combinedMat.flags;
|
||||
origMatIndex0 = matIndex0;
|
||||
origMatIndex1 = matIndex1;
|
||||
}
|
||||
|
||||
PxContactPatch* PX_RESTRICT patch = patches++;
|
||||
patch->normal = contactPoints[rootPatch.startIndex].normal;
|
||||
patch->nbContacts = rootPatch.totalCount;
|
||||
patch->startContactIndex = Ps::to8(currentIndex);
|
||||
//KS - we could probably compress this further into the header but the complexity might not be worth it
|
||||
patch->staticFriction = staticFriction;
|
||||
patch->dynamicFriction = dynamicFriction;
|
||||
patch->restitution = combinedRestitution;
|
||||
patch->materialIndex0 = matIndex0;
|
||||
patch->materialIndex1 = matIndex1;
|
||||
patch->materialFlags = PxU8(materialFlags);
|
||||
patch->internalFlags = PxU8(flags);
|
||||
patch->mMassModification.mInvMassScale0 = 1.0f;
|
||||
patch->mMassModification.mInvMassScale1 = 1.0f;
|
||||
patch->mMassModification.mInvInertiaScale0 = 1.0f;
|
||||
patch->mMassModification.mInvInertiaScale1 = 1.0f;
|
||||
if(insertAveragePoint && (rootPatch.totalCount) > 1)
|
||||
{
|
||||
patch->nbContacts++;
|
||||
PxVec3 avgPt(0.0f);
|
||||
PxF32 avgPen(0.0f);
|
||||
PxF32 recipCount = 1.0f/(PxF32(rootPatch.totalCount));
|
||||
PxU32 index = a;
|
||||
|
||||
while(index != 0xFF)
|
||||
{
|
||||
StridePatch& p = stridePatches[index];
|
||||
for(PxU32 b = p.startIndex; b < p.endIndex; ++b)
|
||||
{
|
||||
avgPt += contactPoints[b].point;
|
||||
avgPen += contactPoints[b].separation;
|
||||
}
|
||||
index = stridePatches[index].nextIndex;
|
||||
}
|
||||
|
||||
if (faceIndice)
|
||||
{
|
||||
StridePatch& p = stridePatches[index];
|
||||
*faceIndice = contactPoints[p.startIndex].internalFaceIndex1;
|
||||
faceIndice++;
|
||||
}
|
||||
point->contact = avgPt * recipCount;
|
||||
point->separation = avgPen * recipCount;
|
||||
|
||||
point++;
|
||||
currentIndex++;
|
||||
Ps::prefetchLine(point, 128);
|
||||
}
|
||||
|
||||
PxU32 index = a;
|
||||
while(index != 0xFF)
|
||||
{
|
||||
StridePatch& p = stridePatches[index];
|
||||
for(PxU32 b = p.startIndex; b < p.endIndex; ++b)
|
||||
{
|
||||
copyContactPoint(point, &contactPoints[b]);
|
||||
if (faceIndice)
|
||||
{
|
||||
*faceIndice = contactPoints[b].internalFaceIndex1;
|
||||
faceIndice++;
|
||||
}
|
||||
point++;
|
||||
currentIndex++;
|
||||
Ps::prefetchLine(point, 128);
|
||||
}
|
||||
index = stridePatches[index].nextIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writtenContactCount = Ps::to8(totalContactPoints);
|
||||
|
||||
return totalRequiredSize;
|
||||
}
|
||||
351
physx/source/lowlevel/common/src/pipeline/PxcNpMemBlockPool.cpp
Normal file
351
physx/source/lowlevel/common/src/pipeline/PxcNpMemBlockPool.cpp
Normal file
@ -0,0 +1,351 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#include "foundation/PxMath.h"
|
||||
#include "PxcNpMemBlockPool.h"
|
||||
#include "PsUserAllocated.h"
|
||||
#include "PsInlineArray.h"
|
||||
#include "PsFoundation.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
PxcNpMemBlockPool::PxcNpMemBlockPool(PxcScratchAllocator& allocator):
|
||||
mConstraints(PX_DEBUG_EXP("PxcNpMemBlockPool::mConstraints")),
|
||||
mExceptionalConstraints(PX_DEBUG_EXP("PxcNpMemBlockPool::mExceptionalConstraints")),
|
||||
mNpCacheActiveStream(0),
|
||||
mFrictionActiveStream(0),
|
||||
mCCDCacheActiveStream(0),
|
||||
mContactIndex(0),
|
||||
mAllocatedBlocks(0),
|
||||
mMaxBlocks(0),
|
||||
mUsedBlocks(0),
|
||||
mMaxUsedBlocks(0),
|
||||
mScratchBlockAddr(0),
|
||||
mNbScratchBlocks(0),
|
||||
mScratchAllocator(allocator),
|
||||
mPeakConstraintAllocations(0),
|
||||
mConstraintAllocations(0)
|
||||
{
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::init(PxU32 initialBlockCount, PxU32 maxBlocks)
|
||||
{
|
||||
mMaxBlocks = maxBlocks;
|
||||
mInitialBlocks = initialBlockCount;
|
||||
|
||||
PxU32 reserve = PxMax<PxU32>(initialBlockCount, 64);
|
||||
|
||||
mConstraints.reserve(reserve);
|
||||
mExceptionalConstraints.reserve(16);
|
||||
|
||||
mFriction[0].reserve(reserve);
|
||||
mFriction[1].reserve(reserve);
|
||||
mNpCache[0].reserve(reserve);
|
||||
mNpCache[1].reserve(reserve);
|
||||
mUnused.reserve(reserve);
|
||||
|
||||
setBlockCount(initialBlockCount);
|
||||
}
|
||||
|
||||
PxU32 PxcNpMemBlockPool::getUsedBlockCount() const
|
||||
{
|
||||
return mUsedBlocks;
|
||||
}
|
||||
|
||||
PxU32 PxcNpMemBlockPool::getMaxUsedBlockCount() const
|
||||
{
|
||||
return mMaxUsedBlocks;
|
||||
}
|
||||
|
||||
PxU32 PxcNpMemBlockPool::getPeakConstraintBlockCount() const
|
||||
{
|
||||
return mPeakConstraintAllocations;
|
||||
}
|
||||
|
||||
|
||||
void PxcNpMemBlockPool::setBlockCount(PxU32 blockCount)
|
||||
{
|
||||
Ps::Mutex::ScopedLock lock(mLock);
|
||||
PxU32 current = getUsedBlockCount();
|
||||
for(PxU32 i=current;i<blockCount;i++)
|
||||
{
|
||||
mUnused.pushBack(reinterpret_cast<PxcNpMemBlock *>(PX_ALLOC(PxcNpMemBlock::SIZE, "PxcNpMemBlock")));
|
||||
mAllocatedBlocks++;
|
||||
}
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::releaseUnusedBlocks()
|
||||
{
|
||||
Ps::Mutex::ScopedLock lock(mLock);
|
||||
while(mUnused.size())
|
||||
{
|
||||
PX_FREE(mUnused.popBack());
|
||||
mAllocatedBlocks--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PxcNpMemBlockPool::~PxcNpMemBlockPool()
|
||||
{
|
||||
// swapping twice guarantees all blocks are released from the stream pairs
|
||||
swapFrictionStreams();
|
||||
swapFrictionStreams();
|
||||
|
||||
swapNpCacheStreams();
|
||||
swapNpCacheStreams();
|
||||
|
||||
releaseConstraintMemory();
|
||||
releaseContacts();
|
||||
releaseContacts();
|
||||
|
||||
PX_ASSERT(mUsedBlocks == 0);
|
||||
|
||||
flushUnused();
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::acquireConstraintMemory()
|
||||
{
|
||||
PxU32 size;
|
||||
void* addr = mScratchAllocator.allocAll(size);
|
||||
size = size&~(PxcNpMemBlock::SIZE-1);
|
||||
|
||||
PX_ASSERT(mScratchBlocks.size()==0);
|
||||
mScratchBlockAddr = reinterpret_cast<PxcNpMemBlock*>(addr);
|
||||
mNbScratchBlocks = size/PxcNpMemBlock::SIZE;
|
||||
|
||||
mScratchBlocks.resize(mNbScratchBlocks);
|
||||
for(PxU32 i=0;i<mNbScratchBlocks;i++)
|
||||
mScratchBlocks[i] = mScratchBlockAddr+i;
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::releaseConstraintMemory()
|
||||
{
|
||||
Ps::Mutex::ScopedLock lock(mLock);
|
||||
|
||||
mPeakConstraintAllocations = mConstraintAllocations = 0;
|
||||
|
||||
while(mConstraints.size())
|
||||
{
|
||||
PxcNpMemBlock* block = mConstraints.popBack();
|
||||
if(mScratchAllocator.isScratchAddr(block))
|
||||
mScratchBlocks.pushBack(block);
|
||||
else
|
||||
{
|
||||
mUnused.pushBack(block);
|
||||
PX_ASSERT(mUsedBlocks>0);
|
||||
mUsedBlocks--;
|
||||
}
|
||||
}
|
||||
|
||||
for(PxU32 i=0;i<mExceptionalConstraints.size();i++)
|
||||
PX_FREE(mExceptionalConstraints[i]);
|
||||
mExceptionalConstraints.clear();
|
||||
|
||||
PX_ASSERT(mScratchBlocks.size()==mNbScratchBlocks); // check we released them all
|
||||
mScratchBlocks.clear();
|
||||
|
||||
if(mScratchBlockAddr)
|
||||
{
|
||||
mScratchAllocator.free(mScratchBlockAddr);
|
||||
mScratchBlockAddr = 0;
|
||||
mNbScratchBlocks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PxcNpMemBlock* PxcNpMemBlockPool::acquire(PxcNpMemBlockArray& trackingArray, PxU32* allocationCount, PxU32* peakAllocationCount, bool isScratchAllocation)
|
||||
{
|
||||
Ps::Mutex::ScopedLock lock(mLock);
|
||||
if(allocationCount && peakAllocationCount)
|
||||
{
|
||||
*peakAllocationCount = PxMax(*allocationCount + 1, *peakAllocationCount);
|
||||
(*allocationCount)++;
|
||||
}
|
||||
|
||||
// this is a bit of hack - the logic would be better placed in acquireConstraintBlock, but then we'd have to grab the mutex
|
||||
// once there to check the scratch block array and once here if we fail - or, we'd need a larger refactor to separate out
|
||||
// locking and acquisition.
|
||||
|
||||
if(isScratchAllocation && mScratchBlocks.size()>0)
|
||||
{
|
||||
PxcNpMemBlock* block = mScratchBlocks.popBack();
|
||||
trackingArray.pushBack(block);
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
if(mUnused.size())
|
||||
{
|
||||
PxcNpMemBlock* block = mUnused.popBack();
|
||||
trackingArray.pushBack(block);
|
||||
mMaxUsedBlocks = PxMax<PxU32>(mUsedBlocks+1, mMaxUsedBlocks);
|
||||
mUsedBlocks++;
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
if(mAllocatedBlocks == mMaxBlocks)
|
||||
{
|
||||
#if PX_CHECKED
|
||||
Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
|
||||
"Reached maximum number of allocated blocks so 16k block allocation will fail!");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if PX_CHECKED
|
||||
if(mInitialBlocks)
|
||||
{
|
||||
Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
|
||||
"Number of required 16k memory blocks has exceeded the initial number of blocks. Allocator is being called. Consider increasing the number of pre-allocated 16k blocks.");
|
||||
}
|
||||
#endif
|
||||
|
||||
// increment here so that if we hit the limit in separate threads we won't overallocated
|
||||
mAllocatedBlocks++;
|
||||
|
||||
PxcNpMemBlock* block = reinterpret_cast<PxcNpMemBlock*>(PX_ALLOC(sizeof(PxcNpMemBlock), "PxcNpMemBlock"));
|
||||
|
||||
if(block)
|
||||
{
|
||||
trackingArray.pushBack(block);
|
||||
mMaxUsedBlocks = PxMax<PxU32>(mUsedBlocks+1, mMaxUsedBlocks);
|
||||
mUsedBlocks++;
|
||||
}
|
||||
else
|
||||
mAllocatedBlocks--;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
PxU8* PxcNpMemBlockPool::acquireExceptionalConstraintMemory(PxU32 size)
|
||||
{
|
||||
PxU8* memory = reinterpret_cast<PxU8*>(PX_ALLOC(size, "PxcNpExceptionalMemory"));
|
||||
if(memory)
|
||||
{
|
||||
Ps::Mutex::ScopedLock lock(mLock);
|
||||
mExceptionalConstraints.pushBack(memory);
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::release(PxcNpMemBlockArray& deadArray, PxU32* allocationCount)
|
||||
{
|
||||
Ps::Mutex::ScopedLock lock(mLock);
|
||||
PX_ASSERT(mUsedBlocks >= deadArray.size());
|
||||
mUsedBlocks -= deadArray.size();
|
||||
if(allocationCount)
|
||||
{
|
||||
*allocationCount -= deadArray.size();
|
||||
}
|
||||
while(deadArray.size())
|
||||
{
|
||||
PxcNpMemBlock* block = deadArray.popBack();
|
||||
for(PxU32 a = 0; a < mUnused.size(); ++a)
|
||||
{
|
||||
PX_ASSERT(mUnused[a] != block);
|
||||
}
|
||||
mUnused.pushBack(block);
|
||||
}
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::flushUnused()
|
||||
{
|
||||
while(mUnused.size())
|
||||
PX_FREE(mUnused.popBack());
|
||||
}
|
||||
|
||||
|
||||
PxcNpMemBlock* PxcNpMemBlockPool::acquireConstraintBlock()
|
||||
{
|
||||
// we track the scratch blocks in the constraint block array, because the code in acquireMultipleConstraintBlocks
|
||||
// assumes that acquired blocks are listed there.
|
||||
|
||||
return acquire(mConstraints);
|
||||
}
|
||||
|
||||
PxcNpMemBlock* PxcNpMemBlockPool::acquireConstraintBlock(PxcNpMemBlockArray& memBlocks)
|
||||
{
|
||||
return acquire(memBlocks, &mConstraintAllocations, &mPeakConstraintAllocations, true);
|
||||
}
|
||||
|
||||
PxcNpMemBlock* PxcNpMemBlockPool::acquireContactBlock()
|
||||
{
|
||||
return acquire(mContacts[mContactIndex], NULL, NULL, true);
|
||||
}
|
||||
|
||||
|
||||
void PxcNpMemBlockPool::releaseConstraintBlocks(PxcNpMemBlockArray& memBlocks)
|
||||
{
|
||||
Ps::Mutex::ScopedLock lock(mLock);
|
||||
|
||||
while(memBlocks.size())
|
||||
{
|
||||
PxcNpMemBlock* block = memBlocks.popBack();
|
||||
if(mScratchAllocator.isScratchAddr(block))
|
||||
mScratchBlocks.pushBack(block);
|
||||
else
|
||||
{
|
||||
mUnused.pushBack(block);
|
||||
PX_ASSERT(mUsedBlocks>0);
|
||||
mUsedBlocks--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::releaseContacts()
|
||||
{
|
||||
//releaseConstraintBlocks(mContacts);
|
||||
release(mContacts[1-mContactIndex]);
|
||||
mContactIndex = 1-mContactIndex;
|
||||
}
|
||||
|
||||
PxcNpMemBlock* PxcNpMemBlockPool::acquireFrictionBlock()
|
||||
{
|
||||
return acquire(mFriction[mFrictionActiveStream]);
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::swapFrictionStreams()
|
||||
{
|
||||
release(mFriction[1-mFrictionActiveStream]);
|
||||
mFrictionActiveStream = 1-mFrictionActiveStream;
|
||||
}
|
||||
|
||||
PxcNpMemBlock* PxcNpMemBlockPool::acquireNpCacheBlock()
|
||||
{
|
||||
return acquire(mNpCache[mNpCacheActiveStream]);
|
||||
}
|
||||
|
||||
void PxcNpMemBlockPool::swapNpCacheStreams()
|
||||
{
|
||||
release(mNpCache[1-mNpCacheActiveStream]);
|
||||
mNpCacheActiveStream = 1-mNpCacheActiveStream;
|
||||
}
|
||||
|
||||
@ -0,0 +1,94 @@
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "PxcConstraintBlockStream.h"
|
||||
#include "PxcNpThreadContext.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
PxcNpThreadContext::PxcNpThreadContext(PxcNpContext* params) :
|
||||
mRenderOutput (params->mRenderBuffer),
|
||||
mContactBlockStream (params->mNpMemBlockPool),
|
||||
mNpCacheStreamPair (params->mNpMemBlockPool),
|
||||
mNarrowPhaseParams (0.0f, params->mMeshContactMargin, params->mToleranceLength),
|
||||
mBodySimPool (PX_DEBUG_EXP("BodySimPool")),
|
||||
mPCM (false),
|
||||
mContactCache (false),
|
||||
mCreateContactStream (params->mCreateContactStream),
|
||||
mCreateAveragePoint (false),
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
mCompressedCacheSize (0),
|
||||
mNbDiscreteContactPairsWithCacheHits(0),
|
||||
mNbDiscreteContactPairsWithContacts (0),
|
||||
#endif
|
||||
mMaxPatches (0),
|
||||
mTotalCompressedCacheSize (0),
|
||||
mContactStreamPool (params->mContactStreamPool),
|
||||
mPatchStreamPool (params->mPatchStreamPool),
|
||||
mForceAndIndiceStreamPool (params->mForceAndIndiceStreamPool),
|
||||
mMaterialManager (params->mMaterialManager),
|
||||
mLocalNewTouchCount (0),
|
||||
mLocalLostTouchCount (0),
|
||||
mLocalFoundPatchCount (0),
|
||||
mLocalLostPatchCount (0)
|
||||
{
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
clearStats();
|
||||
#endif
|
||||
}
|
||||
|
||||
PxcNpThreadContext::~PxcNpThreadContext()
|
||||
{
|
||||
}
|
||||
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
void PxcNpThreadContext::clearStats()
|
||||
{
|
||||
PxMemSet(mDiscreteContactPairs, 0, sizeof(mDiscreteContactPairs));
|
||||
PxMemSet(mModifiedContactPairs, 0, sizeof(mModifiedContactPairs));
|
||||
mCompressedCacheSize = 0;
|
||||
mNbDiscreteContactPairsWithCacheHits = 0;
|
||||
mNbDiscreteContactPairsWithContacts = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void PxcNpThreadContext::reset(PxU32 cmCount)
|
||||
{
|
||||
mContactBlockStream.reset();
|
||||
mNpCacheStreamPair.reset();
|
||||
|
||||
mLocalChangeTouch.clear();
|
||||
mLocalChangeTouch.resize(cmCount);
|
||||
mLocalPatchCountChange.clear();
|
||||
mLocalPatchCountChange.resize(cmCount);
|
||||
mLocalNewTouchCount = 0;
|
||||
mLocalLostTouchCount = 0;
|
||||
mLocalFoundPatchCount = 0;
|
||||
mLocalLostPatchCount = 0;
|
||||
}
|
||||
51
physx/source/lowlevel/software/include/PxsBodySim.h
Normal file
51
physx/source/lowlevel/software/include/PxsBodySim.h
Normal 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
|
||||
628
physx/source/lowlevel/software/include/PxsCCD.h
Normal file
628
physx/source/lowlevel/software/include/PxsCCD.h
Normal 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
|
||||
|
||||
178
physx/source/lowlevel/software/include/PxsContactManager.h
Normal file
178
physx/source/lowlevel/software/include/PxsContactManager.h
Normal 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
|
||||
@ -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
|
||||
339
physx/source/lowlevel/software/include/PxsContext.h
Normal file
339
physx/source/lowlevel/software/include/PxsContext.h
Normal 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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
363
physx/source/lowlevel/software/include/PxsIslandManagerTypes.h
Normal file
363
physx/source/lowlevel/software/include/PxsIslandManagerTypes.h
Normal 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
|
||||
78
physx/source/lowlevel/software/include/PxsIslandNodeIndex.h
Normal file
78
physx/source/lowlevel/software/include/PxsIslandNodeIndex.h
Normal 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
|
||||
940
physx/source/lowlevel/software/include/PxsIslandSim.h
Normal file
940
physx/source/lowlevel/software/include/PxsIslandSim.h
Normal 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
|
||||
48
physx/source/lowlevel/software/include/PxsKernelWrangler.h
Normal file
48
physx/source/lowlevel/software/include/PxsKernelWrangler.h
Normal 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
|
||||
143
physx/source/lowlevel/software/include/PxsMaterialCombiner.h
Normal file
143
physx/source/lowlevel/software/include/PxsMaterialCombiner.h
Normal 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
|
||||
59
physx/source/lowlevel/software/include/PxsMemoryManager.h
Normal file
59
physx/source/lowlevel/software/include/PxsMemoryManager.h
Normal 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
|
||||
@ -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
|
||||
182
physx/source/lowlevel/software/include/PxsRigidBody.h
Normal file
182
physx/source/lowlevel/software/include/PxsRigidBody.h
Normal 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
|
||||
54
physx/source/lowlevel/software/include/PxsShapeSim.h
Normal file
54
physx/source/lowlevel/software/include/PxsShapeSim.h
Normal 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
|
||||
202
physx/source/lowlevel/software/include/PxsSimpleIslandManager.h
Normal file
202
physx/source/lowlevel/software/include/PxsSimpleIslandManager.h
Normal 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
|
||||
144
physx/source/lowlevel/software/include/PxsSimulationController.h
Normal file
144
physx/source/lowlevel/software/include/PxsSimulationController.h
Normal 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
|
||||
144
physx/source/lowlevel/software/include/PxsTransformCache.h
Normal file
144
physx/source/lowlevel/software/include/PxsTransformCache.h
Normal 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
|
||||
@ -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
|
||||
2074
physx/source/lowlevel/software/src/PxsCCD.cpp
Normal file
2074
physx/source/lowlevel/software/src/PxsCCD.cpp
Normal file
File diff suppressed because it is too large
Load Diff
87
physx/source/lowlevel/software/src/PxsContactManager.cpp
Normal file
87
physx/source/lowlevel/software/src/PxsContactManager.cpp
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
623
physx/source/lowlevel/software/src/PxsContext.cpp
Normal file
623
physx/source/lowlevel/software/src/PxsContext.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
2323
physx/source/lowlevel/software/src/PxsIslandSim.cpp
Normal file
2323
physx/source/lowlevel/software/src/PxsIslandSim.cpp
Normal file
File diff suppressed because it is too large
Load Diff
102
physx/source/lowlevel/software/src/PxsMaterialCombiner.cpp
Normal file
102
physx/source/lowlevel/software/src/PxsMaterialCombiner.cpp
Normal 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
377
physx/source/lowlevel/software/src/PxsSimpleIslandManager.cpp
Normal file
377
physx/source/lowlevel/software/src/PxsSimpleIslandManager.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user