feat(physics): wire physx sdk into build
This commit is contained in:
137
engine/third_party/physx/source/simulationcontroller/include/ScActorCore.h
vendored
Normal file
137
engine/third_party/physx/source/simulationcontroller/include/ScActorCore.h
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ACTOR_CORE_H
|
||||
#define SC_ACTOR_CORE_H
|
||||
|
||||
#include "foundation/PxBitAndData.h"
|
||||
#include "PxActor.h"
|
||||
|
||||
#define SC_FILTERING_ID_SHIFT_BIT 24
|
||||
#define SC_FILTERING_ID_MAX (1<<SC_FILTERING_ID_SHIFT_BIT)
|
||||
#define SC_FILTERING_ID_MASK 0x00ffffff
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class ActorSim;
|
||||
|
||||
class ActorCore
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
ActorCore(const PxEMPTY) : mSim(NULL), mActorFlags(PxEmpty)
|
||||
{
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
ActorCore(PxActorType::Enum actorType, PxU8 actorFlags, PxClientID owner, PxDominanceGroup dominanceGroup);
|
||||
~ActorCore();
|
||||
|
||||
PX_FORCE_INLINE ActorSim* getSim() const { return mSim; }
|
||||
PX_FORCE_INLINE void setSim(ActorSim* sim)
|
||||
{
|
||||
PX_ASSERT((sim==NULL) ^ (mSim==NULL));
|
||||
mSim = sim;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxActorFlags getActorFlags() const { return mActorFlags; }
|
||||
void setActorFlags(PxActorFlags af);
|
||||
|
||||
PX_FORCE_INLINE PxDominanceGroup getDominanceGroup() const
|
||||
{
|
||||
return PxDominanceGroup(mDominanceGroup);
|
||||
}
|
||||
void setDominanceGroup(PxDominanceGroup g);
|
||||
|
||||
PX_FORCE_INLINE void setOwnerClient(PxClientID inId)
|
||||
{
|
||||
const PxU32 id = mPackedIDs & SC_FILTERING_ID_MASK;
|
||||
mPackedIDs = (PxU32(inId)<<SC_FILTERING_ID_SHIFT_BIT) | id;
|
||||
}
|
||||
PX_FORCE_INLINE PxClientID getOwnerClient() const
|
||||
{
|
||||
return mPackedIDs>>SC_FILTERING_ID_SHIFT_BIT;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxActorType::Enum getActorCoreType() const { return PxActorType::Enum(mActorType); }
|
||||
|
||||
void reinsertShapes();
|
||||
|
||||
void setAggregateID(PxU32 id);
|
||||
PX_FORCE_INLINE PxU8 hasAggregateID() const { return mDominanceGroup.isBitSet(); }
|
||||
PX_FORCE_INLINE PxU32 getAggregateID() const
|
||||
{
|
||||
if(!hasAggregateID())
|
||||
return PX_INVALID_U32;
|
||||
|
||||
return mPackedIDs & SC_FILTERING_ID_MASK;
|
||||
}
|
||||
|
||||
void setEnvID(PxU32 id);
|
||||
PX_FORCE_INLINE PxU32 getEnvID() const
|
||||
{
|
||||
if(hasAggregateID())
|
||||
return PX_INVALID_U32;
|
||||
|
||||
const PxU32 id = mPackedIDs & SC_FILTERING_ID_MASK;
|
||||
return id == SC_FILTERING_ID_MASK ? PX_INVALID_U32 : id;
|
||||
}
|
||||
private:
|
||||
ActorSim* mSim;
|
||||
PxU32 mPackedIDs; // PxClientID (8bit) | aggregate / env ID (24bit)
|
||||
// PT: TODO: the remaining members could be packed into just a 16bit mask
|
||||
PxActorFlags mActorFlags; // PxActor's flags (PxU8) => only 4 bits used
|
||||
PxU8 mActorType; // Actor type (8 bits, but 3 would be enough)
|
||||
PxBitAndByte mDominanceGroup; // Aggregate bit | dominance group (7 bits, but 5 would be enough because "must be < 32")
|
||||
|
||||
PX_FORCE_INLINE void setID(PxU32 id)
|
||||
{
|
||||
const PxU32 ownerClient = mPackedIDs & (~SC_FILTERING_ID_MASK);
|
||||
mPackedIDs = (id & SC_FILTERING_ID_MASK) | ownerClient;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void resetID()
|
||||
{
|
||||
mPackedIDs |= SC_FILTERING_ID_MASK;
|
||||
}
|
||||
};
|
||||
|
||||
#if PX_P64_FAMILY
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(Sc::ActorCore)==16);
|
||||
#else
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(Sc::ActorCore)==12);
|
||||
#endif
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
67
engine/third_party/physx/source/simulationcontroller/include/ScArticulationAttachmentCore.h
vendored
Normal file
67
engine/third_party/physx/source/simulationcontroller/include/ScArticulationAttachmentCore.h
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#ifndef SC_ATTACHMENT_CORE_H
|
||||
#define SC_ATTACHMENT_CORE_H
|
||||
|
||||
#include "foundation/PxVec3.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class ArticulationAttachmentCore
|
||||
{
|
||||
public:
|
||||
|
||||
// PX_SERIALIZATION
|
||||
ArticulationAttachmentCore(const PxEMPTY) : mTendonSim(NULL) {}
|
||||
void preExportDataReset() { }
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
ArticulationAttachmentCore() : mLowLimit(PX_MAX_F32), mHighLimit(-PX_MAX_F32), mRestLength(0.f)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PxVec3 mRelativeOffset; //relative offset to the link(in link space)
|
||||
ArticulationAttachmentCore* mParent;
|
||||
PxReal mLowLimit;
|
||||
PxReal mHighLimit;
|
||||
PxReal mRestLength;
|
||||
PxReal mCoefficient;
|
||||
PxU32 mLLLinkIndex;
|
||||
PxU32 mAttachmentIndex;
|
||||
Sc::ArticulationSpatialTendonSim* mTendonSim;
|
||||
|
||||
};
|
||||
}//namespace Sc
|
||||
}//namespace physx
|
||||
|
||||
#endif
|
||||
162
engine/third_party/physx/source/simulationcontroller/include/ScArticulationCore.h
vendored
Normal file
162
engine/third_party/physx/source/simulationcontroller/include/ScArticulationCore.h
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ARTICULATION_CORE_H
|
||||
#define SC_ARTICULATION_CORE_H
|
||||
|
||||
#include "ScActorCore.h"
|
||||
#include "DyFeatherstoneArticulation.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxNodeIndex;
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
class ArticulationSim;
|
||||
|
||||
class ArticulationCore
|
||||
{
|
||||
//---------------------------------------------------------------------------------
|
||||
// Construction, destruction & initialization
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
// PX_SERIALIZATION
|
||||
public:
|
||||
ArticulationCore(const PxEMPTY) : mSim(NULL), mCore(PxEmpty) {}
|
||||
//~PX_SERIALIZATION
|
||||
ArticulationCore();
|
||||
~ArticulationCore();
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// External API
|
||||
//---------------------------------------------------------------------------------
|
||||
PX_FORCE_INLINE PxReal getSleepThreshold() const { return mCore.sleepThreshold; }
|
||||
PX_FORCE_INLINE void setSleepThreshold(const PxReal v) { mCore.sleepThreshold = v; }
|
||||
|
||||
PX_FORCE_INLINE PxReal getFreezeThreshold() const { return mCore.freezeThreshold; }
|
||||
PX_FORCE_INLINE void setFreezeThreshold(const PxReal v) { mCore.freezeThreshold = v; }
|
||||
|
||||
PX_FORCE_INLINE PxU16 getSolverIterationCounts() const { return mCore.solverIterationCounts; }
|
||||
PX_FORCE_INLINE void setSolverIterationCounts(PxU16 c) { mCore.solverIterationCounts = c; }
|
||||
|
||||
PX_FORCE_INLINE PxReal getWakeCounter() const { return mCore.wakeCounter; }
|
||||
PX_FORCE_INLINE void setWakeCounterInternal(const PxReal v) { mCore.wakeCounter = v; }
|
||||
void setWakeCounter(const PxReal v);
|
||||
|
||||
bool isSleeping() const;
|
||||
void wakeUp(PxReal wakeCounter);
|
||||
void putToSleep();
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// external reduced coordinate API
|
||||
//---------------------------------------------------------------------------------
|
||||
void setArticulationFlags(PxArticulationFlags flags);
|
||||
PxArticulationFlags getArticulationFlags() const { return mCore.flags; }
|
||||
|
||||
PxU32 getDofs() const;
|
||||
|
||||
PxArticulationCache* createCache() const;
|
||||
|
||||
PxU32 getCacheDataSize() const;
|
||||
|
||||
void zeroCache(PxArticulationCache& cache) const;
|
||||
|
||||
bool applyCache(PxArticulationCache& cache, const PxArticulationCacheFlags flag)const;
|
||||
|
||||
void copyInternalStateToCache
|
||||
(PxArticulationCache& cache, const PxArticulationCacheFlags flag, const bool isGpuSimEnabled) const;
|
||||
|
||||
void packJointData(const PxReal* maximum, PxReal* reduced) const;
|
||||
|
||||
void unpackJointData(const PxReal* reduced, PxReal* maximum) const;
|
||||
|
||||
void commonInit() const;
|
||||
|
||||
void computeGeneralizedGravityForce(PxArticulationCache& cache, const bool rootMotion) const;
|
||||
|
||||
void computeCoriolisAndCentrifugalForce(PxArticulationCache& cache, const bool rootMotion) const;
|
||||
|
||||
void computeGeneralizedExternalForce(PxArticulationCache& cache) const;
|
||||
|
||||
void computeJointAcceleration(PxArticulationCache& cache) const;
|
||||
|
||||
void computeJointForce(PxArticulationCache& cache) const;
|
||||
|
||||
void computeDenseJacobian(PxArticulationCache& cache, PxU32& nRows, PxU32& nCols) const;
|
||||
|
||||
void computeCoefficientMatrix(PxArticulationCache& cache) const;
|
||||
|
||||
bool computeLambda(PxArticulationCache& cache, PxArticulationCache& rollBackCache, const PxReal* const jointTorque, const PxVec3 gravity, const PxU32 maxIter) const;
|
||||
|
||||
void computeGeneralizedMassMatrix(PxArticulationCache& cache, const bool rootMotion) const;
|
||||
|
||||
PxVec3 computeArticulationCOM(const bool rootFrame) const;
|
||||
|
||||
void computeCentroidalMomentumMatrix(PxArticulationCache& cache) const;
|
||||
|
||||
PxU32 getCoefficientMatrixSize() const;
|
||||
|
||||
PxSpatialVelocity getLinkAcceleration(const PxU32 linkId, const bool isGpuSimEnabled) const;
|
||||
|
||||
PxU32 getGpuArticulationIndex() const;
|
||||
|
||||
void updateKinematic(PxArticulationKinematicFlags flags);
|
||||
//---------------------------------------------------------------------------------
|
||||
// Internal API
|
||||
//---------------------------------------------------------------------------------
|
||||
public:
|
||||
PX_FORCE_INLINE void setSim(ArticulationSim* sim)
|
||||
{
|
||||
PX_ASSERT((sim==0) ^ (mSim == 0));
|
||||
mSim = sim;
|
||||
}
|
||||
PX_FORCE_INLINE ArticulationSim* getSim() const { return mSim; }
|
||||
|
||||
PX_FORCE_INLINE Dy::ArticulationCore& getCore() { return mCore; }
|
||||
|
||||
static PX_FORCE_INLINE ArticulationCore& getArticulationCore(ArticulationCore& core)
|
||||
{
|
||||
const size_t offset = PX_OFFSET_OF(ArticulationCore, mCore);
|
||||
return *reinterpret_cast<ArticulationCore*>(reinterpret_cast<PxU8*>(&core) - offset);
|
||||
}
|
||||
|
||||
PxNodeIndex getIslandNodeIndex() const;
|
||||
|
||||
void setGlobalPose();
|
||||
|
||||
private:
|
||||
ArticulationSim* mSim;
|
||||
Dy::ArticulationCore mCore;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
147
engine/third_party/physx/source/simulationcontroller/include/ScArticulationJointCore.h
vendored
Normal file
147
engine/third_party/physx/source/simulationcontroller/include/ScArticulationJointCore.h
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ARTICULATION_JOINT_CORE_H
|
||||
#define SC_ARTICULATION_JOINT_CORE_H
|
||||
|
||||
#include "foundation/PxTransform.h"
|
||||
#include "DyVArticulation.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class BodyCore;
|
||||
class ArticulationJointSim;
|
||||
class ArticulationCore;
|
||||
|
||||
class ArticulationJointDesc
|
||||
{
|
||||
public:
|
||||
BodyCore* parent;
|
||||
BodyCore* child;
|
||||
PxTransform parentPose;
|
||||
PxTransform childPose;
|
||||
};
|
||||
|
||||
class ArticulationJointCore
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
ArticulationJointCore(const PxEMPTY) : mCore(PxEmpty), mSim(NULL) {}
|
||||
void preExportDataReset() { mCore.jCalcUpdateFrames = true; }
|
||||
//~PX_SERIALIZATION
|
||||
ArticulationJointCore(const PxTransform& parentFrame, const PxTransform& childFrame);
|
||||
~ArticulationJointCore();
|
||||
|
||||
//Those methods are not allowed while the articulation are in the scene
|
||||
PX_FORCE_INLINE const PxTransform& getParentPose() const { return mCore.parentPose; }
|
||||
void setParentPose(const PxTransform&);
|
||||
|
||||
PX_FORCE_INLINE const PxTransform& getChildPose() const { return mCore.childPose; }
|
||||
void setChildPose(const PxTransform&);
|
||||
|
||||
//Those functions doesn't change the articulation configuration so the application is allowed to change those value in run-time
|
||||
PX_FORCE_INLINE PxArticulationLimit getLimit(PxArticulationAxis::Enum axis) const { return mCore.limits[axis]; }
|
||||
void setLimit(PxArticulationAxis::Enum axis, const PxArticulationLimit& limit);
|
||||
|
||||
PX_FORCE_INLINE PxArticulationDrive getDrive(PxArticulationAxis::Enum axis) const { return mCore.drives[axis]; }
|
||||
void setDrive(PxArticulationAxis::Enum axis, const PxArticulationDrive& drive);
|
||||
|
||||
void setTargetP(PxArticulationAxis::Enum axis, PxReal targetP);
|
||||
PX_FORCE_INLINE PxReal getTargetP(PxArticulationAxis::Enum axis) const { return mCore.targetP[axis]; }
|
||||
|
||||
void setTargetV(PxArticulationAxis::Enum axis, PxReal targetV);
|
||||
PX_FORCE_INLINE PxReal getTargetV(PxArticulationAxis::Enum axis) const { return mCore.targetV[axis]; }
|
||||
|
||||
void setArmature(PxArticulationAxis::Enum axis, PxReal armature);
|
||||
PX_FORCE_INLINE PxReal getArmature(PxArticulationAxis::Enum axis) const { return mCore.armature[axis]; }
|
||||
|
||||
void setJointPosition(PxArticulationAxis::Enum axis, const PxReal jointPos);
|
||||
PxReal getJointPosition(PxArticulationAxis::Enum axis) const;
|
||||
|
||||
void setJointVelocity(PxArticulationAxis::Enum axis, const PxReal jointVel);
|
||||
PxReal getJointVelocity(PxArticulationAxis::Enum axis) const;
|
||||
|
||||
void setMaxJointVelocity(PxReal maxJointV);
|
||||
PX_FORCE_INLINE PxReal getMaxJointVelocity() const { return mCore.maxJointVelocity[0]; }
|
||||
|
||||
void setMaxJointVelocity(PxArticulationAxis::Enum axis, PxReal maxJointV);
|
||||
PX_FORCE_INLINE PxReal getMaxJointVelocity(PxArticulationAxis::Enum axis) const { return mCore.maxJointVelocity[axis]; }
|
||||
|
||||
PX_FORCE_INLINE void setMotion(PxArticulationAxis::Enum axis, PxArticulationMotion::Enum motion) { mCore.motion[axis] = PxU8(motion); }
|
||||
PX_FORCE_INLINE PxArticulationMotion::Enum getMotion(PxArticulationAxis::Enum axis) const { return PxArticulationMotion::Enum(mCore.motion[axis]); }
|
||||
|
||||
PX_FORCE_INLINE void setJointType(PxArticulationJointType::Enum type) { mCore.setJointType(type); }
|
||||
PX_FORCE_INLINE PxArticulationJointType::Enum getJointType() const { return PxArticulationJointType::Enum(mCore.jointType); }
|
||||
|
||||
void setFrictionCoefficient(const PxReal coefficient);
|
||||
PX_FORCE_INLINE PxReal getFrictionCoefficient() const { return mCore.frictionCoefficient; }
|
||||
|
||||
void setFrictionParams(PxArticulationAxis::Enum axis, const PxJointFrictionParams& jointFrictionParams);
|
||||
PX_FORCE_INLINE PxJointFrictionParams getFrictionParams(PxArticulationAxis::Enum axis) const { return mCore.frictionParams[axis]; }
|
||||
|
||||
PX_FORCE_INLINE ArticulationJointSim* getSim() const { return mSim; }
|
||||
PX_FORCE_INLINE void setSim(ArticulationJointSim* sim)
|
||||
{
|
||||
PX_ASSERT((sim==0) ^ (mSim == 0));
|
||||
mSim = sim;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE Dy::ArticulationJointCore& getCore() { return mCore; }
|
||||
|
||||
PX_FORCE_INLINE void setArticulation(ArticulationCore* articulation) { mArticulation = articulation; }
|
||||
PX_FORCE_INLINE const ArticulationCore* getArticulation() const { return mArticulation; }
|
||||
|
||||
PX_FORCE_INLINE void setRoot(PxArticulationJointReducedCoordinate* base) { mRootType = base; }
|
||||
PX_FORCE_INLINE PxArticulationJointReducedCoordinate* getRoot() const { return mRootType; }
|
||||
|
||||
PX_FORCE_INLINE void setLLIndex(const PxU32 llLinkIndex) { mLLLinkIndex = llLinkIndex; }
|
||||
private:
|
||||
void setSimDirty();
|
||||
PX_FORCE_INLINE void setDirty()
|
||||
{
|
||||
mCore.jCalcUpdateFrames = true;
|
||||
setSimDirty();
|
||||
}
|
||||
|
||||
Dy::ArticulationJointCore mCore;
|
||||
ArticulationJointSim* mSim;
|
||||
ArticulationCore* mArticulation;
|
||||
PxArticulationJointReducedCoordinate* mRootType;
|
||||
PxU32 mLLLinkIndex;
|
||||
#if PX_P64_FAMILY
|
||||
PxU32 pad;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
74
engine/third_party/physx/source/simulationcontroller/include/ScArticulationMimicJointCore.h
vendored
Normal file
74
engine/third_party/physx/source/simulationcontroller/include/ScArticulationMimicJointCore.h
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ARTICULATION_MIMIC_JOINT_CORE
|
||||
#define SC_ARTICULATION_MIMIC_JOINT_CORE
|
||||
|
||||
#include "foundation/PxVec3.h"
|
||||
#include "foundation/PxTransform.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
|
||||
class ArticulationCore;
|
||||
class ArticulationMimicJointSim;
|
||||
|
||||
class ArticulationMimicJointCore
|
||||
{
|
||||
public:
|
||||
|
||||
// PX_SERIALIZATION
|
||||
ArticulationMimicJointCore(const PxEMPTY) :mSim(NULL) {}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
|
||||
ArticulationMimicJointCore() : mSim(NULL) {}
|
||||
|
||||
PX_FORCE_INLINE void setSim(ArticulationMimicJointSim* sim)
|
||||
{
|
||||
PX_ASSERT((sim == 0) ^ (mSim == 0));
|
||||
mSim = sim;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE ArticulationMimicJointSim* getSim() const { return mSim; }
|
||||
|
||||
ArticulationMimicJointSim* mSim;
|
||||
PxU32 mAxisA;
|
||||
PxU32 mAxisB;
|
||||
PxReal mGearRatio;
|
||||
PxReal mOffset;
|
||||
PxReal mNaturalFrequency;
|
||||
PxReal mDampingRatio;
|
||||
};
|
||||
}//namespace Sc
|
||||
}//namespace physx
|
||||
|
||||
#endif //SC_ARTICULATION_MIMIC_JOINT_CORE
|
||||
|
||||
147
engine/third_party/physx/source/simulationcontroller/include/ScArticulationTendonCore.h
vendored
Normal file
147
engine/third_party/physx/source/simulationcontroller/include/ScArticulationTendonCore.h
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#ifndef PX_PHYSICS_SCP_ARTICULATION_TENDON_CORE
|
||||
#define PX_PHYSICS_SCP_ARTICULATION_TENDON_CORE
|
||||
|
||||
#include "DyArticulationTendon.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class ArticulationSpatialTendonSim;
|
||||
class ArticulationFixedTendonSim;
|
||||
|
||||
class ArticulationTendonCore
|
||||
{
|
||||
public:
|
||||
|
||||
// PX_SERIALIZATION
|
||||
ArticulationTendonCore(const PxEMPTY) {}
|
||||
void preExportDataReset() { }
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
ArticulationTendonCore() : mStiffness(0.f), mDamping(0.f), mOffset(0.f), mLimitStiffness(0.f)
|
||||
{
|
||||
|
||||
}
|
||||
PxReal mStiffness;
|
||||
PxReal mDamping;
|
||||
PxReal mOffset;
|
||||
PxReal mLimitStiffness;
|
||||
};
|
||||
|
||||
class ArticulationSpatialTendonCore : public ArticulationTendonCore
|
||||
{
|
||||
public:
|
||||
|
||||
// PX_SERIALIZATION
|
||||
ArticulationSpatialTendonCore(const PxEMPTY) : ArticulationTendonCore(PxEmpty), mSim(NULL) {}
|
||||
void preExportDataReset() { }
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
ArticulationSpatialTendonCore() : ArticulationTendonCore() { mSim = NULL; }
|
||||
~ArticulationSpatialTendonCore() {}
|
||||
|
||||
void setStiffness(const PxReal stiffness);
|
||||
PxReal getStiffness() const;
|
||||
|
||||
void setDamping(const PxReal damping);
|
||||
PxReal getDamping() const;
|
||||
|
||||
void setLimitStiffness(const PxReal stiffness);
|
||||
PxReal getLimitStiffness() const;
|
||||
|
||||
void setOffset(const PxReal offset);
|
||||
PxReal getOffset() const;
|
||||
|
||||
|
||||
PX_FORCE_INLINE void setSim(ArticulationSpatialTendonSim* sim)
|
||||
{
|
||||
PX_ASSERT((sim == 0) ^ (mSim == 0));
|
||||
mSim = sim;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE ArticulationSpatialTendonSim* getSim() const { return mSim; }
|
||||
|
||||
|
||||
ArticulationSpatialTendonSim* mSim;
|
||||
};
|
||||
|
||||
class ArticulationFixedTendonCore : public ArticulationTendonCore
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
ArticulationFixedTendonCore(const PxEMPTY) : ArticulationTendonCore(PxEmpty), mSim(NULL) {}
|
||||
void preExportDataReset() {}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
ArticulationFixedTendonCore() : ArticulationTendonCore(), mLowLimit(PX_MAX_F32), mHighLimit(-PX_MAX_F32), mRestLength(0.f)
|
||||
{ mSim = NULL; }
|
||||
~ArticulationFixedTendonCore() {}
|
||||
|
||||
void setStiffness(const PxReal stiffness);
|
||||
PxReal getStiffness() const;
|
||||
|
||||
void setDamping(const PxReal damping);
|
||||
PxReal getDamping() const;
|
||||
|
||||
void setLimitStiffness(const PxReal stiffness);
|
||||
PxReal getLimitStiffness() const;
|
||||
|
||||
|
||||
void setOffset(const PxReal offset);
|
||||
PxReal getOffset() const;
|
||||
|
||||
void setSpringRestLength(const PxReal restLength);
|
||||
PxReal getSpringRestLength() const;
|
||||
|
||||
void setLimitRange(const PxReal lowLimit, const PxReal highLimit);
|
||||
void getLimitRange(PxReal& lowLimit, PxReal& highLimit) const;
|
||||
|
||||
PX_FORCE_INLINE void setSim(ArticulationFixedTendonSim* sim)
|
||||
{
|
||||
PX_ASSERT((sim == 0) ^ (mSim == 0));
|
||||
mSim = sim;
|
||||
}
|
||||
PX_FORCE_INLINE ArticulationFixedTendonSim* getSim() const { return mSim; }
|
||||
|
||||
PxReal mLowLimit;
|
||||
PxReal mHighLimit;
|
||||
PxReal mRestLength;
|
||||
|
||||
ArticulationFixedTendonSim* mSim;
|
||||
};
|
||||
|
||||
|
||||
}//namespace Sc
|
||||
} //namespace physx
|
||||
|
||||
#endif
|
||||
83
engine/third_party/physx/source/simulationcontroller/include/ScArticulationTendonJointCore.h
vendored
Normal file
83
engine/third_party/physx/source/simulationcontroller/include/ScArticulationTendonJointCore.h
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#ifndef SC_TENDON_JOINT_CORE_H
|
||||
#define SC_TENDON_JOINT_CORE_H
|
||||
|
||||
#include "foundation/PxVec3.h"
|
||||
#include "solver/PxSolverDefs.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class ArticulationFixedTendonSim;
|
||||
|
||||
class ArticulationTendonJointCore
|
||||
{
|
||||
public:
|
||||
|
||||
// PX_SERIALIZATION
|
||||
ArticulationTendonJointCore(const PxEMPTY) : mTendonSim(NULL) {}
|
||||
void preExportDataReset() { }
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
ArticulationTendonJointCore()
|
||||
{
|
||||
coefficient = PX_MAX_F32;
|
||||
recipCoefficient = PX_MAX_F32;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxArticulationAxis::Enum getAxis()
|
||||
{
|
||||
return axis;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void getCoefficient(PxArticulationAxis::Enum& axis_, PxReal& coefficient_, PxReal& recipCoefficient_) const
|
||||
{
|
||||
axis_ = axis;
|
||||
coefficient_ = coefficient;
|
||||
recipCoefficient_ = recipCoefficient;
|
||||
}
|
||||
|
||||
void setCoefficient(PxArticulationAxis::Enum axis_, const PxReal coefficient_, const PxReal recipCoefficient_);
|
||||
|
||||
|
||||
PxArticulationAxis::Enum axis;
|
||||
PxReal coefficient;
|
||||
PxReal recipCoefficient;
|
||||
PxU32 mLLLinkIndex;
|
||||
ArticulationTendonJointCore* mParent;
|
||||
PxU32 mLLTendonJointIndex;
|
||||
Sc::ArticulationFixedTendonSim* mTendonSim;
|
||||
};
|
||||
}//namespace Sc
|
||||
}//namespace physx
|
||||
|
||||
#endif
|
||||
188
engine/third_party/physx/source/simulationcontroller/include/ScBodyCore.h
vendored
Normal file
188
engine/third_party/physx/source/simulationcontroller/include/ScBodyCore.h
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_BODY_CORE_H
|
||||
#define SC_BODY_CORE_H
|
||||
|
||||
#include "foundation/PxTransform.h"
|
||||
#include "ScRigidCore.h"
|
||||
#include "PxRigidDynamic.h"
|
||||
#include "PxvDynamics.h"
|
||||
#include "PxvConfig.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class BodySim;
|
||||
|
||||
class BodyCore : public RigidCore
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
BodyCore(const PxEMPTY) : RigidCore(PxEmpty), mCore(PxEmpty) {}
|
||||
void restoreDynamicData();
|
||||
|
||||
//~PX_SERIALIZATION
|
||||
BodyCore(PxActorType::Enum type, const PxTransform& bodyPose);
|
||||
~BodyCore();
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// External API
|
||||
//---------------------------------------------------------------------------------
|
||||
PX_FORCE_INLINE const PxTransform& getBody2World() const { return mCore.body2World; }
|
||||
void setBody2World(const PxTransform& p);
|
||||
|
||||
void setCMassLocalPose(const PxTransform& body2Actor);
|
||||
|
||||
PX_FORCE_INLINE const PxVec3& getLinearVelocity() const { return mCore.linearVelocity; }
|
||||
void setLinearVelocity(const PxVec3& v, bool skipBodySimUpdate=false);
|
||||
|
||||
PX_FORCE_INLINE const PxVec3& getAngularVelocity() const { return mCore.angularVelocity; }
|
||||
void setAngularVelocity(const PxVec3& v, bool skipBodySimUpdate=false);
|
||||
|
||||
PX_FORCE_INLINE PxReal getCfmScale() const { return mCore.cfmScale; }
|
||||
void setCfmScale(PxReal d);
|
||||
|
||||
PX_FORCE_INLINE void updateVelocities(const PxVec3& linearVelModPerStep, const PxVec3& angularVelModPerStep)
|
||||
{
|
||||
mCore.linearVelocity += linearVelModPerStep;
|
||||
mCore.angularVelocity += angularVelModPerStep;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE const PxTransform& getBody2Actor() const { return mCore.getBody2Actor(); }
|
||||
void setBody2Actor(const PxTransform& p);
|
||||
|
||||
void addSpatialAcceleration(const PxVec3* linAcc, const PxVec3* angAcc);
|
||||
void setSpatialAcceleration(const PxVec3* linAcc, const PxVec3* angAcc);
|
||||
void clearSpatialAcceleration(bool force, bool torque);
|
||||
void addSpatialVelocity(const PxVec3* linVelDelta, const PxVec3* angVelDelta);
|
||||
void clearSpatialVelocity(bool force, bool torque);
|
||||
|
||||
PX_FORCE_INLINE PxReal getMaxPenetrationBias() const { return mCore.maxPenBias; }
|
||||
PX_FORCE_INLINE void setMaxPenetrationBias(PxReal p) { mCore.maxPenBias = p; }
|
||||
|
||||
PxReal getInverseMass() const;
|
||||
void setInverseMass(PxReal m);
|
||||
const PxVec3& getInverseInertia() const;
|
||||
void setInverseInertia(const PxVec3& i);
|
||||
|
||||
PxReal getLinearDamping() const;
|
||||
void setLinearDamping(PxReal d);
|
||||
|
||||
PxReal getAngularDamping() const;
|
||||
void setAngularDamping(PxReal d);
|
||||
|
||||
PX_FORCE_INLINE PxRigidBodyFlags getFlags() const { return mCore.mFlags; }
|
||||
void setFlags(PxRigidBodyFlags f);
|
||||
|
||||
PX_FORCE_INLINE PxRigidDynamicLockFlags getRigidDynamicLockFlags() const { return mCore.lockFlags; }
|
||||
|
||||
PX_FORCE_INLINE void setRigidDynamicLockFlags(PxRigidDynamicLockFlags flags) { mCore.lockFlags = flags; }
|
||||
|
||||
PX_FORCE_INLINE PxReal getSleepThreshold() const { return mCore.sleepThreshold; }
|
||||
void setSleepThreshold(PxReal t);
|
||||
|
||||
PX_FORCE_INLINE PxReal getFreezeThreshold() const { return mCore.freezeThreshold; }
|
||||
void setFreezeThreshold(PxReal t);
|
||||
|
||||
PX_FORCE_INLINE PxReal getMaxContactImpulse() const { return mCore.maxContactImpulse; }
|
||||
void setMaxContactImpulse(PxReal m);
|
||||
|
||||
PX_FORCE_INLINE PxReal getOffsetSlop() const { return mCore.offsetSlop; }
|
||||
void setOffsetSlop(PxReal slop);
|
||||
|
||||
PxNodeIndex getInternalIslandNodeIndex() const;
|
||||
|
||||
PX_FORCE_INLINE PxReal getWakeCounter() const { return mCore.wakeCounter; }
|
||||
void setWakeCounter(PxReal wakeCounter, bool forceWakeUp=false);
|
||||
|
||||
bool isSleeping() const;
|
||||
PX_FORCE_INLINE void wakeUp(PxReal wakeCounter) { setWakeCounter(wakeCounter, true); }
|
||||
void putToSleep();
|
||||
|
||||
PxReal getMaxAngVelSq() const;
|
||||
void setMaxAngVelSq(PxReal v);
|
||||
|
||||
PxReal getMaxLinVelSq() const;
|
||||
void setMaxLinVelSq(PxReal v);
|
||||
|
||||
PX_FORCE_INLINE PxU16 getSolverIterationCounts() const { return mCore.solverIterationCounts; }
|
||||
void setSolverIterationCounts(PxU16 c);
|
||||
|
||||
bool getKinematicTarget(PxTransform& p) const;
|
||||
bool getHasValidKinematicTarget() const;
|
||||
void setKinematicTarget(const PxTransform& p, PxReal wakeCounter);
|
||||
void invalidateKinematicTarget();
|
||||
|
||||
PX_FORCE_INLINE PxReal getContactReportThreshold() const { return mCore.contactReportThreshold; }
|
||||
void setContactReportThreshold(PxReal t) { mCore.contactReportThreshold = t; }
|
||||
|
||||
void onOriginShift(const PxVec3& shift);
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Internal API
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
PX_FORCE_INLINE void setLinearVelocityInternal(const PxVec3& v) { mCore.linearVelocity = v; }
|
||||
PX_FORCE_INLINE void setAngularVelocityInternal(const PxVec3& v) { mCore.angularVelocity = v; }
|
||||
PX_FORCE_INLINE void setWakeCounterFromSim(PxReal c) { mCore.wakeCounter = c; }
|
||||
|
||||
BodySim* getSim() const;
|
||||
|
||||
PX_FORCE_INLINE PxsBodyCore& getCore() { return mCore; }
|
||||
PX_FORCE_INLINE const PxsBodyCore& getCore() const { return mCore; }
|
||||
static PX_FORCE_INLINE size_t getCoreOffset() { return PX_OFFSET_OF_RT(BodyCore, mCore); }
|
||||
|
||||
PX_FORCE_INLINE PxReal getCCDAdvanceCoefficient() const { return mCore.ccdAdvanceCoefficient; }
|
||||
PX_FORCE_INLINE void setCCDAdvanceCoefficient(PxReal c) { mCore.ccdAdvanceCoefficient = c; }
|
||||
|
||||
void onRemoveKinematicFromScene();
|
||||
|
||||
PxIntBool isFrozen() const;
|
||||
|
||||
static PX_FORCE_INLINE BodyCore& getCore(PxsBodyCore& core)
|
||||
{
|
||||
return *reinterpret_cast<BodyCore*>(reinterpret_cast<PxU8*>(&core) - getCoreOffset());
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE BodyCore& getCore(const PxsBodyCore& core)
|
||||
{
|
||||
return *reinterpret_cast<BodyCore*>(reinterpret_cast<PxU8*>(&const_cast<PxsBodyCore&>(core)) - getCoreOffset());
|
||||
}
|
||||
|
||||
void setFixedBaseLink(bool value);
|
||||
private:
|
||||
PX_ALIGN_PREFIX(16) PxsBodyCore mCore PX_ALIGN_SUFFIX(16);
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
71
engine/third_party/physx/source/simulationcontroller/include/ScBroadphase.h
vendored
Normal file
71
engine/third_party/physx/source/simulationcontroller/include/ScBroadphase.h
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_BROADPHASE_H
|
||||
#define SC_BROADPHASE_H
|
||||
|
||||
#include "PxvConfig.h"
|
||||
#include "foundation/PxArray.h"
|
||||
|
||||
// PT: this class captures parts of the Sc::Scene that deals with broadphase matters.
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxBroadPhaseCallback;
|
||||
|
||||
namespace Bp
|
||||
{
|
||||
class AABBManagerBase;
|
||||
}
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
class ObjectIDTracker;
|
||||
|
||||
class BroadphaseManager
|
||||
{
|
||||
public:
|
||||
BroadphaseManager();
|
||||
~BroadphaseManager();
|
||||
|
||||
PX_FORCE_INLINE void setBroadPhaseCallback(PxBroadPhaseCallback* callback) { mBroadPhaseCallback = callback; }
|
||||
PX_FORCE_INLINE PxBroadPhaseCallback* getBroadPhaseCallback() const { return mBroadPhaseCallback; }
|
||||
|
||||
void prepareOutOfBoundsCallbacks(Bp::AABBManagerBase* aabbManager);
|
||||
bool fireOutOfBoundsCallbacks(Bp::AABBManagerBase* aabbManager, const ObjectIDTracker& tracker, PxU64 contextID);
|
||||
|
||||
void flush(Bp::AABBManagerBase* aabbManager);
|
||||
|
||||
PxBroadPhaseCallback* mBroadPhaseCallback;
|
||||
PxArray<PxU32> mOutOfBoundsIDs;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
122
engine/third_party/physx/source/simulationcontroller/include/ScConstraintCore.h
vendored
Normal file
122
engine/third_party/physx/source/simulationcontroller/include/ScConstraintCore.h
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_CONSTRAINT_CORE_H
|
||||
#define SC_CONSTRAINT_CORE_H
|
||||
|
||||
#include "PxConstraint.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class ConstraintSim;
|
||||
class RigidCore;
|
||||
|
||||
class ConstraintCore
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
ConstraintCore(const PxEMPTY) : mFlags(PxEmpty), mConnector(NULL), mSim(NULL), mResidual() {}
|
||||
PX_FORCE_INLINE void setConstraintFunctions(PxConstraintConnector& n, const PxConstraintShaderTable& shaders)
|
||||
{
|
||||
mConnector = &n;
|
||||
mSolverPrep = shaders.solverPrep;
|
||||
mVisualize = shaders.visualize;
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
ConstraintCore(PxConstraintConnector& connector, const PxConstraintShaderTable& shaders, PxU32 dataSize);
|
||||
~ConstraintCore() {}
|
||||
|
||||
void setBodies(RigidCore* r0v, RigidCore* r1v);
|
||||
|
||||
PxConstraint* getPxConstraint();
|
||||
const PxConstraint* getPxConstraint() const;
|
||||
PX_FORCE_INLINE PxConstraintConnector* getPxConnector() const { return mConnector; }
|
||||
|
||||
PX_FORCE_INLINE PxConstraintFlags getFlags() const { return mFlags; }
|
||||
void setFlags(PxConstraintFlags flags);
|
||||
|
||||
void getForce(PxVec3& force, PxVec3& torque) const;
|
||||
|
||||
void setBreakForce(PxReal linear, PxReal angular);
|
||||
PX_FORCE_INLINE void getBreakForce(PxReal& linear, PxReal& angular) const
|
||||
{
|
||||
linear = mLinearBreakForce;
|
||||
angular = mAngularBreakForce;
|
||||
}
|
||||
|
||||
void setMinResponseThreshold(PxReal threshold);
|
||||
PX_FORCE_INLINE PxReal getMinResponseThreshold() const { return mMinResponseThreshold; }
|
||||
|
||||
void breakApart();
|
||||
|
||||
PX_FORCE_INLINE PxConstraintVisualize getVisualize() const { return mVisualize; }
|
||||
PX_FORCE_INLINE PxConstraintSolverPrep getSolverPrep() const { return mSolverPrep; }
|
||||
PX_FORCE_INLINE PxU32 getConstantBlockSize() const { return mDataSize; }
|
||||
|
||||
PX_FORCE_INLINE void setSim(ConstraintSim* sim)
|
||||
{
|
||||
PX_ASSERT((sim==0) ^ (mSim == 0));
|
||||
mSim = sim;
|
||||
}
|
||||
PX_FORCE_INLINE ConstraintSim* getSim() const { return mSim; }
|
||||
|
||||
PX_FORCE_INLINE bool isDirty() const { return mIsDirty ? true : false; }
|
||||
PX_FORCE_INLINE void setDirty() { mIsDirty = 1; }
|
||||
PX_FORCE_INLINE void clearDirty() { mIsDirty = 0; }
|
||||
|
||||
PX_FORCE_INLINE PxConstraintResidual getSolverResidual() const { return mResidual; }
|
||||
PX_FORCE_INLINE void setSolverResidual(const PxConstraintResidual& residual) { mResidual = residual; }
|
||||
|
||||
private:
|
||||
PxConstraintFlags mFlags;
|
||||
//In order to support O(1) insert/remove mIsDirty really wants to be an index into NpScene's dirty joint array
|
||||
PxU8 mIsDirty;
|
||||
PxU8 mPadding;
|
||||
|
||||
PxVec3 mAppliedForce;
|
||||
PxVec3 mAppliedTorque;
|
||||
|
||||
PxConstraintConnector* mConnector;
|
||||
PxConstraintSolverPrep mSolverPrep;
|
||||
PxConstraintVisualize mVisualize;
|
||||
PxU32 mDataSize;
|
||||
PxReal mLinearBreakForce;
|
||||
PxReal mAngularBreakForce;
|
||||
PxReal mMinResponseThreshold;
|
||||
|
||||
ConstraintSim* mSim;
|
||||
PxConstraintResidual mResidual;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
160
engine/third_party/physx/source/simulationcontroller/include/ScDeformableSurfaceCore.h
vendored
Normal file
160
engine/third_party/physx/source/simulationcontroller/include/ScDeformableSurfaceCore.h
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_DEFORMABLE_SURFACE_CORE
|
||||
#define SC_DEFORMABLE_SURFACE_CORE
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
|
||||
#include "PxDeformableSurface.h"
|
||||
#include "../../lowleveldynamics/include/DyDeformableSurfaceCore.h"
|
||||
#include "foundation/PxAssert.h"
|
||||
#include "ScActorCore.h"
|
||||
#include "ScShapeCore.h"
|
||||
#include "PxFiltering.h"
|
||||
#include "ScRigidCore.h" //KS - required for ShapeChangeNotifyFlags. Ideally, we should move that to a separate shared file
|
||||
#include "PxConeLimitedConstraint.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
|
||||
class DeformableSurfaceSim;
|
||||
|
||||
class DeformableSurfaceCore : public ActorCore
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
DeformableSurfaceCore(const PxEMPTY) : ActorCore(PxEmpty) {}
|
||||
//~PX_SERIALIZATION
|
||||
DeformableSurfaceCore();
|
||||
~DeformableSurfaceCore();
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// PxActor API
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
void setActorFlags(PxActorFlags flags);
|
||||
PxActorFlags getActorFlags() const { return mCore.actorFlags; }
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// PxDeformableBody API
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
void setBodyFlags(PxDeformableBodyFlags flags);
|
||||
PxDeformableBodyFlags getBodyFlags() const { return mCore.bodyFlags; }
|
||||
|
||||
void setLinearDamping(const PxReal linearDamping);
|
||||
PxReal getLinearDamping() const { return mCore.linearDamping; }
|
||||
|
||||
void setMaxLinearVelocity(const PxReal maxLinearVelocity);
|
||||
PxReal getMaxLinearVelocity() const { return mCore.maxLinearVelocity; }
|
||||
|
||||
void setMaxPenetrationBias(const PxReal maxPenetrationBias);
|
||||
PxReal getMaxPenetrationBias() const { return mCore.maxPenetrationBias; }
|
||||
|
||||
void setSolverIterationCounts(PxU16 c);
|
||||
PxU16 getSolverIterationCounts() const { return mCore.solverIterationCounts; }
|
||||
|
||||
void setSleepThreshold(const PxReal sleepThreshold);
|
||||
PxReal getSleepThreshold() const { return mCore.sleepThreshold; }
|
||||
|
||||
void setSettlingThreshold(const PxReal settlingThreshold);
|
||||
PxReal getSettlingThreshold() const { return mCore.settlingThreshold; }
|
||||
|
||||
void setSettlingDamping(const PxReal linearDamping);
|
||||
PxReal getSettlingDamping() const { return mCore.settlingDamping; }
|
||||
|
||||
void setSelfCollisionFilterDistance(const PxReal selfCollisionFilterDistance);
|
||||
PxReal getSelfCollisionFilterDistance() const { return mCore.selfCollisionFilterDistance; }
|
||||
|
||||
//deprecated
|
||||
void setSelfCollisionStressTolerance(const PxReal selfCollisionStressTolerance);
|
||||
PxReal getSelfCollisionStressTolerance() const { return mCore.selfCollisionStressTolerance; }
|
||||
|
||||
void setWakeCounter(const PxReal v);
|
||||
void setWakeCounterInternal(const PxReal v);
|
||||
PxReal getWakeCounter() const { return mCore.wakeCounter; }
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// PxDeformableBody API
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
void setSurfaceFlags(PxDeformableSurfaceFlags flags);
|
||||
PxDeformableSurfaceFlags getSurfaceFlags() const { return mCore.surfaceFlags; }
|
||||
|
||||
void setNbCollisionPairUpdatesPerTimestep(const PxU32 frequency);
|
||||
PxU32 getNbCollisionPairUpdatesPerTimestep() const { return mCore.nbCollisionPairUpdatesPerTimestep; }
|
||||
|
||||
void setNbCollisionSubsteps(const PxU32 frequency);
|
||||
PxU32 getNbCollisionSubsteps() const { return mCore.nbCollisionSubsteps; }
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Internal API
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
PxU32 addRigidAttachment(Sc::BodyCore* core, PxU32 vertId, const PxVec3& actorSpacePose, PxConeLimitedConstraint* constraint);
|
||||
void removeRigidAttachment(Sc::BodyCore* core, PxU32 handle);
|
||||
|
||||
void addTriRigidFilter(Sc::BodyCore* core, PxU32 triIdx);
|
||||
void removeTriRigidFilter(Sc::BodyCore* core, PxU32 triIdx);
|
||||
|
||||
PxU32 addTriRigidAttachment(Sc::BodyCore* core, PxU32 triIdx, const PxVec4& barycentric,
|
||||
const PxVec3& actorSpacePose, PxConeLimitedConstraint* constraint);
|
||||
void removeTriRigidAttachment(Sc::BodyCore* core, PxU32 handle);
|
||||
|
||||
void addClothFilter(Sc::DeformableSurfaceCore* otherCore, PxU32 otherTriIdx, PxU32 triIdx);
|
||||
void removeClothFilter(Sc::DeformableSurfaceCore* otherCore, PxU32 otherTriIdx0, PxU32 triIdx);
|
||||
|
||||
PxU32 addClothAttachment(Sc::DeformableSurfaceCore* otherCore, PxU32 otherTriIdx, const PxVec4& otherTriBarycentric, PxU32 triIdx,
|
||||
const PxVec4& triBarycentric);
|
||||
void removeClothAttachment(Sc::DeformableSurfaceCore* otherCore, PxU32 handle);
|
||||
|
||||
void addMaterial(const PxU16 handle);
|
||||
void clearMaterials();
|
||||
PxActor* getPxActor() const;
|
||||
void attachShapeCore(ShapeCore* shapeCore);
|
||||
void onShapeChange(ShapeCore& shape, ShapeChangeNotifyFlags notifyFlags);
|
||||
PX_FORCE_INLINE PxU64& getGpuMemStat() { return mGpuMemStat; }
|
||||
|
||||
DeformableSurfaceSim* getSim() const;
|
||||
PX_FORCE_INLINE const Dy::DeformableSurfaceCore& getCore() const { return mCore; }
|
||||
PX_FORCE_INLINE Dy::DeformableSurfaceCore& getCore() { return mCore; }
|
||||
|
||||
private:
|
||||
Dy::DeformableSurfaceCore mCore;
|
||||
PxU64 mGpuMemStat;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
} // namespace physx
|
||||
|
||||
#endif // PX_SUPPORT_GPU_PHYSX
|
||||
#endif // SC_DEFORMABLE_SURFACE_CORE
|
||||
176
engine/third_party/physx/source/simulationcontroller/include/ScDeformableVolumeCore.h
vendored
Normal file
176
engine/third_party/physx/source/simulationcontroller/include/ScDeformableVolumeCore.h
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_DEFORMABLE_VOLUME_CORE_H
|
||||
#define SC_DEFORMABLE_VOLUME_CORE_H
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
#include "PxDeformableVolume.h"
|
||||
#include "DyDeformableVolumeCore.h"
|
||||
#include "foundation/PxAssert.h"
|
||||
#include "ScActorCore.h"
|
||||
#include "ScShapeCore.h"
|
||||
#include "PxFiltering.h"
|
||||
#include "ScRigidCore.h" //KS - needed for ShapeChangeNotifyFlags. Move to a shared header
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
|
||||
class DeformableVolumeSim;
|
||||
class BodyCore;
|
||||
class DeformableSurfaceCore;
|
||||
class ParticleSystemCore;
|
||||
|
||||
class DeformableVolumeCore : public ActorCore
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
DeformableVolumeCore(const PxEMPTY) : ActorCore(PxEmpty){}
|
||||
//~PX_SERIALIZATION
|
||||
DeformableVolumeCore();
|
||||
~DeformableVolumeCore();
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// PxActor API
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
void setActorFlags(PxActorFlags flags);
|
||||
PxActorFlags getActorFlags() const { return mCore.actorFlags; }
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// PxDeformableBody API
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
void setBodyFlags(PxDeformableBodyFlags flags);
|
||||
PxDeformableBodyFlags getBodyFlags() const { return mCore.bodyFlags; }
|
||||
|
||||
void setLinearDamping(const PxReal linearDamping);
|
||||
PxReal getLinearDamping() const { return mCore.linearDamping; }
|
||||
|
||||
void setMaxLinearVelocity(const PxReal maxLinearVelocity);
|
||||
PxReal getMaxLinearVelocity() const { return mCore.maxLinearVelocity; }
|
||||
|
||||
void setMaxPenetrationBias(const PxReal maxPenetrationBias);
|
||||
PxReal getMaxPenetrationBias() const { return mCore.maxPenetrationBias; }
|
||||
|
||||
void setSolverIterationCounts(PxU16 c);
|
||||
PxU16 getSolverIterationCounts() const { return mCore.solverIterationCounts; }
|
||||
|
||||
void setSleepThreshold(const PxReal sleepThreshold);
|
||||
PxReal getSleepThreshold() const { return mCore.sleepThreshold; }
|
||||
|
||||
void setSettlingThreshold(const PxReal settlingThreshold);
|
||||
PxReal getSettlingThreshold() const { return mCore.settlingThreshold; }
|
||||
|
||||
void setSettlingDamping(const PxReal linearDamping);
|
||||
PxReal getSettlingDamping() const { return mCore.settlingDamping; }
|
||||
|
||||
void setSelfCollisionFilterDistance(const PxReal selfCollisionFilterDistance);
|
||||
PxReal getSelfCollisionFilterDistance() const { return mCore.selfCollisionFilterDistance; }
|
||||
|
||||
void setWakeCounter(const PxReal v);
|
||||
void setWakeCounterInternal(const PxReal v);
|
||||
PxReal getWakeCounter() const { return mCore.wakeCounter; }
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// PxDeformableBody API
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
void setVolumeFlags(PxDeformableVolumeFlags flags);
|
||||
PxDeformableVolumeFlags getVolumeFlags() const { return mCore.volumeFlags; }
|
||||
|
||||
void setSelfCollisionStressTolerance(const PxReal selfCollisionStressTolerance);
|
||||
PxReal getSelfCollisionStressTolerance() const { return mCore.selfCollisionStressTolerance; }
|
||||
|
||||
void setKinematicTargets(const PxVec4* positions);
|
||||
|
||||
PxU32 getGpuIndex() const;
|
||||
|
||||
void addParticleFilter(Sc::ParticleSystemCore* core, PxU32 particleId, PxU32 userBufferId, PxU32 tetId);
|
||||
void removeParticleFilter(Sc::ParticleSystemCore* core, PxU32 particleId, PxU32 userBufferId, PxU32 tetId);
|
||||
|
||||
PxU32 addParticleAttachment(Sc::ParticleSystemCore* core, PxU32 particleId, PxU32 userBufferId, PxU32 tetId, const PxVec4& barycentric);
|
||||
void removeParticleAttachment(Sc::ParticleSystemCore* core, PxU32 handle);
|
||||
|
||||
void addRigidFilter(Sc::BodyCore* core, PxU32 vertId);
|
||||
void removeRigidFilter(Sc::BodyCore* core, PxU32 vertId);
|
||||
|
||||
PxU32 addRigidAttachment(Sc::BodyCore* core, PxU32 vertId, const PxVec3& actorSpacePose, PxConeLimitedConstraint* constraint, bool doConversion);
|
||||
void removeRigidAttachment(Sc::BodyCore* core, PxU32 handle);
|
||||
|
||||
void addTetRigidFilter(Sc::BodyCore* core, PxU32 tetIdx);
|
||||
void removeTetRigidFilter(Sc::BodyCore* core, PxU32 tetIdx);
|
||||
|
||||
PxU32 addTetRigidAttachment(Sc::BodyCore* core, PxU32 tetIdx, const PxVec4& barycentric, const PxVec3& actorSpacePose,
|
||||
PxConeLimitedConstraint* constraint, bool doConversion);
|
||||
|
||||
void addSoftBodyFilter(Sc::DeformableVolumeCore& core, PxU32 tetIdx0, PxU32 tetIdx1);
|
||||
void removeSoftBodyFilter(Sc::DeformableVolumeCore& core, PxU32 tetIdx0, PxU32 tetIdx1);
|
||||
void addSoftBodyFilters(Sc::DeformableVolumeCore& core, PxU32* tetIndices0, PxU32* tetIndices1, PxU32 tetIndicesSize);
|
||||
void removeSoftBodyFilters(Sc::DeformableVolumeCore& core, PxU32* tetIndices0, PxU32* tetIndices1, PxU32 tetIndicesSize);
|
||||
|
||||
PxU32 addSoftBodyAttachment(Sc::DeformableVolumeCore& core, PxU32 tetIdx0, const PxVec4& triBarycentric0, PxU32 tetIdx1, const PxVec4& tetBarycentric1,
|
||||
PxConeLimitedConstraint* constraint, PxReal constraintOffset, bool doConversion);
|
||||
void removeSoftBodyAttachment(Sc::DeformableVolumeCore& core, PxU32 handle);
|
||||
|
||||
void addClothFilter(Sc::DeformableSurfaceCore& core, PxU32 triIdx, PxU32 tetIdx);
|
||||
void removeClothFilter(Sc::DeformableSurfaceCore& core, PxU32 triIdx, PxU32 tetIdx);
|
||||
|
||||
PxU32 addClothAttachment(Sc::DeformableSurfaceCore& core, PxU32 triIdx, const PxVec4& triBarycentric, PxU32 tetIdx, const PxVec4& tetBarycentric,
|
||||
PxConeLimitedConstraint* constraint, PxReal constraintOffset, bool doConversion);
|
||||
void removeClothAttachment(Sc::DeformableSurfaceCore& core, PxU32 handle);
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Internal API
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
void addMaterial(const PxU16 handle);
|
||||
void clearMaterials();
|
||||
PxActor* getPxActor() const;
|
||||
void attachShapeCore(ShapeCore* shapeCore);
|
||||
void attachSimulationMesh(PxTetrahedronMesh* simulationMesh, PxDeformableVolumeAuxData* simulationState);
|
||||
void onShapeChange(ShapeCore& shape, ShapeChangeNotifyFlags notifyFlags);
|
||||
PX_FORCE_INLINE PxU64& getGpuMemStat() { return mGpuMemStat; }
|
||||
|
||||
DeformableVolumeSim* getSim() const;
|
||||
PX_FORCE_INLINE const Dy::DeformableVolumeCore& getCore() const { return mCore; }
|
||||
PX_FORCE_INLINE Dy::DeformableVolumeCore& getCore() { return mCore; }
|
||||
|
||||
private:
|
||||
Dy::DeformableVolumeCore mCore;
|
||||
PxU64 mGpuMemStat;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
} // namespace physx
|
||||
|
||||
#endif // PX_SUPPORT_GPU_PHYSX
|
||||
#endif // SC_DEFORMABLE_VOLUME_CORE_H
|
||||
123
engine/third_party/physx/source/simulationcontroller/include/ScIterators.h
vendored
Normal file
123
engine/third_party/physx/source/simulationcontroller/include/ScIterators.h
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ITERATORS_H
|
||||
#define SC_ITERATORS_H
|
||||
|
||||
#include "foundation/PxVec3.h"
|
||||
#include "PxContact.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxShape;
|
||||
class PxsContactManagerOutputIterator;
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
class ShapeSimBase;
|
||||
class ElementSimInteraction;
|
||||
class ActorSim;
|
||||
|
||||
struct Contact
|
||||
{
|
||||
Contact()
|
||||
: normal(0.0f)
|
||||
, point(0.0f)
|
||||
, separation(0.0f)
|
||||
, normalForce(0.0f)
|
||||
{}
|
||||
|
||||
PxVec3 normal;
|
||||
PxVec3 point;
|
||||
PxShape* shape0;
|
||||
PxShape* shape1;
|
||||
PxReal separation;
|
||||
PxReal normalForce;
|
||||
PxU32 faceIndex0; // these are the external indices
|
||||
PxU32 faceIndex1;
|
||||
bool normalForceAvailable;
|
||||
};
|
||||
|
||||
struct FrictionAnchor
|
||||
{
|
||||
PxVec3 normal;
|
||||
PxVec3 point;
|
||||
PxVec3 impulse;
|
||||
};
|
||||
|
||||
class ContactIterator
|
||||
{
|
||||
public:
|
||||
|
||||
class Pair
|
||||
{
|
||||
public:
|
||||
Pair() : mIter(NULL, NULL, NULL, 0, 0), mAnchorIter(NULL, NULL, 0) {}
|
||||
Pair(const void*& contactPatches, const void*& contactPoints, const void*& frictionPatches, const PxU32 /*contactDataSize*/, const PxReal*& forces, PxU32 numContacts, PxU32 numPatches, ShapeSimBase& shape0, ShapeSimBase& shape1, ActorSim* actor0, ActorSim* actor1);
|
||||
Contact* getNextContact();
|
||||
FrictionAnchor* getNextFrictionAnchor();
|
||||
PxActor* getActor0() { return mActor0; }
|
||||
PxActor* getActor1() { return mActor1; }
|
||||
|
||||
private:
|
||||
PxU32 mIndex;
|
||||
PxU32 mNumContacts;
|
||||
PxContactStreamIterator mIter;
|
||||
PxFrictionAnchorStreamIterator mAnchorIter;
|
||||
const PxReal* mForces;
|
||||
Contact mCurrentContact;
|
||||
FrictionAnchor mCurrentAnchor;
|
||||
PxActor* mActor0;
|
||||
PxActor* mActor1;
|
||||
};
|
||||
|
||||
ContactIterator() {}
|
||||
explicit ContactIterator(ElementSimInteraction** first, ElementSimInteraction** last, PxsContactManagerOutputIterator& outputs): mCurrent(first), mLast(last), mOffset(0), mOutputs(&outputs)
|
||||
{
|
||||
if ((!first) || (!last) || (first == last))
|
||||
{
|
||||
mCurrent = NULL;
|
||||
mLast = NULL;
|
||||
}
|
||||
}
|
||||
Pair* getNextPair();
|
||||
private:
|
||||
ElementSimInteraction** mCurrent;
|
||||
ElementSimInteraction** mLast;
|
||||
Pair mCurrentPair;
|
||||
PxU32 mOffset;
|
||||
PxsContactManagerOutputIterator* mOutputs;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
154
engine/third_party/physx/source/simulationcontroller/include/ScParticleSystemCore.h
vendored
Normal file
154
engine/third_party/physx/source/simulationcontroller/include/ScParticleSystemCore.h
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_PARTICLESYSTEM_CORE_H
|
||||
#define SC_PARTICLESYSTEM_CORE_H
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
#include "PxParticleSystem.h"
|
||||
#include "foundation/PxAssert.h"
|
||||
#include "ScActorCore.h"
|
||||
#include "ScShapeCore.h"
|
||||
#include "PxFiltering.h"
|
||||
#include "DyParticleSystem.h"
|
||||
#include "ScParticleSystemShapeCore.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class ParticleSystemSim;
|
||||
class BodyCore;
|
||||
|
||||
class ParticleSystemCore : public ActorCore
|
||||
{
|
||||
// PX_SERIALIZATION
|
||||
public:
|
||||
ParticleSystemCore(const PxEMPTY) : ActorCore(PxEmpty) {}
|
||||
//~PX_SERIALIZATION
|
||||
ParticleSystemCore(PxActorType::Enum actorType);
|
||||
~ParticleSystemCore();
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// External API
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
PxReal getSleepThreshold() const;
|
||||
void setSleepThreshold(const PxReal v);
|
||||
|
||||
PxReal getRestOffset() const;
|
||||
void setRestOffset(const PxReal v);
|
||||
|
||||
PxReal getContactOffset() const;
|
||||
void setContactOffset(const PxReal v);
|
||||
|
||||
PxReal getParticleContactOffset() const;
|
||||
void setParticleContactOffset(const PxReal v);
|
||||
|
||||
PxReal getSolidRestOffset() const;
|
||||
void setSolidRestOffset(const PxReal v);
|
||||
|
||||
PxReal getFluidRestOffset() const;
|
||||
void setFluidRestOffset(const PxReal v);
|
||||
|
||||
PxReal getMaxDepenetrationVelocity() const;
|
||||
void setMaxDepenetrationVelocity(const PxReal v);
|
||||
|
||||
PxReal getMaxVelocity() const;
|
||||
void setMaxVelocity(const PxReal v);
|
||||
|
||||
PxParticleSystemCallback* getParticleSystemCallback() const;
|
||||
void setParticleSystemCallback(PxParticleSystemCallback* callback);
|
||||
|
||||
PxReal getFluidBoundaryDensityScale() const;
|
||||
void setFluidBoundaryDensityScale(const PxReal v);
|
||||
|
||||
PxU32 getGridSizeX() const;
|
||||
void setGridSizeX(const PxU32 v);
|
||||
|
||||
PxU32 getGridSizeY() const;
|
||||
void setGridSizeY(const PxU32 v);
|
||||
|
||||
PxU32 getGridSizeZ() const;
|
||||
void setGridSizeZ(const PxU32 v);
|
||||
|
||||
PxU16 getSolverIterationCounts() const { return mShapeCore.getLLCore().solverIterationCounts; }
|
||||
void setSolverIterationCounts(PxU16 c);
|
||||
|
||||
PxReal getWakeCounter() const;
|
||||
void setWakeCounter(const PxReal v);
|
||||
void setWakeCounterInternal(const PxReal v);
|
||||
|
||||
bool isSleeping() const;
|
||||
void wakeUp(PxReal wakeCounter);
|
||||
void putToSleep();
|
||||
|
||||
PxActor* getPxActor() const;
|
||||
|
||||
|
||||
PxParticleFlags getFlags() const { return mShapeCore.getLLCore().mFlags; }
|
||||
|
||||
void setFlags(PxParticleFlags flags);
|
||||
|
||||
PxParticleLockFlags getLockFlags() const { return mShapeCore.getLLCore().mLockFlags; }
|
||||
|
||||
void setLockFlags(PxParticleLockFlags lockFlags) { mShapeCore.getLLCore().mLockFlags = lockFlags; }
|
||||
|
||||
void setWind(const PxVec3& wind) {mShapeCore.getLLCore().mWind = wind;}
|
||||
|
||||
PxVec3 getWind() const { return mShapeCore.getLLCore().mWind; }
|
||||
|
||||
PxSparseGridParams getSparseGridParams() const { return mShapeCore.getLLCore().sparseGridParams; }
|
||||
void setSparseGridParams(const PxSparseGridParams& params) { mShapeCore.getLLCore().sparseGridParams = params; }
|
||||
|
||||
void addRigidAttachment(Sc::BodyCore* core);
|
||||
|
||||
void removeRigidAttachment(Sc::BodyCore* core);
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Internal API
|
||||
//---------------------------------------------------------------------------------
|
||||
public:
|
||||
ParticleSystemSim* getSim() const;
|
||||
|
||||
PX_FORCE_INLINE const ParticleSystemShapeCore& getShapeCore() const { return mShapeCore; }
|
||||
PX_FORCE_INLINE ParticleSystemShapeCore& getShapeCore() { return mShapeCore; }
|
||||
|
||||
void setDirty(const bool dirty);
|
||||
|
||||
private:
|
||||
//ParticleSystemSim* mSim;
|
||||
ParticleSystemShapeCore mShapeCore;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
127
engine/third_party/physx/source/simulationcontroller/include/ScPhysics.h
vendored
Normal file
127
engine/third_party/physx/source/simulationcontroller/include/ScPhysics.h
vendored
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-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_PHYSICS_H
|
||||
#define SC_PHYSICS_H
|
||||
|
||||
#include "PxPhysics.h"
|
||||
#include "PxScene.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "foundation/PxBasicTemplates.h"
|
||||
#include "PxActor.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
class PxMaterial;
|
||||
class PxTolerancesScale;
|
||||
struct PxvOffsetTable;
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
class PxPhysXGpu;
|
||||
#endif
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
class Scene;
|
||||
class StaticCore;
|
||||
class RigidCore;
|
||||
class BodyCore;
|
||||
class ArticulationCore;
|
||||
class ArticulationJointCore;
|
||||
class ConstraintCore;
|
||||
class ShapeCore;
|
||||
|
||||
struct OffsetTable
|
||||
{
|
||||
PX_FORCE_INLINE OffsetTable() {}
|
||||
|
||||
PX_FORCE_INLINE PxShape* convertScShape2Px(ShapeCore* sc) const { return PxPointerOffset<PxShape*>(sc, scShape2Px); }
|
||||
PX_FORCE_INLINE const PxShape* convertScShape2Px(const ShapeCore* sc) const { return PxPointerOffset<const PxShape*>(sc, scShape2Px); }
|
||||
|
||||
PX_FORCE_INLINE PxConstraint* convertScConstraint2Px(ConstraintCore* sc) const { return PxPointerOffset<PxConstraint*>(sc, scConstraint2Px); }
|
||||
PX_FORCE_INLINE const PxConstraint* convertScConstraint2Px(const ConstraintCore* sc) const { return PxPointerOffset<const PxConstraint*>(sc, scConstraint2Px); }
|
||||
|
||||
PX_FORCE_INLINE PxArticulationReducedCoordinate* convertScArticulation2Px(ArticulationCore* sc) const
|
||||
{
|
||||
return PxPointerOffset<PxArticulationReducedCoordinate*>(sc, scArticulationRC2Px);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE const PxArticulationReducedCoordinate* convertScArticulation2Px(const ArticulationCore* sc) const
|
||||
{
|
||||
return PxPointerOffset<const PxArticulationReducedCoordinate*>(sc, scArticulationRC2Px);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxArticulationJointReducedCoordinate* convertScArticulationJoint2Px(ArticulationJointCore* sc) const
|
||||
{
|
||||
return PxPointerOffset<PxArticulationJointReducedCoordinate*>(sc, scArticulationJointRC2Px);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE const PxArticulationJointReducedCoordinate* convertScArticulationJoint2Px(const ArticulationJointCore* sc) const
|
||||
{
|
||||
return PxPointerOffset<const PxArticulationJointReducedCoordinate*>(sc, scArticulationJointRC2Px);
|
||||
}
|
||||
|
||||
ptrdiff_t scRigidStatic2PxActor;
|
||||
ptrdiff_t scRigidDynamic2PxActor;
|
||||
ptrdiff_t scArticulationLink2PxActor;
|
||||
ptrdiff_t scDeformableSurface2PxActor;
|
||||
ptrdiff_t scDeformableVolume2PxActor;
|
||||
ptrdiff_t scPBDParticleSystem2PxActor;
|
||||
ptrdiff_t scShape2Px;
|
||||
ptrdiff_t scArticulationRC2Px;
|
||||
ptrdiff_t scArticulationJointRC2Px;
|
||||
ptrdiff_t scConstraint2Px;
|
||||
|
||||
ptrdiff_t scCore2PxActor[PxActorType::eACTOR_COUNT];
|
||||
};
|
||||
extern OffsetTable gOffsetTable;
|
||||
|
||||
class Physics : public PxUserAllocated
|
||||
{
|
||||
public:
|
||||
PX_FORCE_INLINE static Physics& getInstance() { return *mInstance; }
|
||||
|
||||
Physics(const PxTolerancesScale&, const PxvOffsetTable& pxvOffsetTable);
|
||||
~Physics();
|
||||
|
||||
PX_FORCE_INLINE const PxTolerancesScale& getTolerancesScale() const { return mScale; }
|
||||
|
||||
private:
|
||||
PxTolerancesScale mScale;
|
||||
static Physics* mInstance;
|
||||
|
||||
public:
|
||||
static const PxReal sWakeCounterOnCreation;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
88
engine/third_party/physx/source/simulationcontroller/include/ScRigidCore.h
vendored
Normal file
88
engine/third_party/physx/source/simulationcontroller/include/ScRigidCore.h
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_RIGID_CORE_H
|
||||
#define SC_RIGID_CORE_H
|
||||
|
||||
#include "ScActorCore.h"
|
||||
#include "ScPhysics.h"
|
||||
#include "PxvDynamics.h"
|
||||
#include "PxShape.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class RigidSim;
|
||||
class ShapeCore;
|
||||
|
||||
struct ShapeChangeNotifyFlag
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eGEOMETRY = 1<<0,
|
||||
eSHAPE2BODY = 1<<1,
|
||||
eFILTERDATA = 1<<2,
|
||||
eCONTACTOFFSET = 1<<3,
|
||||
eRESTOFFSET = 1<<4,
|
||||
eRESET_FILTERING = 1<<5
|
||||
};
|
||||
};
|
||||
typedef PxFlags<ShapeChangeNotifyFlag::Enum, PxU32> ShapeChangeNotifyFlags;
|
||||
PX_FLAGS_OPERATORS(ShapeChangeNotifyFlag::Enum,PxU32)
|
||||
|
||||
class RigidCore : public ActorCore
|
||||
{
|
||||
public:
|
||||
|
||||
PX_FORCE_INLINE PxActor* getPxActor() const
|
||||
{
|
||||
return PxPointerOffset<PxActor*>(const_cast<RigidCore*>(this), gOffsetTable.scCore2PxActor[getActorCoreType()]);
|
||||
}
|
||||
|
||||
void addShapeToScene(ShapeCore& shape);
|
||||
void removeShapeFromScene(ShapeCore& shape, bool wakeOnLostTouch);
|
||||
void onShapeChange(ShapeCore& shape, ShapeChangeNotifyFlags notifyFlags);
|
||||
void onShapeFlagsChange(ShapeCore& shape, PxShapeFlags oldShapeFlags);
|
||||
void unregisterShapeFromNphase(ShapeCore& shapeCore);
|
||||
void registerShapeInNphase(ShapeCore& shapeCore);
|
||||
|
||||
RigidSim* getSim() const;
|
||||
|
||||
PxU32 getRigidID() const;
|
||||
protected:
|
||||
RigidCore(const PxEMPTY) : ActorCore(PxEmpty) {}
|
||||
RigidCore(PxActorType::Enum type);
|
||||
~RigidCore();
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
1177
engine/third_party/physx/source/simulationcontroller/include/ScScene.h
vendored
Normal file
1177
engine/third_party/physx/source/simulationcontroller/include/ScScene.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
132
engine/third_party/physx/source/simulationcontroller/include/ScShapeCore.h
vendored
Normal file
132
engine/third_party/physx/source/simulationcontroller/include/ScShapeCore.h
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_SHAPE_CORE_H
|
||||
#define SC_SHAPE_CORE_H
|
||||
|
||||
#include "foundation/PxUtilities.h"
|
||||
#include "PxvGeometry.h"
|
||||
#include "PxFiltering.h"
|
||||
#include "PxShape.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxShape; // PT: TODO: fw decl of higher-level class isn't great
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
class ShapeSim;
|
||||
|
||||
class ShapeCore
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
ShapeCore(const PxEMPTY);
|
||||
void exportExtraData(PxSerializationContext& stream);
|
||||
void importExtraData(PxDeserializationContext& context);
|
||||
void resolveReferences(PxDeserializationContext& context);
|
||||
void resolveMaterialReference(PxU32 materialTableIndex, PxU16 materialIndex);
|
||||
//~PX_SERIALIZATION
|
||||
ShapeCore( const PxGeometry& geometry, PxShapeFlags shapeFlags,
|
||||
const PxU16* materialIndices, PxU16 materialCount, bool isExclusive,
|
||||
PxShapeCoreFlag::Enum coreFlags = PxShapeCoreFlag::Enum(0));
|
||||
|
||||
~ShapeCore();
|
||||
|
||||
PX_FORCE_INLINE PxGeometryType::Enum getGeometryType() const { return mCore.mGeometry.getType(); }
|
||||
PxShape* getPxShape();
|
||||
const PxShape* getPxShape() const;
|
||||
|
||||
PX_FORCE_INLINE const GeometryUnion& getGeometryUnion() const { return mCore.mGeometry; }
|
||||
PX_FORCE_INLINE const PxGeometry& getGeometry() const { return mCore.mGeometry.getGeometry(); }
|
||||
void setGeometry(const PxGeometry& geom);
|
||||
|
||||
PxU16 getNbMaterialIndices() const;
|
||||
const PxU16* getMaterialIndices() const;
|
||||
void setMaterialIndices(const PxU16* materialIndices, PxU16 materialIndexCount);
|
||||
|
||||
PX_FORCE_INLINE const PxTransform& getShape2Actor() const { return mCore.getTransform(); }
|
||||
PX_FORCE_INLINE void setShape2Actor(const PxTransform& s2b) { mCore.setTransform(s2b); }
|
||||
|
||||
PX_FORCE_INLINE const PxFilterData& getSimulationFilterData() const { return mSimulationFilterData; }
|
||||
PX_FORCE_INLINE void setSimulationFilterData(const PxFilterData& data) { mSimulationFilterData = data; }
|
||||
|
||||
PX_FORCE_INLINE PxReal getContactOffset() const { return mCore.mContactOffset; }
|
||||
void setContactOffset(PxReal offset);
|
||||
|
||||
PX_FORCE_INLINE PxReal getRestOffset() const { return mCore.mRestOffset; }
|
||||
PX_FORCE_INLINE void setRestOffset(PxReal offset) { mCore.mRestOffset = offset; }
|
||||
|
||||
PX_FORCE_INLINE PxReal getDensityForFluid() const { return mCore.getDensityForFluid(); }
|
||||
PX_FORCE_INLINE void setDensityForFluid(PxReal densityForFluid) { mCore.setDensityForFluid(densityForFluid); }
|
||||
|
||||
PX_FORCE_INLINE PxReal getTorsionalPatchRadius() const { return mCore.mTorsionalRadius; }
|
||||
PX_FORCE_INLINE void setTorsionalPatchRadius(PxReal tpr) { mCore.mTorsionalRadius = tpr; }
|
||||
|
||||
PX_FORCE_INLINE PxReal getMinTorsionalPatchRadius() const {return mCore.mMinTorsionalPatchRadius; }
|
||||
PX_FORCE_INLINE void setMinTorsionalPatchRadius(PxReal radius) { mCore.mMinTorsionalPatchRadius = radius; }
|
||||
|
||||
PX_FORCE_INLINE PxShapeFlags getFlags() const { return PxShapeFlags(mCore.mShapeFlags); }
|
||||
PX_FORCE_INLINE void setFlags(PxShapeFlags f) { mCore.mShapeFlags = f; }
|
||||
|
||||
PX_FORCE_INLINE const PxsShapeCore& getCore() const { return mCore; }
|
||||
static PX_FORCE_INLINE size_t getCoreOffset() { return PX_OFFSET_OF(ShapeCore, mCore); }
|
||||
static PX_FORCE_INLINE ShapeCore& getCore(PxsShapeCore& core)
|
||||
{
|
||||
return *reinterpret_cast<ShapeCore*>(reinterpret_cast<PxU8*>(&core) - getCoreOffset());
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE ShapeSim* getExclusiveSim() const
|
||||
{
|
||||
return mExclusiveSim;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setExclusiveSim(ShapeSim* sim)
|
||||
{
|
||||
if(!sim || mCore.mShapeCoreFlags.isSet(PxShapeCoreFlag::eIS_EXCLUSIVE))
|
||||
mExclusiveSim = sim;
|
||||
}
|
||||
|
||||
#if PX_WINDOWS_FAMILY // PT: to avoid "error: offset of on non-standard-layout type" on Linux
|
||||
protected:
|
||||
#endif
|
||||
PxFilterData mSimulationFilterData; // Simulation filter data
|
||||
PxsShapeCore PX_ALIGN(16, mCore);
|
||||
ShapeSim* mExclusiveSim; //only set if shape is exclusive
|
||||
#if PX_WINDOWS_FAMILY // PT: to avoid "error: offset of on non-standard-layout type" on Linux
|
||||
public:
|
||||
#endif
|
||||
const char* mName; // PT: moved here from NpShape to fill padding bytes
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
65
engine/third_party/physx/source/simulationcontroller/include/ScSqBoundsSync.h
vendored
Normal file
65
engine/third_party/physx/source/simulationcontroller/include/ScSqBoundsSync.h
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_SQ_BOUNDS_SYNC_H
|
||||
#define SC_SQ_BOUNDS_SYNC_H
|
||||
|
||||
#include "foundation/PxSimpleTypes.h"
|
||||
#include "foundation/PxBitMap.h"
|
||||
|
||||
#include "PxSceneQuerySystem.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxBounds3;
|
||||
class PxRigidBody;
|
||||
class PxShape;
|
||||
|
||||
typedef PxSQPrunerHandle ScPrunerHandle;
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
// PT: TODO: revisit the need for a virtual interface
|
||||
struct SqRefFinder
|
||||
{
|
||||
virtual ScPrunerHandle find(const PxRigidBody* body, const PxShape* shape, PxU32& prunerIndex) = 0;
|
||||
|
||||
virtual ~SqRefFinder() {}
|
||||
};
|
||||
|
||||
// PT: TODO: revisit the need for a virtual interface
|
||||
struct SqBoundsSync
|
||||
{
|
||||
virtual void sync(PxU32 prunerIndex, const ScPrunerHandle* handles, const PxU32* boundsIndices, const PxBounds3* bounds, const PxTransform32* transforms, PxU32 count, const PxBitMap& ignoredIndices) = 0;
|
||||
|
||||
virtual ~SqBoundsSync() {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
70
engine/third_party/physx/source/simulationcontroller/include/ScStaticCore.h
vendored
Normal file
70
engine/third_party/physx/source/simulationcontroller/include/ScStaticCore.h
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_STATIC_CORE_H
|
||||
#define SC_STATIC_CORE_H
|
||||
|
||||
#include "ScRigidCore.h"
|
||||
#include "PxvDynamics.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class StaticSim;
|
||||
|
||||
class StaticCore : public RigidCore
|
||||
{
|
||||
public:
|
||||
StaticCore(const PxTransform& actor2World): RigidCore(PxActorType::eRIGID_STATIC)
|
||||
{
|
||||
mCore.body2World = actor2World;
|
||||
mCore.mFlags = PxRigidBodyFlags();
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE const PxTransform& getActor2World() const { return mCore.body2World; }
|
||||
void setActor2World(const PxTransform& actor2World);
|
||||
|
||||
PX_FORCE_INLINE PxsRigidCore& getCore() { return mCore; }
|
||||
static PX_FORCE_INLINE size_t getCoreOffset() { return PX_OFFSET_OF_RT(StaticCore, mCore);}
|
||||
|
||||
StaticCore(const PxEMPTY) : RigidCore(PxEmpty), mCore(PxEmpty) {}
|
||||
|
||||
StaticSim* getSim() const;
|
||||
|
||||
PX_FORCE_INLINE void onOriginShift(const PxVec3& shift) { mCore.body2World.p -= shift; }
|
||||
|
||||
private:
|
||||
PxsRigidCore mCore;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
161
engine/third_party/physx/source/simulationcontroller/src/ScActorCore.cpp
vendored
Normal file
161
engine/third_party/physx/source/simulationcontroller/src/ScActorCore.cpp
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScActorCore.h"
|
||||
#include "ScActorSim.h"
|
||||
#include "ScShapeCore.h"
|
||||
#include "ScShapeSim.h"
|
||||
#include "ScBodySim.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::ActorCore::ActorCore(PxActorType::Enum actorType, PxU8 actorFlags, PxClientID owner, PxDominanceGroup dominanceGroup) :
|
||||
mSim (NULL),
|
||||
mPackedIDs ((PxU32(owner)<<SC_FILTERING_ID_SHIFT_BIT)|SC_FILTERING_ID_MASK),
|
||||
mActorFlags (actorFlags),
|
||||
mActorType (PxU8(actorType)),
|
||||
mDominanceGroup (dominanceGroup)
|
||||
{
|
||||
PX_ASSERT((actorType & 0xff) == actorType);
|
||||
PX_ASSERT(!hasAggregateID());
|
||||
}
|
||||
|
||||
Sc::ActorCore::~ActorCore()
|
||||
{
|
||||
}
|
||||
|
||||
void Sc::ActorCore::setActorFlags(PxActorFlags af)
|
||||
{
|
||||
const PxActorFlags old = mActorFlags;
|
||||
if(af!=old)
|
||||
{
|
||||
mActorFlags = af;
|
||||
|
||||
if(mSim)
|
||||
mSim->postActorFlagChange(old, af);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ActorCore::setDominanceGroup(PxDominanceGroup g)
|
||||
{
|
||||
PX_ASSERT(g<32);
|
||||
|
||||
const bool b = mDominanceGroup.isBitSet()!=0;
|
||||
mDominanceGroup = PxBitAndByte(PxU8(g) & 31, b);
|
||||
|
||||
if(mSim)
|
||||
{
|
||||
//force all related interactions to refresh, so they fetch new dominance values.
|
||||
mSim->setActorsInteractionsDirty(InteractionDirtyFlag::eDOMINANCE, NULL, InteractionFlag::eRB_ELEMENT);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ActorCore::setAggregateID(PxU32 id)
|
||||
{
|
||||
if(id==0xffffffff)
|
||||
{
|
||||
if(hasAggregateID())
|
||||
{
|
||||
// PT: this was an aggregate ID and we want to disable it.
|
||||
mDominanceGroup.clearBit();
|
||||
|
||||
resetID();
|
||||
}
|
||||
else
|
||||
{
|
||||
// PT: this was not an aggregate ID. Make sure it wasn't an env ID either.
|
||||
PX_ASSERT((mPackedIDs & SC_FILTERING_ID_MASK) == SC_FILTERING_ID_MASK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PX_ASSERT(id<SC_FILTERING_ID_MAX);
|
||||
|
||||
// PT: we want to setup an aggregate ID.
|
||||
if(hasAggregateID())
|
||||
{
|
||||
// PT: this was already an aggregate ID and we want to update it.
|
||||
}
|
||||
else
|
||||
{
|
||||
// PT: this was not an aggregate ID. Make sure it wasn't an env ID either.
|
||||
PX_ASSERT((mPackedIDs & SC_FILTERING_ID_MASK) == SC_FILTERING_ID_MASK);
|
||||
|
||||
mDominanceGroup.setBit();
|
||||
}
|
||||
|
||||
setID(id);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ActorCore::setEnvID(PxU32 id)
|
||||
{
|
||||
if(id==0xffffffff)
|
||||
{
|
||||
// PT: we want to disable the env ID
|
||||
if(hasAggregateID())
|
||||
{
|
||||
// PT: this is an aggregate ID => env ID is already disabled.
|
||||
}
|
||||
else
|
||||
{
|
||||
// PT: this is not an aggregate ID => disable env ID.
|
||||
resetID();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PX_ASSERT(id<SC_FILTERING_ID_MAX);
|
||||
|
||||
// PT: we want to setup an env ID.
|
||||
if(hasAggregateID())
|
||||
{
|
||||
// PT: this is already an aggregate ID, invalid case
|
||||
PX_ASSERT(!"Invalid case, aggregated actors cannot have their own env ID. Setup the env ID on the owner aggregate.");
|
||||
}
|
||||
else
|
||||
{
|
||||
setID(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ActorCore::reinsertShapes()
|
||||
{
|
||||
PX_ASSERT(mSim);
|
||||
if(!mSim)
|
||||
return;
|
||||
|
||||
PxU32 nbElems = mSim->getNbElements();
|
||||
ElementSim** elems = mSim->getElements();
|
||||
while (nbElems--)
|
||||
{
|
||||
ShapeSim* current = static_cast<ShapeSim*>(*elems++);
|
||||
current->reinsertBroadPhase();
|
||||
}
|
||||
}
|
||||
252
engine/third_party/physx/source/simulationcontroller/src/ScActorPair.h
vendored
Normal file
252
engine/third_party/physx/source/simulationcontroller/src/ScActorPair.h
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ACTOR_PAIR_H
|
||||
#define SC_ACTOR_PAIR_H
|
||||
|
||||
#include "ScRigidSim.h"
|
||||
#include "ScContactStream.h"
|
||||
#include "ScNPhaseCore.h"
|
||||
#include "foundation/PxErrors.h"
|
||||
#include "foundation/PxFoundation.h"
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#include "foundation/PxSimpleTypes.h"
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
#include "ScDeformableSurfaceSim.h"
|
||||
#include "ScDeformableVolumeSim.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class ActorPairContactReportData
|
||||
{
|
||||
public:
|
||||
ActorPairContactReportData() :
|
||||
mStrmResetStamp (0xffffffff),
|
||||
mActorAID (0xffffffff),
|
||||
mActorBID (0xffffffff),
|
||||
mPxActorA (NULL),
|
||||
mPxActorB (NULL)
|
||||
{}
|
||||
|
||||
ContactStreamManager mContactStreamManager;
|
||||
PxU32 mStrmResetStamp;
|
||||
PxU32 mActorAID;
|
||||
PxU32 mActorBID;
|
||||
PxActor* mPxActorA;
|
||||
PxActor* mPxActorB;
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Class shared by all shape interactions for a pair of actors.
|
||||
|
||||
This base class is used if no shape pair of an actor pair has contact reports requested.
|
||||
*/
|
||||
class ActorPair
|
||||
{
|
||||
public:
|
||||
|
||||
enum ActorPairFlags
|
||||
{
|
||||
eIS_REPORT_PAIR = (1<<0),
|
||||
eIS_IN_CONTACT_REPORT_ACTOR_PAIR_SET = (1<<1), // PT: whether the pair is already stored in the 'ContactReportActorPairSet' or not
|
||||
eMAX = (1<<2)
|
||||
};
|
||||
|
||||
PX_FORCE_INLINE ActorPair() : mRefCount(0), mTouchCount_internalFlags(0) {}
|
||||
PX_FORCE_INLINE ~ActorPair() {}
|
||||
|
||||
PX_FORCE_INLINE PxIntBool isReportPair() const { return (getFlags() & eIS_REPORT_PAIR); }
|
||||
|
||||
PX_FORCE_INLINE void incTouchCount() { setTouchCount(getTouchCount() + 1); PX_ASSERT(getTouchCount()); }
|
||||
PX_FORCE_INLINE void decTouchCount() { PX_ASSERT(getTouchCount()); setTouchCount(getTouchCount() -1); }
|
||||
PX_FORCE_INLINE PxU32 getTouchCount() const { return mTouchCount_internalFlags >> sTouchCountShift; }
|
||||
|
||||
PX_FORCE_INLINE void incRefCount() { ++mRefCount; PX_ASSERT(mRefCount>0); }
|
||||
PX_FORCE_INLINE PxU32 decRefCount() { PX_ASSERT(mRefCount>0); return --mRefCount; }
|
||||
PX_FORCE_INLINE PxU32 getRefCount() const { return mRefCount; }
|
||||
|
||||
private:
|
||||
ActorPair& operator=(const ActorPair&);
|
||||
|
||||
protected:
|
||||
PxU32 mRefCount;
|
||||
PxU32 mTouchCount_internalFlags;
|
||||
|
||||
PX_FORCE_INLINE PxU32 getFlags() const { return mTouchCount_internalFlags & sFlagMask; }
|
||||
PX_FORCE_INLINE void raiseFlags(PxU32 flags) { PX_ASSERT(flags < ActorPairFlags::eMAX); mTouchCount_internalFlags |= flags; }
|
||||
PX_FORCE_INLINE void clearFlags(PxU32 flags);
|
||||
PX_FORCE_INLINE void setTouchCount(PxU32 count);
|
||||
|
||||
public:
|
||||
static const PxU32 sFlagMask = (ActorPairFlags::eMAX - 1);
|
||||
static const PxU32 sTouchCountShift = 2; // shift necessary to extract the touch count
|
||||
|
||||
PX_COMPILE_TIME_ASSERT(ActorPairFlags::eMAX == (1 << sTouchCountShift)); // if this breaks please adjust the sTouchCountShift above.
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Class shared by all shape interactions for a pair of actors if contact reports are requested.
|
||||
|
||||
This class is used if at least one shape pair of an actor pair has contact reports requested.
|
||||
|
||||
\note If a pair of actors had contact reports requested for some of the shape interactions but all of them switch to not wanting contact reports
|
||||
any longer, then the ActorPairReport instance is kept being used and won't get replaced by a simpler ActorPair instance.
|
||||
*/
|
||||
class ActorPairReport : public ActorPair
|
||||
{
|
||||
PX_NOCOPY(ActorPairReport)
|
||||
public:
|
||||
|
||||
PX_FORCE_INLINE ActorPairReport(ActorSim&, ActorSim&);
|
||||
PX_FORCE_INLINE ~ActorPairReport();
|
||||
|
||||
PX_INLINE ContactStreamManager& createContactStreamManager(NPhaseCore&);
|
||||
PX_FORCE_INLINE ContactStreamManager& getContactStreamManager() const { PX_ASSERT(mReportData); return mReportData->mContactStreamManager; }
|
||||
PX_FORCE_INLINE ActorSim& getActorA() const { return mActorA; }
|
||||
PX_FORCE_INLINE ActorSim& getActorB() const { return mActorB; }
|
||||
PX_INLINE PxU32 getActorAID() const { PX_ASSERT(mReportData); return mReportData->mActorAID; }
|
||||
PX_INLINE PxU32 getActorBID() const { PX_ASSERT(mReportData); return mReportData->mActorBID; }
|
||||
PX_INLINE PxActor* getPxActorA() const { PX_ASSERT(mReportData); return mReportData->mPxActorA; }
|
||||
PX_INLINE PxActor* getPxActorB() const { PX_ASSERT(mReportData); return mReportData->mPxActorB; }
|
||||
PX_INLINE bool streamResetStamp(PxU32 cmpStamp);
|
||||
|
||||
PX_FORCE_INLINE PxIntBool isInContactReportActorPairSet() const { return (getFlags() & eIS_IN_CONTACT_REPORT_ACTOR_PAIR_SET); }
|
||||
PX_FORCE_INLINE void setInContactReportActorPairSet() { raiseFlags(eIS_IN_CONTACT_REPORT_ACTOR_PAIR_SET); }
|
||||
PX_FORCE_INLINE void clearInContactReportActorPairSet() { clearFlags(eIS_IN_CONTACT_REPORT_ACTOR_PAIR_SET); }
|
||||
|
||||
PX_FORCE_INLINE void createContactReportData(NPhaseCore&);
|
||||
|
||||
PX_FORCE_INLINE void convert(const ActorPair& aPair) { PX_ASSERT(!aPair.isReportPair()); setTouchCount(aPair.getTouchCount()); mRefCount = aPair.getRefCount(); }
|
||||
|
||||
PX_FORCE_INLINE static ActorPairReport& cast(ActorPair& aPair) { PX_ASSERT(aPair.isReportPair()); return static_cast<ActorPairReport&>(aPair); }
|
||||
|
||||
private:
|
||||
ActorSim& mActorA;
|
||||
ActorSim& mActorB;
|
||||
public:
|
||||
ActorPairContactReportData* mReportData;
|
||||
};
|
||||
} // namespace Sc
|
||||
|
||||
//// Sc::ActorPair implementations
|
||||
|
||||
PX_FORCE_INLINE void Sc::ActorPair::setTouchCount(PxU32 count)
|
||||
{
|
||||
PX_ASSERT(count <= (PX_MAX_U32 >> sTouchCountShift));
|
||||
if (count == (PX_MAX_U32 >> sTouchCountShift)) // we rely on inc/dec behaviour here which means we'll always pass the max value before overflowing.
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL, "Sc::ActorPair: maximum count of touching shapes per pair reached, any additional touch will introduce undefined behavior.");
|
||||
}
|
||||
|
||||
mTouchCount_internalFlags = (mTouchCount_internalFlags & sFlagMask) | (count << sTouchCountShift);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void Sc::ActorPair::clearFlags(PxU32 flags)
|
||||
{
|
||||
PX_ASSERT(flags < ActorPairFlags::eMAX);
|
||||
|
||||
PxU32 tmpFlags = getFlags();
|
||||
tmpFlags &= ~flags;
|
||||
mTouchCount_internalFlags &= ~sFlagMask;
|
||||
raiseFlags(tmpFlags);
|
||||
}
|
||||
|
||||
//// Sc::ActorPairReport implementations
|
||||
|
||||
PX_FORCE_INLINE Sc::ActorPairReport::ActorPairReport(ActorSim& actor0, ActorSim& actor1) : ActorPair(),
|
||||
mActorA (actor0),
|
||||
mActorB (actor1),
|
||||
mReportData (NULL)
|
||||
{
|
||||
PX_ASSERT(getFlags() == 0);
|
||||
raiseFlags(ActorPair::eIS_REPORT_PAIR);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE Sc::ActorPairReport::~ActorPairReport()
|
||||
{
|
||||
PX_ASSERT(mReportData == NULL);
|
||||
}
|
||||
|
||||
PX_INLINE bool Sc::ActorPairReport::streamResetStamp(PxU32 cmpStamp)
|
||||
{
|
||||
PX_ASSERT(mReportData);
|
||||
const bool ret = (cmpStamp != mReportData->mStrmResetStamp);
|
||||
mReportData->mStrmResetStamp = cmpStamp;
|
||||
return ret;
|
||||
}
|
||||
|
||||
PX_INLINE Sc::ContactStreamManager& Sc::ActorPairReport::createContactStreamManager(NPhaseCore& npCore)
|
||||
{
|
||||
// Lazy create report data
|
||||
if(!mReportData)
|
||||
createContactReportData(npCore);
|
||||
|
||||
return mReportData->mContactStreamManager;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void Sc::ActorPairReport::createContactReportData(NPhaseCore& npCore)
|
||||
{
|
||||
PX_ASSERT(!mReportData);
|
||||
Sc::ActorPairContactReportData* reportData = npCore.createActorPairContactReportData();
|
||||
mReportData = reportData;
|
||||
|
||||
if(reportData)
|
||||
{
|
||||
const ActorCore& actorCoreA = mActorA.getActorCore();
|
||||
const ActorCore& actorCoreB = mActorB.getActorCore();
|
||||
|
||||
reportData->mActorAID = mActorA.getActorID();
|
||||
reportData->mActorBID = mActorB.getActorID();
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
if (mActorA.getActorType() == PxActorType::eDEFORMABLE_VOLUME)
|
||||
reportData->mPxActorA = static_cast<const DeformableVolumeCore&>(actorCoreA).getPxActor();
|
||||
else if (mActorA.getActorType() == PxActorType::eDEFORMABLE_SURFACE)
|
||||
reportData->mPxActorA = static_cast<const DeformableSurfaceCore&>(actorCoreA).getPxActor();
|
||||
else
|
||||
#endif
|
||||
reportData->mPxActorA = static_cast<const RigidCore&>(actorCoreA).getPxActor();
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
if (mActorB.getActorType() == PxActorType::eDEFORMABLE_VOLUME)
|
||||
reportData->mPxActorB = static_cast<const DeformableVolumeCore&>(actorCoreB).getPxActor();
|
||||
else if (mActorB.getActorType() == PxActorType::eDEFORMABLE_SURFACE)
|
||||
reportData->mPxActorB = static_cast<const DeformableSurfaceCore&>(actorCoreB).getPxActor();
|
||||
else
|
||||
#endif
|
||||
reportData->mPxActorB = static_cast<const RigidCore&>(actorCoreB).getPxActor();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
167
engine/third_party/physx/source/simulationcontroller/src/ScActorSim.cpp
vendored
Normal file
167
engine/third_party/physx/source/simulationcontroller/src/ScActorSim.cpp
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScActorSim.h"
|
||||
#include "ScActorCore.h"
|
||||
#include "ScElementSim.h"
|
||||
#include "ScScene.h"
|
||||
#include "ScInteraction.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
static const PxFilterObjectType::Enum gFilterType[PxActorType::eACTOR_COUNT] =
|
||||
{
|
||||
PxFilterObjectType::eRIGID_STATIC, // PxActorType::eRIGID_STATIC
|
||||
PxFilterObjectType::eRIGID_DYNAMIC, // PxActorType::eRIGID_DYNAMIC
|
||||
PxFilterObjectType::eARTICULATION, // PxActorType::eARTICULATION_LINK
|
||||
PxFilterObjectType::eDEFORMABLE_SURFACE,// PxActorType::eDEFORMABLE_SURFACE
|
||||
PxFilterObjectType::eDEFORMABLE_VOLUME, // PxActorType::eDEFORMABLE_VOLUME
|
||||
PxFilterObjectType::ePARTICLESYSTEM, // PxActorType::ePBD_PARTICLESYSTEM
|
||||
};
|
||||
|
||||
static const PxU32 gFilterFlagEx[PxActorType::eACTOR_COUNT] =
|
||||
{
|
||||
PxFilterObjectFlagEx::eRIGID_STATIC, // PxActorType::eRIGID_STATIC
|
||||
PxFilterObjectFlagEx::eRIGID_DYNAMIC, // PxActorType::eRIGID_DYNAMIC
|
||||
PxFilterObjectFlagEx::eRIGID_DYNAMIC, // PxActorType::eARTICULATION_LINK
|
||||
PxFilterObjectFlagEx::eNON_RIGID|PxFilterObjectFlagEx::eDEFORMABLE_SURFACE, // PxActorType::eDEFORMABLE_SURFACE
|
||||
PxFilterObjectFlagEx::eNON_RIGID|PxFilterObjectFlagEx::eDEFORMABLE_VOLUME, // PxActorType::eDEFORMABLE_VOLUME
|
||||
PxFilterObjectFlagEx::eNON_RIGID|PxFilterObjectFlagEx::ePARTICLESYSTEM, // PxActorType::ePBD_PARTICLESYSTEM
|
||||
};
|
||||
|
||||
// PT: if this breaks, you need to update the above table
|
||||
PX_COMPILE_TIME_ASSERT(PxActorType::eACTOR_COUNT==6);
|
||||
|
||||
// PT: make sure that the highest flag fits into 16bit
|
||||
PX_COMPILE_TIME_ASSERT(PxFilterObjectFlagEx::eLAST<=0xffff);
|
||||
|
||||
Sc::ActorSim::ActorSim(Scene& scene, ActorCore& core) :
|
||||
mScene (scene),
|
||||
mCore (core),
|
||||
mActiveListIndex (SC_NOT_IN_SCENE_INDEX),
|
||||
mActiveCompoundListIndex(SC_NOT_IN_SCENE_INDEX),
|
||||
mNodeIndex (PX_INVALID_NODE),
|
||||
mInternalFlags (0)
|
||||
{
|
||||
core.setSim(this);
|
||||
mId = scene.getActorIDTracker().createID();
|
||||
|
||||
{
|
||||
PX_ASSERT(gFilterType[PxActorType::eRIGID_STATIC] == PxFilterObjectType::eRIGID_STATIC);
|
||||
PX_ASSERT(gFilterType[PxActorType::eRIGID_DYNAMIC] == PxFilterObjectType::eRIGID_DYNAMIC);
|
||||
PX_ASSERT(gFilterType[PxActorType::eARTICULATION_LINK] == PxFilterObjectType::eARTICULATION);
|
||||
PX_ASSERT(gFilterType[PxActorType::eDEFORMABLE_SURFACE] == PxFilterObjectType::eDEFORMABLE_SURFACE);
|
||||
PX_ASSERT(gFilterType[PxActorType::eDEFORMABLE_VOLUME] == PxFilterObjectType::eDEFORMABLE_VOLUME);
|
||||
PX_ASSERT(gFilterType[PxActorType::ePBD_PARTICLESYSTEM] == PxFilterObjectType::ePARTICLESYSTEM);
|
||||
|
||||
const PxActorType::Enum actorType = getActorType();
|
||||
|
||||
PxFilterObjectAttributes filterAttr = 0;
|
||||
setFilterObjectAttributeType(filterAttr, gFilterType[actorType]);
|
||||
|
||||
filterAttr |= gFilterFlagEx[actorType];
|
||||
|
||||
mFilterFlags = PxTo16(filterAttr);
|
||||
}
|
||||
}
|
||||
|
||||
Sc::ActorSim::~ActorSim()
|
||||
{
|
||||
mInteractions.releaseMem(*this);
|
||||
|
||||
mScene.getActorIDTracker().releaseID(mId);
|
||||
}
|
||||
|
||||
void Sc::ActorSim::registerInteractionInActor(Interaction* interaction)
|
||||
{
|
||||
const PxU32 id = mInteractions.size();
|
||||
mInteractions.pushBack(interaction, *this);
|
||||
interaction->setActorId(this, id);
|
||||
}
|
||||
|
||||
void Sc::ActorSim::unregisterInteractionFromActor(Interaction* interaction)
|
||||
{
|
||||
const PxU32 i = interaction->getActorId(this);
|
||||
PX_ASSERT(i < mInteractions.size());
|
||||
mInteractions.replaceWithLast(i);
|
||||
if(i<mInteractions.size())
|
||||
{
|
||||
if(mInteractions[i]) // ### DEFENSIVE PT: for OM-122969
|
||||
mInteractions[i]->setActorId(this, i);
|
||||
else
|
||||
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL, "Sc::ActorSim::unregisterInteractionFromActor: found null interaction!");
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ActorSim::reallocInteractions(Sc::Interaction**& mem, PxU32& capacity, PxU32 size, PxU32 requiredMinCapacity)
|
||||
{
|
||||
Interaction** newMem;
|
||||
PxU32 newCapacity;
|
||||
|
||||
if(requiredMinCapacity==0)
|
||||
{
|
||||
newCapacity = 0;
|
||||
newMem = 0;
|
||||
}
|
||||
else if(requiredMinCapacity<=INLINE_INTERACTION_CAPACITY)
|
||||
{
|
||||
newCapacity = INLINE_INTERACTION_CAPACITY;
|
||||
newMem = mInlineInteractionMem;
|
||||
}
|
||||
else
|
||||
{
|
||||
newCapacity = PxNextPowerOfTwo(requiredMinCapacity-1);
|
||||
newMem = reinterpret_cast<Interaction**>(mScene.allocatePointerBlock(newCapacity));
|
||||
}
|
||||
|
||||
PX_ASSERT(newCapacity >= requiredMinCapacity && requiredMinCapacity>=size);
|
||||
|
||||
if(mem)
|
||||
{
|
||||
PxMemCopy(newMem, mem, size*sizeof(Interaction*));
|
||||
|
||||
if(mem!=mInlineInteractionMem)
|
||||
mScene.deallocatePointerBlock(reinterpret_cast<void**>(mem), capacity);
|
||||
}
|
||||
|
||||
capacity = newCapacity;
|
||||
mem = newMem;
|
||||
}
|
||||
|
||||
void Sc::ActorSim::setActorsInteractionsDirty(InteractionDirtyFlag::Enum flag, const ActorSim* other, PxU8 interactionFlag)
|
||||
{
|
||||
PxU32 size = getActorInteractionCount();
|
||||
Interaction** interactions = getActorInteractions();
|
||||
while(size--)
|
||||
{
|
||||
Interaction* interaction = *interactions++;
|
||||
if((!other || other == &interaction->getActorSim0() || other == &interaction->getActorSim1()) && (interaction->readInteractionFlag(interactionFlag)))
|
||||
interaction->setDirty(flag);
|
||||
}
|
||||
}
|
||||
223
engine/third_party/physx/source/simulationcontroller/src/ScActorSim.h
vendored
Normal file
223
engine/third_party/physx/source/simulationcontroller/src/ScActorSim.h
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ACTOR_SIM_H
|
||||
#define SC_ACTOR_SIM_H
|
||||
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "CmPtrTable.h"
|
||||
#include "CmUtils.h"
|
||||
#include "PxActor.h"
|
||||
#include "ScInteractionFlags.h"
|
||||
#include "ScActorCore.h"
|
||||
#include "PxsSimpleIslandManager.h"
|
||||
#include "PxFiltering.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
class PxActor;
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
|
||||
#define SC_NOT_IN_SCENE_INDEX 0xffffffff // the body is not in the scene yet
|
||||
#define SC_NOT_IN_ACTIVE_LIST_INDEX 0xfffffffe // the body is in the scene but not in the active list
|
||||
|
||||
struct PxFilterObjectFlagEx : PxFilterObjectFlag
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eRIGID_STATIC = eNEXT_FREE,
|
||||
eRIGID_DYNAMIC = eNEXT_FREE<<1,
|
||||
eNON_RIGID = eNEXT_FREE<<2,
|
||||
eDEFORMABLE_SURFACE = eNEXT_FREE<<3,
|
||||
eDEFORMABLE_VOLUME = eNEXT_FREE<<4,
|
||||
ePARTICLESYSTEM = eNEXT_FREE<<5,
|
||||
|
||||
eLAST = ePARTICLESYSTEM
|
||||
};
|
||||
};
|
||||
|
||||
static const PxReal ScInternalWakeCounterResetValue = 20.0f*0.02f;
|
||||
|
||||
class Interaction;
|
||||
class ElementSim;
|
||||
class Scene;
|
||||
|
||||
class ShapeManager : public PxUserAllocated
|
||||
{
|
||||
public:
|
||||
|
||||
ShapeManager() {}
|
||||
~ShapeManager() {}
|
||||
|
||||
PX_FORCE_INLINE PxU32 getNbElements() const
|
||||
{
|
||||
return mShapes.getCount();
|
||||
}
|
||||
PX_FORCE_INLINE ElementSim** getElements()
|
||||
{
|
||||
return reinterpret_cast<ElementSim**>(mShapes.getPtrs());
|
||||
}
|
||||
PX_FORCE_INLINE ElementSim*const* getElements() const
|
||||
{
|
||||
return reinterpret_cast<ElementSim*const*>(mShapes.getPtrs());
|
||||
}
|
||||
// void onElementAttach(ElementSim& element);
|
||||
void onElementDetach(ElementSim& element);
|
||||
|
||||
Cm::PtrTable mShapes;
|
||||
};
|
||||
|
||||
class ActorSim : public ShapeManager
|
||||
{
|
||||
friend class Scene; // the scene is allowed to set the scene array index
|
||||
friend class Interaction;
|
||||
PX_NOCOPY(ActorSim)
|
||||
|
||||
public:
|
||||
|
||||
enum InternalFlags
|
||||
{
|
||||
//BF_DISABLE_GRAVITY = 1 << 0, // Don't apply the scene's gravity
|
||||
|
||||
BF_HAS_STATIC_TOUCH = 1 << 1, // Set when a body is part of an island with static contacts. Needed to be able to recalculate adaptive force if this changes
|
||||
BF_KINEMATIC_MOVED = 1 << 2, // Set when the kinematic was moved
|
||||
|
||||
BF_ON_DEATHROW = 1 << 3, // Set when the body is destroyed
|
||||
|
||||
BF_IS_IN_SLEEP_LIST = 1 << 4, // Set when the body is added to the list of bodies which were put to sleep
|
||||
BF_IS_IN_WAKEUP_LIST = 1 << 5, // Set when the body is added to the list of bodies which were woken up
|
||||
BF_SLEEP_NOTIFY = 1 << 6, // A sleep notification should be sent for this body (and not a wakeup event, even if the body is part of the woken list as well)
|
||||
BF_WAKEUP_NOTIFY = 1 << 7, // A wake up notification should be sent for this body (and not a sleep event, even if the body is part of the sleep list as well)
|
||||
|
||||
BF_HAS_CONSTRAINTS = 1 << 8, // Set if the body has one or more constraints
|
||||
BF_KINEMATIC_SETTLING = 1 << 9, // Set when the body was moved kinematically last frame
|
||||
BF_KINEMATIC_SETTLING_2 = 1 << 10,
|
||||
BF_KINEMATIC_MOVE_FLAGS = BF_KINEMATIC_MOVED | BF_KINEMATIC_SETTLING | BF_KINEMATIC_SETTLING_2, //Used to clear kinematic masks in 1 call
|
||||
BF_KINEMATIC_SURFACE_VELOCITY = 1 << 11, //Set when the application calls setKinematicVelocity. Actor remains awake until application calls clearKinematicVelocity.
|
||||
BF_IS_COMPOUND_RIGID = 1 << 12, // Set when the body is a compound actor, we dont want to set the sq bounds
|
||||
|
||||
// PT: WARNING: flags stored on 16-bits now.
|
||||
};
|
||||
|
||||
ActorSim(Scene&, ActorCore&);
|
||||
virtual ~ActorSim();
|
||||
|
||||
// Get the scene the actor resides in
|
||||
PX_FORCE_INLINE Scene& getScene() const { return mScene; }
|
||||
|
||||
// Get the number of interactions connected to the actor
|
||||
PX_FORCE_INLINE PxU32 getActorInteractionCount() const { return mInteractions.size(); }
|
||||
|
||||
// Get an iterator to the interactions connected to the actor
|
||||
PX_FORCE_INLINE Interaction** getActorInteractions() const { return mInteractions.begin(); }
|
||||
|
||||
// Get the type ID of the actor
|
||||
PX_FORCE_INLINE PxActorType::Enum getActorType() const { return mCore.getActorCoreType(); }
|
||||
|
||||
// Returns true if the actor is a dynamic rigid body (including articulation links)
|
||||
PX_FORCE_INLINE PxU16 isDynamicRigid() const { return mFilterFlags & PxFilterObjectFlagEx::eRIGID_DYNAMIC; }
|
||||
PX_FORCE_INLINE PxU16 isDeformableSurface() const { return mFilterFlags & PxFilterObjectFlagEx::eDEFORMABLE_SURFACE; }
|
||||
PX_FORCE_INLINE PxU16 isDeformableVolume() const { return mFilterFlags & PxFilterObjectFlagEx::eDEFORMABLE_VOLUME; }
|
||||
PX_FORCE_INLINE PxU16 isParticleSystem() const { return mFilterFlags & PxFilterObjectFlagEx::ePARTICLESYSTEM; }
|
||||
PX_FORCE_INLINE PxU16 isNonRigid() const { return mFilterFlags & PxFilterObjectFlagEx::eNON_RIGID; }
|
||||
PX_FORCE_INLINE PxU16 isStaticRigid() const { return mFilterFlags & PxFilterObjectFlagEx::eRIGID_STATIC; }
|
||||
|
||||
virtual void postActorFlagChange(PxU32, PxU32) {}
|
||||
|
||||
void setActorsInteractionsDirty(InteractionDirtyFlag::Enum flag, const ActorSim* other, PxU8 interactionFlag);
|
||||
|
||||
PX_FORCE_INLINE ActorCore& getActorCore() const { return mCore; }
|
||||
|
||||
PX_FORCE_INLINE bool isActive() const { return (mActiveListIndex < SC_NOT_IN_ACTIVE_LIST_INDEX); }
|
||||
|
||||
PX_FORCE_INLINE PxU32 getActiveListIndex() const { return mActiveListIndex; } // if the body is active, the index is smaller than SC_NOT_IN_ACTIVE_LIST_INDEX
|
||||
PX_FORCE_INLINE void setActiveListIndex(PxU32 index) { mActiveListIndex = index; }
|
||||
|
||||
PX_FORCE_INLINE PxU32 getActiveCompoundListIndex() const { return mActiveCompoundListIndex; } // if the body is active and is compound, the index is smaller than SC_NOT_IN_ACTIVE_LIST_INDEX
|
||||
PX_FORCE_INLINE void setActiveCompoundListIndex(PxU32 index) { mActiveCompoundListIndex = index; }
|
||||
|
||||
PX_FORCE_INLINE PxNodeIndex getNodeIndex() const { return mNodeIndex; }
|
||||
|
||||
PX_FORCE_INLINE PxU32 getActorID() const { return mId; }
|
||||
|
||||
PX_FORCE_INLINE PxU16 getInternalFlag() const { return mInternalFlags; }
|
||||
PX_FORCE_INLINE PxU16 readInternalFlag(InternalFlags flag) const { return PxU16(mInternalFlags & flag); }
|
||||
PX_FORCE_INLINE void raiseInternalFlag(InternalFlags flag) { mInternalFlags |= flag; }
|
||||
PX_FORCE_INLINE void clearInternalFlag(InternalFlags flag) { mInternalFlags &= ~flag; }
|
||||
|
||||
PX_FORCE_INLINE PxFilterObjectAttributes getFilterAttributes() const { return PxFilterObjectAttributes(mFilterFlags); }
|
||||
|
||||
virtual PxActor* getPxActor() const = 0;
|
||||
|
||||
//This can all be removed and functionality can be subsumed by the island system, removing the need for this
|
||||
//virtual call and any associated work
|
||||
virtual void registerCountedInteraction() {}
|
||||
virtual void unregisterCountedInteraction() {}
|
||||
virtual PxU32 getNumCountedInteractions() const { return 0; }
|
||||
|
||||
virtual void internalWakeUp(PxReal wakeCounterValue = ScInternalWakeCounterResetValue) { PX_UNUSED(wakeCounterValue); }
|
||||
|
||||
private:
|
||||
//These are called from interaction creation/destruction
|
||||
void registerInteractionInActor(Interaction* interaction);
|
||||
void unregisterInteractionFromActor(Interaction* interaction);
|
||||
void reallocInteractions(Sc::Interaction**& mem, PxU32& capacity, PxU32 size, PxU32 requiredMinCapacity);
|
||||
protected:
|
||||
// dsequeira: interaction arrays are a major cause of small allocations, so we don't want to delegate them to the heap allocator
|
||||
// it's not clear this inline array is really needed, we should take it out and see whether the cache perf is worse
|
||||
|
||||
static const PxU32 INLINE_INTERACTION_CAPACITY = 4;
|
||||
Interaction* mInlineInteractionMem[INLINE_INTERACTION_CAPACITY];
|
||||
|
||||
Cm::OwnedArray<Sc::Interaction*, Sc::ActorSim, PxU32, &Sc::ActorSim::reallocInteractions>
|
||||
mInteractions;
|
||||
|
||||
Scene& mScene;
|
||||
ActorCore& mCore;
|
||||
// Sleeping
|
||||
PxU32 mActiveListIndex; // Used by Scene to track active bodies
|
||||
PxU32 mActiveCompoundListIndex; // Used by Scene to track active compound bodies
|
||||
|
||||
// Island manager
|
||||
PxNodeIndex mNodeIndex;
|
||||
|
||||
PxU32 mId; // PT: ID provided by Sc::Scene::mActorIDTracker
|
||||
|
||||
PxU16 mInternalFlags;
|
||||
PxU16 mFilterFlags; // PT: PxFilterObjectAttributes. Capturing the type information in local flags here is redundant
|
||||
// but avoids reading the Core memory from the Sim object, and is also faster to test multiple types at once.
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
274
engine/third_party/physx/source/simulationcontroller/src/ScArticulationCore.cpp
vendored
Normal file
274
engine/third_party/physx/source/simulationcontroller/src/ScArticulationCore.cpp
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#include "ScArticulationCore.h"
|
||||
|
||||
#include "ScPhysics.h"
|
||||
#include "ScBodyCore.h"
|
||||
#include "ScBodySim.h"
|
||||
#include "ScArticulationSim.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::ArticulationCore::ArticulationCore() :
|
||||
mSim(NULL)
|
||||
{
|
||||
const PxTolerancesScale& scale = Physics::getInstance().getTolerancesScale();
|
||||
|
||||
mCore.solverIterationCounts = 1<<8 | 4;
|
||||
mCore.sleepThreshold = 5e-5f * scale.speed * scale.speed;
|
||||
mCore.freezeThreshold = 5e-6f * scale.speed * scale.speed;
|
||||
mCore.wakeCounter = Physics::sWakeCounterOnCreation;
|
||||
mCore.gpuRemapIndex = 0xffffffff;
|
||||
}
|
||||
|
||||
Sc::ArticulationCore::~ArticulationCore()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
//
|
||||
// ArticulationCore interface implementation
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
|
||||
void Sc::ArticulationCore::setWakeCounter(const PxReal v)
|
||||
{
|
||||
mCore.wakeCounter = v;
|
||||
|
||||
if (mSim)
|
||||
{
|
||||
mSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_WAKECOUNTER);
|
||||
}
|
||||
|
||||
#if PX_DEBUG
|
||||
if(mSim)
|
||||
mSim->debugCheckWakeCounterOfLinks(v);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Sc::ArticulationCore::isSleeping() const
|
||||
{
|
||||
return mSim ? mSim->isSleeping() : (mCore.wakeCounter == 0.0f);
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::wakeUp(PxReal wakeCounter)
|
||||
{
|
||||
mCore.wakeCounter = wakeCounter;
|
||||
|
||||
if (mSim)
|
||||
{
|
||||
Dy::FeatherstoneArticulation* arti = static_cast<Dy::FeatherstoneArticulation*>(mSim->getLowLevelArticulation());
|
||||
arti->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_WAKECOUNTER);
|
||||
}
|
||||
|
||||
#if PX_DEBUG
|
||||
if(mSim)
|
||||
mSim->debugCheckSleepStateOfLinks(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::putToSleep()
|
||||
{
|
||||
mCore.wakeCounter = 0.0f;
|
||||
|
||||
if (mSim)
|
||||
{
|
||||
Dy::FeatherstoneArticulation* arti = static_cast<Dy::FeatherstoneArticulation*>(mSim->getLowLevelArticulation());
|
||||
arti->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_WAKECOUNTER);
|
||||
}
|
||||
|
||||
#if PX_DEBUG
|
||||
if(mSim)
|
||||
mSim->debugCheckSleepStateOfLinks(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::setArticulationFlags(PxArticulationFlags flags)
|
||||
{
|
||||
mCore.flags = flags;
|
||||
if(mSim)
|
||||
{
|
||||
mSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_USER_FLAGS);
|
||||
|
||||
const bool isFixedBaseLink = flags & PxArticulationFlag::eFIX_BASE;
|
||||
mSim->setFixedBaseLink(isFixedBaseLink);
|
||||
}
|
||||
}
|
||||
|
||||
PxU32 Sc::ArticulationCore::getDofs() const
|
||||
{
|
||||
return mSim ? mSim->getDofs() : 0xFFFFFFFFu;
|
||||
}
|
||||
|
||||
PxArticulationCache* Sc::ArticulationCore::createCache() const
|
||||
{
|
||||
return mSim ? mSim->createCache() : NULL;
|
||||
}
|
||||
|
||||
PxU32 Sc::ArticulationCore::getCacheDataSize() const
|
||||
{
|
||||
return mSim ? mSim->getCacheDataSize() : 0xFFFFFFFFu;
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::zeroCache(PxArticulationCache& cache) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->zeroCache(cache);
|
||||
}
|
||||
|
||||
bool Sc::ArticulationCore::applyCache(PxArticulationCache& cache, const PxArticulationCacheFlags flag) const
|
||||
{
|
||||
if(mSim)
|
||||
return mSim->applyCache(cache, flag);
|
||||
return false;
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::copyInternalStateToCache(PxArticulationCache& cache, const PxArticulationCacheFlags flag, const bool isGpuSimEnabled) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->copyInternalStateToCache(cache, flag, isGpuSimEnabled);
|
||||
}
|
||||
|
||||
|
||||
void Sc::ArticulationCore::packJointData(const PxReal* maximum, PxReal* reduced) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->packJointData(maximum, reduced);
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::unpackJointData(const PxReal* reduced, PxReal* maximum) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->unpackJointData(reduced, maximum);
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::commonInit() const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->commonInit();
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::computeGeneralizedGravityForce(PxArticulationCache& cache, const bool rootMotion) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->computeGeneralizedGravityForce(cache, rootMotion);
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::computeCoriolisAndCentrifugalForce(PxArticulationCache& cache, const bool rootMotion) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->computeCoriolisAndCentrifugalForce(cache, rootMotion);
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::computeGeneralizedExternalForce(PxArticulationCache& cache) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->computeGeneralizedExternalForce(cache);
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::computeJointAcceleration(PxArticulationCache& cache) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->computeJointAcceleration(cache);
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::computeJointForce(PxArticulationCache& cache) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->computeJointForce(cache);
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::computeDenseJacobian(PxArticulationCache& cache, PxU32& nRows, PxU32& nCols) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->computeDenseJacobian(cache, nRows, nCols);
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::computeCoefficientMatrix(PxArticulationCache& cache) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->computeCoefficientMatrix(cache);
|
||||
}
|
||||
|
||||
bool Sc::ArticulationCore::computeLambda(PxArticulationCache& cache, PxArticulationCache& initialState, const PxReal* const jointTorque, const PxVec3 gravity, const PxU32 maxIter) const
|
||||
{
|
||||
return mSim ? mSim->computeLambda(cache, initialState, jointTorque, gravity, maxIter) : false;
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::computeGeneralizedMassMatrix(PxArticulationCache& cache, const bool rootMotion) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->computeGeneralizedMassMatrix(cache, rootMotion);
|
||||
}
|
||||
|
||||
PxVec3 Sc::ArticulationCore::computeArticulationCOM(const bool rootFrame) const
|
||||
{
|
||||
return mSim ? mSim->computeArticulationCOM(rootFrame) : PxVec3(0.0f);
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::computeCentroidalMomentumMatrix(PxArticulationCache& cache) const
|
||||
{
|
||||
if(mSim)
|
||||
mSim->computeCentroidalMomentumMatrix(cache);
|
||||
}
|
||||
|
||||
PxU32 Sc::ArticulationCore::getCoefficientMatrixSize() const
|
||||
{
|
||||
return mSim ? mSim->getCoefficientMatrixSize() : 0xFFFFFFFFu;
|
||||
}
|
||||
|
||||
PxSpatialVelocity Sc::ArticulationCore::getLinkAcceleration(const PxU32 linkId, const bool isGpuSimEnabled) const
|
||||
{
|
||||
return mSim ? mSim->getLinkAcceleration(linkId, isGpuSimEnabled) : PxSpatialVelocity();
|
||||
}
|
||||
|
||||
PxU32 Sc::ArticulationCore::getGpuArticulationIndex() const
|
||||
{
|
||||
return mSim ? mCore.gpuRemapIndex : 0xffffffff;
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::updateKinematic(PxArticulationKinematicFlags flags)
|
||||
{
|
||||
PX_ASSERT(mSim);
|
||||
|
||||
if (mSim)
|
||||
mSim->updateKinematic(flags);
|
||||
}
|
||||
|
||||
PxNodeIndex Sc::ArticulationCore::getIslandNodeIndex() const
|
||||
{
|
||||
return mSim ? mSim->getIslandNodeIndex() : PxNodeIndex(PX_INVALID_NODE);
|
||||
}
|
||||
|
||||
void Sc::ArticulationCore::setGlobalPose()
|
||||
{
|
||||
if(mSim)
|
||||
mSim->setGlobalPose();
|
||||
}
|
||||
306
engine/third_party/physx/source/simulationcontroller/src/ScArticulationJointCore.cpp
vendored
Normal file
306
engine/third_party/physx/source/simulationcontroller/src/ScArticulationJointCore.cpp
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScArticulationJointCore.h"
|
||||
#include "ScArticulationCore.h"
|
||||
#include "ScArticulationSim.h"
|
||||
#include "ScArticulationJointSim.h"
|
||||
#include "ScBodyCore.h"
|
||||
#include "ScPhysics.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::ArticulationJointCore::ArticulationJointCore(const PxTransform& parentFrame, const PxTransform& childFrame) :
|
||||
mCore (parentFrame, childFrame),
|
||||
mSim (NULL),
|
||||
mArticulation (NULL),
|
||||
mRootType (NULL),
|
||||
mLLLinkIndex (0xffffffff)
|
||||
{
|
||||
}
|
||||
|
||||
Sc::ArticulationJointCore::~ArticulationJointCore()
|
||||
{
|
||||
PX_ASSERT(getSim() == 0);
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setSimDirty()
|
||||
{
|
||||
Sc::ArticulationJointSim* sim = getSim();
|
||||
if(sim)
|
||||
sim->setDirty();
|
||||
|
||||
ArticulationSim* artiSim = mArticulation->getSim();
|
||||
if (artiSim && artiSim->isLLArticulationInitialized())
|
||||
{
|
||||
Dy::FeatherstoneArticulation* llarticulation = artiSim->getLowLevelArticulation();
|
||||
llarticulation->mJcalcDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setParentPose(const PxTransform& t)
|
||||
{
|
||||
// AD: we check if it changed at all to avoid marking the complete articulation dirty for a jcalc.
|
||||
// The jcalc internally checks these ArticulationJointCoreDirtyFlag again so we would skip most things
|
||||
// but we'd still check all the joints. The same is also true for the following functions.
|
||||
if (!(mCore.parentPose == t))
|
||||
{
|
||||
mCore.parentPose = t;
|
||||
|
||||
setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setChildPose(const PxTransform& t)
|
||||
{
|
||||
if (!(mCore.childPose == t))
|
||||
{
|
||||
mCore.childPose = t;
|
||||
|
||||
setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setTargetP(PxArticulationAxis::Enum axis, PxReal targetP)
|
||||
{
|
||||
// this sets the target position in the core.
|
||||
mCore.targetP[axis] = targetP;
|
||||
|
||||
// this sets the target position in the ll articulation. This needs to happen immediately because we might
|
||||
// look up the value using the cache API again, and that one is reading directly from the llArticulation.
|
||||
ArticulationSim* artiSim = mArticulation->getSim();
|
||||
if (artiSim && artiSim->isLLArticulationInitialized())
|
||||
{
|
||||
Dy::FeatherstoneArticulation* llarticulation = artiSim->getLowLevelArticulation();
|
||||
Dy::ArticulationData& data = llarticulation->getArticulationData();
|
||||
Dy::ArticulationJointCoreData* jointData = data.getJointData();
|
||||
Dy::ArticulationJointCoreData& jointDatum = jointData[mLLLinkIndex];
|
||||
|
||||
PxReal* jointTargetPositions = data.getJointTargetPositions();
|
||||
PxReal* jTargetPosition = &jointTargetPositions[jointDatum.jointOffset];
|
||||
|
||||
const PxU32 dofId = mCore.invDofIds[axis];
|
||||
|
||||
if (dofId != 0xff)
|
||||
{
|
||||
jTargetPosition[dofId] = targetP;
|
||||
|
||||
artiSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_JOINT_TARGET_POS);
|
||||
}
|
||||
}
|
||||
|
||||
// AD: does not need setDirty - we write directly into the llArticulation and the GPU part is
|
||||
// handled by setArticulationDirty.
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setTargetV(PxArticulationAxis::Enum axis, PxReal targetV)
|
||||
{
|
||||
// this sets the target velocity in the core.
|
||||
mCore.targetV[axis] = targetV;
|
||||
|
||||
// this sets the target velocity in the ll articulation. This needs to happen immediately because we might
|
||||
// look up the value using the cache API again, and that one is reading directly from the llArticulation.
|
||||
ArticulationSim* artiSim = mArticulation->getSim();
|
||||
if (artiSim && artiSim->isLLArticulationInitialized())
|
||||
{
|
||||
Dy::FeatherstoneArticulation* llarticulation = artiSim->getLowLevelArticulation();
|
||||
Dy::ArticulationData& data = llarticulation->getArticulationData();
|
||||
Dy::ArticulationJointCoreData* jointData = data.getJointData();
|
||||
Dy::ArticulationJointCoreData& jointDatum = jointData[mLLLinkIndex];
|
||||
|
||||
PxReal* jointTargetVelocities = data.getJointTargetVelocities();
|
||||
PxReal* jTargetVelocity = &jointTargetVelocities[jointDatum.jointOffset];
|
||||
|
||||
const PxU32 dofId = mCore.invDofIds[axis];
|
||||
|
||||
if (dofId != 0xff)
|
||||
{
|
||||
jTargetVelocity[dofId] = targetV;
|
||||
|
||||
artiSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_JOINT_TARGET_VEL);
|
||||
}
|
||||
}
|
||||
|
||||
// AD: does not need setDirty - we write directly into the llArticulation and the GPU part is
|
||||
// handled by setArticulationDirty.
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setArmature(PxArticulationAxis::Enum axis, PxReal armature)
|
||||
{
|
||||
if (mCore.armature[axis] != armature)
|
||||
{
|
||||
mCore.armature[axis] = armature;
|
||||
|
||||
setSimDirty();
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setJointPosition(PxArticulationAxis::Enum axis, const PxReal jointPos)
|
||||
{
|
||||
// this sets the position in the core.
|
||||
mCore.jointPos[axis] = jointPos;
|
||||
|
||||
// this sets the position in the ll articulation. This needs to happen immediately because we might
|
||||
// look up the value using the cache API again, and that one is reading directly from the llArticulation.
|
||||
ArticulationSim* artiSim = mArticulation->getSim();
|
||||
if (artiSim && artiSim->isLLArticulationInitialized())
|
||||
{
|
||||
Dy::FeatherstoneArticulation* llarticulation = artiSim->getLowLevelArticulation();
|
||||
Dy::ArticulationData& data = llarticulation->getArticulationData();
|
||||
Dy::ArticulationJointCoreData* jointData = data.getJointData();
|
||||
Dy::ArticulationJointCoreData& jointDatum = jointData[mLLLinkIndex];
|
||||
|
||||
PxReal* jointPositions = data.getJointPositions();
|
||||
PxReal* jPosition = &jointPositions[jointDatum.jointOffset];
|
||||
|
||||
const PxU32 dofId = mCore.invDofIds[axis];
|
||||
|
||||
if (dofId != 0xff)
|
||||
{
|
||||
jPosition[dofId] = jointPos;
|
||||
|
||||
artiSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_POSITIONS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AD: we need this indirection right now because we could have updated joint vel using the cache, so
|
||||
// the read from the joint core might be stale.
|
||||
PxReal Sc::ArticulationJointCore::getJointPosition(PxArticulationAxis::Enum axis) const
|
||||
{
|
||||
PxReal jointPos = mCore.jointPos[axis];
|
||||
ArticulationSim* artiSim = mArticulation->getSim();
|
||||
if (artiSim && artiSim->isLLArticulationInitialized())
|
||||
{
|
||||
const Dy::FeatherstoneArticulation* llarticulation = artiSim->getLowLevelArticulation();
|
||||
const Dy::ArticulationData& data = llarticulation->getArticulationData();
|
||||
const Dy::ArticulationJointCoreData* jointData = data.getJointData();
|
||||
const Dy::ArticulationJointCoreData& jointDatum = jointData[mLLLinkIndex];
|
||||
|
||||
const PxReal* jointPositions = data.getJointPositions();
|
||||
const PxReal* jPosition = &jointPositions[jointDatum.jointOffset];
|
||||
|
||||
const PxU32 dofId = mCore.invDofIds[axis];
|
||||
|
||||
if(dofId != 0xff)
|
||||
jointPos = jPosition[dofId];
|
||||
}
|
||||
|
||||
return jointPos;
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setJointVelocity(PxArticulationAxis::Enum axis, const PxReal jointVel)
|
||||
{
|
||||
mCore.jointVel[axis] = jointVel;
|
||||
|
||||
ArticulationSim* artiSim = mArticulation->getSim();
|
||||
if (artiSim && artiSim->isLLArticulationInitialized())
|
||||
{
|
||||
Dy::FeatherstoneArticulation* llarticulation = artiSim->getLowLevelArticulation();
|
||||
Dy::ArticulationData& data = llarticulation->getArticulationData();
|
||||
Dy::ArticulationJointCoreData* jointData = data.getJointData();
|
||||
Dy::ArticulationJointCoreData& jointDatum = jointData[mLLLinkIndex];
|
||||
|
||||
PxReal* jointVelocities = data.getJointVelocities();
|
||||
PxReal* jVelocity = &jointVelocities[jointDatum.jointOffset];
|
||||
|
||||
const PxU32 dofId = mCore.invDofIds[axis];
|
||||
if (dofId != 0xff)
|
||||
{
|
||||
jVelocity[dofId] = jointVel;
|
||||
|
||||
artiSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_VELOCITIES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AD: we need this indirection right now because we could have updated joint vel using the cache, so
|
||||
// the read from the joint core might be stale.
|
||||
PxReal Sc::ArticulationJointCore::getJointVelocity(PxArticulationAxis::Enum axis) const
|
||||
{
|
||||
PxReal jointVel = mCore.jointVel[axis];
|
||||
ArticulationSim* artiSim = mArticulation->getSim();
|
||||
if (artiSim && artiSim->isLLArticulationInitialized())
|
||||
{
|
||||
const Dy::FeatherstoneArticulation* llarticulation = artiSim->getLowLevelArticulation();
|
||||
const Dy::ArticulationData& data = llarticulation->getArticulationData();
|
||||
const Dy::ArticulationJointCoreData* jointData = data.getJointData();
|
||||
const Dy::ArticulationJointCoreData& jointDatum = jointData[mLLLinkIndex];
|
||||
|
||||
const PxReal* jointVelocities = data.getJointVelocities();
|
||||
const PxReal* jVelocities = &jointVelocities[jointDatum.jointOffset];
|
||||
|
||||
const PxU32 dofId = mCore.invDofIds[axis];
|
||||
if (dofId != 0xff)
|
||||
jointVel = jVelocities[dofId];
|
||||
}
|
||||
|
||||
return jointVel;
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setLimit(PxArticulationAxis::Enum axis, const PxArticulationLimit& limit)
|
||||
{
|
||||
mCore.setLimit(axis, limit);
|
||||
|
||||
setSimDirty();
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setDrive(PxArticulationAxis::Enum axis, const PxArticulationDrive& drive)
|
||||
{
|
||||
mCore.setDrive(axis, drive);
|
||||
|
||||
setSimDirty();
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setFrictionCoefficient(PxReal frictionCoefficient)
|
||||
{
|
||||
mCore.setFrictionCoefficient(frictionCoefficient);
|
||||
|
||||
setSimDirty();
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setFrictionParams(PxArticulationAxis::Enum axis, const PxJointFrictionParams& jointFrictionParams)
|
||||
{
|
||||
mCore.setFrictionParams(axis, jointFrictionParams);
|
||||
|
||||
setSimDirty();
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setMaxJointVelocity(PxReal maxJointV)
|
||||
{
|
||||
mCore.setMaxJointVelocity(maxJointV);
|
||||
|
||||
setSimDirty();
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointCore::setMaxJointVelocity(PxArticulationAxis::Enum axis, PxReal maxJointV)
|
||||
{
|
||||
mCore.setMaxJointVelocity(axis, maxJointV);
|
||||
|
||||
setSimDirty();
|
||||
}
|
||||
97
engine/third_party/physx/source/simulationcontroller/src/ScArticulationJointSim.cpp
vendored
Normal file
97
engine/third_party/physx/source/simulationcontroller/src/ScArticulationJointSim.cpp
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScArticulationJointSim.h"
|
||||
#include "ScArticulationJointCore.h"
|
||||
#include "ScBodySim.h"
|
||||
#include "ScScene.h"
|
||||
#include "PxsRigidBody.h"
|
||||
#include "ScArticulationSim.h"
|
||||
#include "PxsSimpleIslandManager.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::ArticulationJointSim::ArticulationJointSim(ArticulationJointCore& joint, ActorSim& parent, ActorSim& child) :
|
||||
Interaction (parent, child, InteractionType::eARTICULATION, 0),
|
||||
mCore (joint)
|
||||
{
|
||||
{
|
||||
onActivate();
|
||||
registerInActors();
|
||||
}
|
||||
|
||||
BodySim& childBody = static_cast<BodySim&>(child),
|
||||
& parentBody = static_cast<BodySim&>(parent);
|
||||
|
||||
parentBody.getArticulation()->addBody(childBody, &parentBody, this);
|
||||
|
||||
mCore.setSim(this);
|
||||
}
|
||||
|
||||
Sc::ArticulationJointSim::~ArticulationJointSim()
|
||||
{
|
||||
// articulation interactions do not make use of the dirty flags yet. If they did, a setClean(true) has to be introduced here.
|
||||
PX_ASSERT(!readInteractionFlag(InteractionFlag::eIN_DIRTY_LIST));
|
||||
PX_ASSERT(!getDirtyFlags());
|
||||
|
||||
unregisterFromActors();
|
||||
|
||||
mCore.setSim(NULL);
|
||||
}
|
||||
|
||||
Sc::BodySim& Sc::ArticulationJointSim::getParent() const
|
||||
{
|
||||
return static_cast<BodySim&>(getActorSim0());
|
||||
}
|
||||
|
||||
Sc::BodySim& Sc::ArticulationJointSim::getChild() const
|
||||
{
|
||||
return static_cast<BodySim&>(getActorSim1());
|
||||
}
|
||||
|
||||
bool Sc::ArticulationJointSim::onActivate()
|
||||
{
|
||||
if(!(getParent().isActive() && getChild().isActive()))
|
||||
return false;
|
||||
|
||||
raiseInteractionFlag(InteractionFlag::eIS_ACTIVE);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sc::ArticulationJointSim::onDeactivate()
|
||||
{
|
||||
clearInteractionFlag(InteractionFlag::eIS_ACTIVE);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sc::ArticulationJointSim::setDirty()
|
||||
{
|
||||
Dy::ArticulationJointCore& llCore = mCore.getCore();
|
||||
ArticulationSim* sim = mCore.getArticulation()->getSim();
|
||||
sim->setJointDirty(llCore);
|
||||
}
|
||||
66
engine/third_party/physx/source/simulationcontroller/src/ScArticulationJointSim.h
vendored
Normal file
66
engine/third_party/physx/source/simulationcontroller/src/ScArticulationJointSim.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ARTICULATION_JOINT_SIM_H
|
||||
#define SC_ARTICULATION_JOINT_SIM_H
|
||||
|
||||
#include "ScInteraction.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
|
||||
class ArticulationJointCore;
|
||||
class BodySim;
|
||||
|
||||
class ArticulationJointSim : public Interaction
|
||||
{
|
||||
PX_NOCOPY(ArticulationJointSim)
|
||||
public:
|
||||
ArticulationJointSim(ArticulationJointCore& joint, ActorSim& parent, ActorSim& child);
|
||||
~ArticulationJointSim();
|
||||
|
||||
bool onActivate();
|
||||
bool onDeactivate();
|
||||
|
||||
PX_FORCE_INLINE ArticulationJointCore& getCore() const { return mCore; }
|
||||
|
||||
BodySim& getParent() const;
|
||||
BodySim& getChild() const;
|
||||
|
||||
void setDirty();
|
||||
private:
|
||||
ArticulationJointCore& mCore;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
83
engine/third_party/physx/source/simulationcontroller/src/ScArticulationMimicJointSim.cpp
vendored
Normal file
83
engine/third_party/physx/source/simulationcontroller/src/ScArticulationMimicJointSim.cpp
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScArticulationMimicJointSim.h"
|
||||
#include "ScArticulationMimicJointCore.h"
|
||||
#include "PxArticulationReducedCoordinate.h"
|
||||
#include "ScArticulationSim.h"
|
||||
#include "PxArticulationReducedCoordinate.h"
|
||||
#include "DyArticulationMimicJointCore.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
Sc::ArticulationMimicJointSim::ArticulationMimicJointSim(ArticulationMimicJointCore& mimicJointCore, Scene& scene) :
|
||||
mScene(scene), mCore(mimicJointCore),
|
||||
mLLIndex(0xffffffff)
|
||||
{
|
||||
mimicJointCore.setSim(this);
|
||||
mLLMimicJoint.axisA = mimicJointCore.mAxisA;
|
||||
mLLMimicJoint.axisB = mimicJointCore.mAxisB;
|
||||
mLLMimicJoint.gearRatio = mimicJointCore.mGearRatio;
|
||||
mLLMimicJoint.offset = mimicJointCore.mOffset;
|
||||
mLLMimicJoint.naturalFrequency = mimicJointCore.mNaturalFrequency;
|
||||
mLLMimicJoint.dampingRatio = mimicJointCore.mDampingRatio;
|
||||
}
|
||||
|
||||
Sc::ArticulationMimicJointSim::~ArticulationMimicJointSim()
|
||||
{
|
||||
mCore.setSim(NULL);
|
||||
}
|
||||
|
||||
void Sc::ArticulationMimicJointSim::setGearRatio(const PxReal gearRatio)
|
||||
{
|
||||
mLLMimicJoint.gearRatio = gearRatio;
|
||||
mArticulationSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_MIMIC_JOINT);
|
||||
}
|
||||
|
||||
void Sc::ArticulationMimicJointSim::setOffset(const PxReal offset)
|
||||
{
|
||||
mLLMimicJoint.offset = offset;
|
||||
mArticulationSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_MIMIC_JOINT);
|
||||
}
|
||||
|
||||
void Sc::ArticulationMimicJointSim::setNaturalFrequency(const PxReal naturalFrequency)
|
||||
{
|
||||
mLLMimicJoint.naturalFrequency = naturalFrequency;
|
||||
mArticulationSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_MIMIC_JOINT);
|
||||
}
|
||||
|
||||
void Sc::ArticulationMimicJointSim::setDampingRatio(const PxReal dampingRatio)
|
||||
{
|
||||
mLLMimicJoint.dampingRatio = dampingRatio;
|
||||
mArticulationSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_MIMIC_JOINT);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
85
engine/third_party/physx/source/simulationcontroller/src/ScArticulationMimicJointSim.h
vendored
Normal file
85
engine/third_party/physx/source/simulationcontroller/src/ScArticulationMimicJointSim.h
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ARTICULATION_MIMIC_JOINT_SIM_H
|
||||
#define SC_ARTICULATION_MIMIC_JOINT_SIM_H
|
||||
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "PxArticulationReducedCoordinate.h"
|
||||
#include "DyFeatherstoneArticulation.h"
|
||||
#include "DyArticulationMimicJointCore.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class Scene;
|
||||
class ArticulationMimicJointCore;
|
||||
class ArticulationCore;
|
||||
class ArticulationSim;
|
||||
|
||||
class ArticulationMimicJointSim : public PxUserAllocated
|
||||
{
|
||||
|
||||
PX_NOCOPY(ArticulationMimicJointSim)
|
||||
|
||||
|
||||
public:
|
||||
ArticulationMimicJointSim(Sc::ArticulationMimicJointCore& core, Sc::Scene& scene);
|
||||
|
||||
~ArticulationMimicJointSim();
|
||||
|
||||
PX_FORCE_INLINE Sc::Scene& getScene() { return mScene; }
|
||||
PX_FORCE_INLINE const Sc::Scene& getScene() const { return mScene; }
|
||||
|
||||
PX_FORCE_INLINE void setLowLevelIndex(const PxU32 llIndex) { mLLIndex = llIndex;}
|
||||
PX_FORCE_INLINE PxU32 getLowLevelIndex() const { return mLLIndex; }
|
||||
|
||||
PX_FORCE_INLINE Sc::ArticulationMimicJointCore& getCore() { return mCore; }
|
||||
PX_FORCE_INLINE const Sc::ArticulationMimicJointCore& getCore() const { return mCore; }
|
||||
|
||||
PX_FORCE_INLINE Dy::ArticulationMimicJointCore& getLLMimicJoint() { return mLLMimicJoint; }
|
||||
|
||||
void setGearRatio(const PxReal gearRatio);
|
||||
void setOffset(const PxReal offset);
|
||||
void setNaturalFrequency(const PxReal naturalFrequency);
|
||||
void setDampingRatio(const PxReal dampingRatio);
|
||||
|
||||
Sc::Scene& mScene;
|
||||
Sc::ArticulationMimicJointCore& mCore;
|
||||
Sc::ArticulationSim* mArticulationSim;
|
||||
Dy::ArticulationMimicJointCore mLLMimicJoint;
|
||||
PxU32 mLLIndex;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //SC_ARTICULATION_MIMIC_JOINT_SIM_H
|
||||
|
||||
|
||||
825
engine/third_party/physx/source/simulationcontroller/src/ScArticulationSim.cpp
vendored
Normal file
825
engine/third_party/physx/source/simulationcontroller/src/ScArticulationSim.cpp
vendored
Normal file
@@ -0,0 +1,825 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScArticulationSim.h"
|
||||
#include "ScArticulationCore.h"
|
||||
#include "ScArticulationJointSim.h"
|
||||
#include "ScArticulationJointCore.h"
|
||||
#include "ScBodySim.h"
|
||||
#include "ScConstraintSim.h"
|
||||
#include "ScArticulationTendonSim.h"
|
||||
#include "ScArticulationMimicJointSim.h"
|
||||
#include "ScScene.h"
|
||||
|
||||
#include "DyConstraint.h"
|
||||
#include "DyFeatherstoneArticulation.h"
|
||||
#include "PxsContext.h"
|
||||
#include "CmSpatialVector.h"
|
||||
#include "foundation/PxVecMath.h"
|
||||
#include "PxsSimpleIslandManager.h"
|
||||
#include "ScShapeSim.h"
|
||||
#include "PxsSimulationController.h"
|
||||
#include "DyIslandManager.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Dy;
|
||||
using namespace Sc;
|
||||
using namespace IG;
|
||||
|
||||
ArticulationSim* Sc::getArticulationSim(const IslandSim& islandSim, PxNodeIndex nodeIndex)
|
||||
{
|
||||
void* userData = getArticulationFromIG(islandSim, nodeIndex)->getUserData();
|
||||
return reinterpret_cast<ArticulationSim*>(userData);
|
||||
}
|
||||
|
||||
Sc::ArticulationSim::ArticulationSim(ArticulationCore& core, Scene& scene, BodyCore& root) :
|
||||
mLLArticulation (NULL),
|
||||
mScene (scene),
|
||||
mCore (core),
|
||||
mLinks ("ScArticulationSim::links"),
|
||||
mBodies ("ScArticulationSim::bodies"),
|
||||
mJoints ("ScArticulationSim::joints"),
|
||||
mMaxDepth (0),
|
||||
mIsLLArticulationInitialized(false)
|
||||
{
|
||||
mLinks.reserve(16);
|
||||
mJoints.reserve(16);
|
||||
mBodies.reserve(16);
|
||||
|
||||
mLLArticulation = mScene.createLLArticulation(this);
|
||||
|
||||
mIslandNodeIndex = scene.getSimpleIslandManager()->addNode(false, false, IG::Node::eARTICULATION_TYPE, mLLArticulation);
|
||||
|
||||
if(!mLLArticulation)
|
||||
{
|
||||
PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL, "Articulation: could not allocate low-level resources.");
|
||||
return;
|
||||
}
|
||||
|
||||
PX_ASSERT(root.getSim());
|
||||
|
||||
addBody(*root.getSim(), NULL, NULL);
|
||||
|
||||
mCore.setSim(this);
|
||||
|
||||
mLLArticulation->setDyContext(mScene.getDynamicsContext());
|
||||
mLLArticulation->getSolverDesc().initData(&core.getCore(), NULL);
|
||||
|
||||
//mLLArticulation->onUpdateSolverDesc();
|
||||
}
|
||||
|
||||
Sc::ArticulationSim::~ArticulationSim()
|
||||
{
|
||||
if (!mLLArticulation)
|
||||
return;
|
||||
|
||||
mScene.destroyLLArticulation(*mLLArticulation);
|
||||
|
||||
mScene.getSimpleIslandManager()->removeNode(mIslandNodeIndex);
|
||||
|
||||
mCore.setSim(NULL);
|
||||
}
|
||||
|
||||
PxU32 Sc::ArticulationSim::findBodyIndex(BodySim& body) const
|
||||
{
|
||||
for(PxU32 i=0; i<mBodies.size(); i++)
|
||||
{
|
||||
if(mBodies[i]==&body)
|
||||
return i;
|
||||
}
|
||||
PX_ASSERT(0);
|
||||
return 0x80000000;
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::addLoopConstraint(ConstraintSim* constraintSim)
|
||||
{
|
||||
const PxU32 size = mLoopConstraints.size();
|
||||
if (size < mLoopConstraints.size())
|
||||
mLoopConstraints.reserve(size*2 + 1);
|
||||
|
||||
BodySim* bodySim0 = constraintSim->getBody(0);
|
||||
BodySim* bodySim1 = constraintSim->getBody(1);
|
||||
|
||||
ArticulationLoopConstraint lConstraint;
|
||||
if (bodySim0)
|
||||
lConstraint.linkIndex0 = findBodyIndex(*bodySim0);
|
||||
else
|
||||
lConstraint.linkIndex0 = 0x80000000;
|
||||
|
||||
if(bodySim1)
|
||||
lConstraint.linkIndex1 = findBodyIndex(*bodySim1);
|
||||
else
|
||||
lConstraint.linkIndex1 = 0x80000000;
|
||||
|
||||
lConstraint.constraint = &constraintSim->getLowLevelConstraint();
|
||||
|
||||
mLoopConstraints.pushBack(lConstraint);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::removeLoopConstraint(ConstraintSim* constraintSim)
|
||||
{
|
||||
Dy::Constraint* constraint = &constraintSim->getLowLevelConstraint();
|
||||
|
||||
const PxU32 size = mLoopConstraints.size();
|
||||
PxU32 index = 0;
|
||||
while (index < size && mLoopConstraints[index].constraint != constraint)
|
||||
++index;
|
||||
|
||||
if (index != size)
|
||||
mLoopConstraints.replaceWithLast(index);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::updateCached(PxBitMapPinned* shapeChangedMap)
|
||||
{
|
||||
for(PxU32 i=0; i<mBodies.size(); i++)
|
||||
mBodies[i]->updateCached(shapeChangedMap);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::markShapesUpdated(PxBitMapPinned* shapeChangedMap)
|
||||
{
|
||||
for (PxU32 a = 0; a < mBodies.size(); ++a)
|
||||
{
|
||||
PxU32 nbElems = mBodies[a]->getNbElements();
|
||||
ElementSim** elems = mBodies[a]->getElements();
|
||||
while (nbElems--)
|
||||
{
|
||||
ShapeSim* sim = static_cast<ShapeSim*>(*elems++);
|
||||
if (sim->isInBroadPhase())
|
||||
shapeChangedMap->growAndSet(sim->getElementID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::addBody(BodySim& body, BodySim* parent, ArticulationJointSim* joint)
|
||||
{
|
||||
mBodies.pushBack(&body);
|
||||
mJoints.pushBack(joint);
|
||||
mLLArticulation->addBody();
|
||||
|
||||
const PxU32 index = mLinks.size();
|
||||
|
||||
PX_ASSERT((((index==0) && (joint == 0)) && (parent == 0)) ||
|
||||
(((index!=0) && joint) && (parent && (parent->getArticulation() == this))));
|
||||
|
||||
ArticulationLink& link = mLinks.insert();
|
||||
|
||||
link.bodyCore = &body.getBodyCore().getCore();
|
||||
link.mPathToRootStartIndex = 0;
|
||||
link.mPathToRootCount = 0;
|
||||
link.mChildrenStartIndex = 0xffffffff;
|
||||
link.mNumChildren = 0;
|
||||
bool shouldSleep;
|
||||
bool currentlyAsleep;
|
||||
const bool bodyReadyForSleep = body.checkSleepReadinessBesidesWakeCounter();
|
||||
const PxReal wakeCounter = getCore().getWakeCounter();
|
||||
|
||||
if(parent)
|
||||
{
|
||||
currentlyAsleep = !mBodies[0]->isActive();
|
||||
shouldSleep = currentlyAsleep && bodyReadyForSleep;
|
||||
|
||||
PxU32 parentIndex = findBodyIndex(*parent);
|
||||
link.parent = parentIndex;
|
||||
ArticulationLink& parentLink = mLinks[parentIndex];
|
||||
link.inboundJoint = &joint->getCore().getCore();
|
||||
|
||||
if (parentLink.mChildrenStartIndex == 0xffffffff)
|
||||
parentLink.mChildrenStartIndex = index;
|
||||
|
||||
parentLink.mNumChildren++;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
currentlyAsleep = (wakeCounter == 0.0f);
|
||||
shouldSleep = currentlyAsleep && bodyReadyForSleep;
|
||||
|
||||
link.parent = DY_ARTICULATION_LINK_NONE;
|
||||
link.inboundJoint = NULL;
|
||||
}
|
||||
|
||||
|
||||
if(currentlyAsleep && !shouldSleep)
|
||||
{
|
||||
for(PxU32 i=0; i < (mBodies.size() - 1); i++)
|
||||
mBodies[i]->internalWakeUpArticulationLink(wakeCounter);
|
||||
}
|
||||
|
||||
body.setArticulation(this, wakeCounter, shouldSleep, index);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::removeBody(BodySim& body)
|
||||
{
|
||||
for (PxU32 i = 0; i < mBodies.size(); ++i)
|
||||
{
|
||||
if (mBodies[i] == &body)
|
||||
{
|
||||
mBodies.replaceWithLast(i);
|
||||
mJoints.replaceWithLast(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::addTendon(ArticulationSpatialTendonSim* const tendonSim)
|
||||
{
|
||||
tendonSim->mArtiSim = this;
|
||||
|
||||
const PxU32 index = mSpatialTendons.size();
|
||||
Dy::ArticulationSpatialTendon& llTendon = tendonSim->mLLTendon;
|
||||
llTendon.setTendonIndex(index);
|
||||
mSpatialTendons.pushBack(&llTendon);
|
||||
|
||||
//mSpatialTendons.pushBack(&tendonSim->mLLTendon);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::addTendon(ArticulationFixedTendonSim* const tendonSim)
|
||||
{
|
||||
tendonSim->mArtiSim = this;
|
||||
|
||||
const PxU32 index = mFixedTendons.size();
|
||||
Dy::ArticulationFixedTendon& llTendon = tendonSim->mLLTendon;
|
||||
llTendon.setTendonIndex(index);
|
||||
mFixedTendons.pushBack(&llTendon);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::addMimicJoint(ArticulationMimicJointSim* const mimicJointSim, const PxU32 linkA, const PxU32 linkB)
|
||||
{
|
||||
const PxU32 index = mMimicJoints.size();
|
||||
mimicJointSim->setLowLevelIndex(index);
|
||||
mimicJointSim->mArticulationSim = this;
|
||||
|
||||
Dy::ArticulationMimicJointCore& llMimicJoint = mimicJointSim->getLLMimicJoint();
|
||||
llMimicJoint.linkA = linkA;
|
||||
llMimicJoint.linkB = linkB;
|
||||
mMimicJoints.pushBack(&llMimicJoint);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::createLLStructure()
|
||||
{
|
||||
if(!mBodies.size())
|
||||
return;
|
||||
|
||||
mLLArticulation->setupLinks(mLinks.size(), mLinks.begin());
|
||||
|
||||
mLLArticulation->assignTendons(mSpatialTendons.size(), mSpatialTendons.begin());
|
||||
|
||||
mLLArticulation->assignTendons(mFixedTendons.size(), mFixedTendons.begin());
|
||||
|
||||
mLLArticulation->assignMimicJoints(mMimicJoints.size(), mMimicJoints.begin());
|
||||
|
||||
mIsLLArticulationInitialized = true;
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::initializeConfiguration()
|
||||
{
|
||||
Dy::ArticulationData& data = mLLArticulation->getArticulationData();
|
||||
mLLArticulation->jcalc(data);
|
||||
mLLArticulation->mJcalcDirty = false;
|
||||
|
||||
Dy::ArticulationLink* links = data.getLinks();
|
||||
Dy::ArticulationJointCoreData* jointData = data.getJointData();
|
||||
const PxU32 linkCount = data.getLinkCount();
|
||||
|
||||
PxReal* jointVelocites = data.getJointVelocities();
|
||||
PxReal* jointPositions = data.getJointPositions();
|
||||
PxReal* jointTargetPositions = data.getJointTargetPositions();
|
||||
PxReal* jointTargetVelocities = data.getJointTargetVelocities();
|
||||
|
||||
for (PxU32 linkID = 1; linkID < linkCount; ++linkID)
|
||||
{
|
||||
Dy::ArticulationLink& link = links[linkID];
|
||||
|
||||
Dy::ArticulationJointCore* joint = link.inboundJoint;
|
||||
Dy::ArticulationJointCoreData& jointDatum = jointData[linkID];
|
||||
|
||||
PxReal* jPositions = &jointPositions[jointDatum.jointOffset];
|
||||
PxReal* jVelocites = &jointVelocites[jointDatum.jointOffset];
|
||||
PxReal* jTargetPositions = &jointTargetPositions[jointDatum.jointOffset];
|
||||
PxReal* jTargetVelocities = &jointTargetVelocities[jointDatum.jointOffset];
|
||||
|
||||
for (PxU8 i = 0; i < jointDatum.nbDof; ++i)
|
||||
{
|
||||
const PxU32 dofId = joint->dofIds[i];
|
||||
jPositions[i] = joint->jointPos[dofId];
|
||||
jVelocites[i] = joint->jointVel[dofId];
|
||||
jTargetPositions[i] = joint->targetP[dofId];
|
||||
jTargetVelocities[i] = joint->targetV[dofId];
|
||||
}
|
||||
}
|
||||
|
||||
PxU32 flags = (Dy::ArticulationDirtyFlag::eDIRTY_POSITIONS |
|
||||
Dy::ArticulationDirtyFlag::eDIRTY_VELOCITIES |
|
||||
Dy::ArticulationDirtyFlag::eDIRTY_JOINT_TARGET_POS |
|
||||
Dy::ArticulationDirtyFlag::eDIRTY_JOINT_TARGET_VEL);
|
||||
|
||||
mLLArticulation->raiseGPUDirtyFlag(Dy::ArticulationDirtyFlag::Enum(flags));
|
||||
|
||||
mLLArticulation->initPathToRoot();
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::updateKinematic(PxArticulationKinematicFlags flags)
|
||||
{
|
||||
Dy::ArticulationData& data = mLLArticulation->getArticulationData();
|
||||
if (mLLArticulation->mJcalcDirty)
|
||||
{
|
||||
mLLArticulation->jcalc(data);
|
||||
mLLArticulation->mJcalcDirty = false;
|
||||
}
|
||||
|
||||
if ((flags & PxArticulationKinematicFlag::ePOSITION))
|
||||
{
|
||||
mLLArticulation->raiseGPUDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_POSITIONS);
|
||||
mLLArticulation->teleportLinks(data);
|
||||
}
|
||||
|
||||
if ((flags & PxArticulationKinematicFlag::ePOSITION) ||
|
||||
(flags & PxArticulationKinematicFlag::eVELOCITY))
|
||||
{
|
||||
mLLArticulation->raiseGPUDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_VELOCITIES);
|
||||
mLLArticulation->computeLinkVelocities(data);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::copyJointStatus(const PxU32 linkID)
|
||||
{
|
||||
Dy::ArticulationData& data = mLLArticulation->getArticulationData();
|
||||
Dy::ArticulationLink* links = data.getLinks();
|
||||
Dy::ArticulationJointCoreData* jointData = data.getJointData();
|
||||
|
||||
Dy::ArticulationLink& link = links[linkID];
|
||||
Dy::ArticulationJointCore* joint = link.inboundJoint;
|
||||
Dy::ArticulationJointCoreData& jointDatum = jointData[linkID];
|
||||
|
||||
PxReal* jointVelocites = data.getJointVelocities();
|
||||
PxReal* jointPositions = data.getJointPositions();
|
||||
|
||||
PxReal* jVelocities = &jointVelocites[jointDatum.jointOffset];
|
||||
PxReal* jPositions = &jointPositions[jointDatum.jointOffset];
|
||||
|
||||
for(PxU8 i = 0; i < jointDatum.nbDof; ++i)
|
||||
{
|
||||
const PxU32 dofId = joint->dofIds[i];
|
||||
joint->jointPos[dofId] = jPositions[i];
|
||||
joint->jointVel[dofId] = jVelocities[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::updateCCDLinks(PxArray<BodySim*>& sims)
|
||||
{
|
||||
|
||||
for (PxU32 a = 0; a < mBodies.size(); ++a)
|
||||
{
|
||||
if (mBodies[a]->getLowLevelBody().getCore().mFlags & PxRigidBodyFlag::eENABLE_CCD)
|
||||
{
|
||||
sims.pushBack(mBodies[a]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::putToSleep()
|
||||
{
|
||||
for (PxU32 i = 0; i < mLinks.size(); i++)
|
||||
{
|
||||
BodySim* bodySim = mBodies[i];
|
||||
PxsRigidBody& rigid = bodySim->getLowLevelBody();
|
||||
|
||||
PxsBodyCore& bodyCore = bodySim->getBodyCore().getCore();
|
||||
|
||||
//rigid.setPose(rigid.getLastCCDTransform());
|
||||
|
||||
//KS - the IG deactivates bodies in parallel with the solver. It appears that under certain circumstances, the solver's integration (which performs
|
||||
//sleep checks) could decide that the body is no longer a candidate for sleeping on the same frame that the island gen decides to deactivate the island
|
||||
//that the body is contained in. This is a rare occurrence but the behavior we want to emulate is that of IG running before solver so we should therefore
|
||||
//permit the IG to make the authoritative decision over whether the body should be active or inactive.
|
||||
bodyCore.wakeCounter = 0.0f;
|
||||
bodyCore.linearVelocity = PxVec3(0.0f);
|
||||
bodyCore.angularVelocity = PxVec3(0.0f);
|
||||
|
||||
rigid.clearAllFrameFlags();
|
||||
|
||||
//Force update
|
||||
}
|
||||
mScene.getSimulationController()->updateArticulation(mLLArticulation, mIslandNodeIndex);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::sleepCheck(PxReal dt)
|
||||
{
|
||||
if(!mBodies.size())
|
||||
return;
|
||||
|
||||
#if PX_CHECKED
|
||||
{
|
||||
PxReal maxTimer = 0.0f, minTimer = PX_MAX_F32;
|
||||
bool allActive = true, noneActive = true;
|
||||
PX_UNUSED(allActive);
|
||||
PX_UNUSED(noneActive);
|
||||
for(PxU32 i=0;i<mLinks.size();i++)
|
||||
{
|
||||
PxReal timer = mBodies[i]->getBodyCore().getWakeCounter();
|
||||
maxTimer = PxMax(maxTimer, timer);
|
||||
minTimer = PxMin(minTimer, timer);
|
||||
bool active = mBodies[i]->isActive();
|
||||
allActive &= active;
|
||||
noneActive &= !active;
|
||||
}
|
||||
// either all links are asleep, or no links are asleep
|
||||
PX_ASSERT(maxTimer==0 || minTimer!=0);
|
||||
PX_ASSERT(allActive || noneActive);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if(!mBodies[0]->isActive())
|
||||
return;
|
||||
|
||||
const PxReal sleepThreshold = getCore().getCore().sleepThreshold;
|
||||
|
||||
PxReal maxTimer = 0.0f , minTimer = PX_MAX_F32;
|
||||
|
||||
for(PxU32 i=0;i<mLinks.size();i++)
|
||||
{
|
||||
const Cm::SpatialVector& motionVelocity = mLLArticulation->getMotionVelocity(i);
|
||||
PxReal timer = mBodies[i]->updateWakeCounter(dt, sleepThreshold, motionVelocity);
|
||||
maxTimer = PxMax(maxTimer, timer);
|
||||
minTimer = PxMin(minTimer, timer);
|
||||
}
|
||||
|
||||
mCore.setWakeCounterInternal(maxTimer);
|
||||
|
||||
if(maxTimer != 0.0f)
|
||||
{
|
||||
if(minTimer == 0.0f)
|
||||
{
|
||||
// make sure nothing goes to sleep unless everything does
|
||||
for(PxU32 i=0;i<mLinks.size();i++)
|
||||
mBodies[i]->getBodyCore().setWakeCounterFromSim(PxMax(1e-6f, mBodies[i]->getBodyCore().getWakeCounter()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for(PxU32 i=0;i<mLinks.size();i++)
|
||||
{
|
||||
mBodies[i]->notifyReadyForSleeping();
|
||||
mBodies[i]->getLowLevelBody().resetSleepFilter();
|
||||
}
|
||||
|
||||
mScene.getSimpleIslandManager()->deactivateNode(mIslandNodeIndex);
|
||||
}
|
||||
|
||||
bool Sc::ArticulationSim::isSleeping() const
|
||||
{
|
||||
return (mBodies.size() > 0) ? (!mBodies[0]->isActive()) : true;
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::internalWakeUp(PxReal wakeCounter)
|
||||
{
|
||||
if(mCore.getWakeCounter() < wakeCounter)
|
||||
{
|
||||
mCore.setWakeCounterInternal(wakeCounter);
|
||||
for(PxU32 i=0;i<mBodies.size();i++)
|
||||
mBodies[i]->internalWakeUpArticulationLink(wakeCounter);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::updateForces(PxReal dt)
|
||||
{
|
||||
PxU32 count = 0;
|
||||
bool anyForcesApplied = false;
|
||||
|
||||
for(PxU32 i=0;i<mBodies.size();i++)
|
||||
{
|
||||
if (i+1 < mBodies.size())
|
||||
{
|
||||
PxPrefetchLine(mBodies[i+1],128);
|
||||
PxPrefetchLine(mBodies[i+1],256);
|
||||
}
|
||||
|
||||
anyForcesApplied |= mBodies[i]->updateForces(dt, NULL, NULL, count, &mLLArticulation->getSolverDesc().acceleration[i], NULL);
|
||||
}
|
||||
if(anyForcesApplied)
|
||||
mLLArticulation->raiseGPUDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_EXT_ACCEL);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::clearAcceleration(PxReal dt)
|
||||
{
|
||||
PxU32 count = 0;
|
||||
|
||||
bool anyBodyRetains = false;
|
||||
|
||||
for (PxU32 i = 0; i < mBodies.size(); i++)
|
||||
{
|
||||
if (i + 1 < mBodies.size())
|
||||
{
|
||||
PxPrefetchLine(mBodies[i + 1], 128);
|
||||
PxPrefetchLine(mBodies[i + 1], 256);
|
||||
}
|
||||
|
||||
const bool accDirty = mBodies[i]->readVelocityModFlag(VMF_ACC_DIRTY);
|
||||
|
||||
// the code restores the pre-impulse state:
|
||||
// if we only applied an impulse and no acceleration, we clear the acceleration here.
|
||||
// if we applied an acceleration, we re-apply the acceleration terms we have in the velMod.
|
||||
// we cleared out the impulse here when we pushed the data at the start of the sim.
|
||||
|
||||
if (!accDirty)
|
||||
{
|
||||
mLLArticulation->getSolverDesc().acceleration[i].linear = PxVec3(0.f);
|
||||
mLLArticulation->getSolverDesc().acceleration[i].angular = PxVec3(0.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
mBodies[i]->updateForces(dt, NULL, NULL, count, &mLLArticulation->getSolverDesc().acceleration[i], NULL);
|
||||
}
|
||||
|
||||
// we need to raise the dirty flag if retain accelerations is on
|
||||
// because in that case we need to restore the acceleration without impulses. We
|
||||
// can only do that using the CPU->GPU codepath because we don't distinguish between
|
||||
// acceleration and impulses on the GPU.
|
||||
// The flag must be raised here because we don't know at the start of the next sim step
|
||||
// that the data in velMod is actually valid and the articulation would not be added
|
||||
// to the dirty list.
|
||||
|
||||
// without retain accelerations, the accelerations are cleared directly on the GPU.
|
||||
if (mBodies[i]->getFlagsFast() & PxRigidBodyFlag::eRETAIN_ACCELERATIONS)
|
||||
anyBodyRetains = true;
|
||||
}
|
||||
|
||||
if (anyBodyRetains)
|
||||
{
|
||||
mScene.getSimulationController()->updateArticulationExtAccel(mLLArticulation, mIslandNodeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::saveLastCCDTransform()
|
||||
{
|
||||
for(PxU32 i=0;i<mBodies.size();i++)
|
||||
{
|
||||
if (i+1 < mBodies.size())
|
||||
{
|
||||
PxPrefetchLine(mBodies[i+1],128);
|
||||
PxPrefetchLine(mBodies[i+1],256);
|
||||
}
|
||||
mBodies[i]->getLowLevelBody().saveLastCCDTransform();
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::setFixedBaseLink(bool value)
|
||||
{
|
||||
const PxU32 linkCount = mLinks.size();
|
||||
|
||||
if(linkCount > 0)
|
||||
mLinks[0].bodyCore->fixedBaseLink = PxU8(value);
|
||||
}
|
||||
|
||||
PxU32 Sc::ArticulationSim::getDofs() const
|
||||
{
|
||||
return mLLArticulation->getDofs();
|
||||
}
|
||||
|
||||
PxU32 Sc::ArticulationSim::getDof(const PxU32 linkID) const
|
||||
{
|
||||
return mLLArticulation->getDof(linkID);
|
||||
}
|
||||
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(Cm::SpatialVector)==sizeof(PxSpatialForce));
|
||||
PxArticulationCache* Sc::ArticulationSim::createCache()
|
||||
{
|
||||
return FeatherstoneArticulation::createCache(getDofs(), mLinks.size());
|
||||
}
|
||||
|
||||
PxU32 Sc::ArticulationSim::getCacheDataSize() const
|
||||
{
|
||||
return FeatherstoneArticulation::getCacheDataSize(getDofs(), mLinks.size());
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::zeroCache(PxArticulationCache& cache) const
|
||||
{
|
||||
const PxU32 cacheDataSize = getCacheDataSize();
|
||||
|
||||
PxMemZero(cache.externalForces, cacheDataSize);
|
||||
}
|
||||
|
||||
//copy external data to internal data
|
||||
bool Sc::ArticulationSim::applyCache(PxArticulationCache& cache, const PxArticulationCacheFlags flag) const
|
||||
{
|
||||
//checkResize();
|
||||
bool shouldWake = false;
|
||||
if (mLLArticulation->applyCache(cache, flag, shouldWake))
|
||||
{
|
||||
mScene.getSimulationController()->updateArticulation(mLLArticulation, mIslandNodeIndex);
|
||||
}
|
||||
return shouldWake;
|
||||
}
|
||||
|
||||
//copy internal data to external data
|
||||
void Sc::ArticulationSim::copyInternalStateToCache(PxArticulationCache& cache, const PxArticulationCacheFlags flag, const bool isGpuSimEnabled) const
|
||||
{
|
||||
mLLArticulation->copyInternalStateToCache(cache, flag, isGpuSimEnabled);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::packJointData(const PxReal* maximum, PxReal* reduced) const
|
||||
{
|
||||
mLLArticulation->packJointData(maximum, reduced);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::unpackJointData(const PxReal* reduced, PxReal* maximum) const
|
||||
{
|
||||
mLLArticulation->unpackJointData(reduced, maximum);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::commonInit()
|
||||
{
|
||||
mLLArticulation->initializeCommonData();
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::computeGeneralizedGravityForce(PxArticulationCache& cache, const bool rootMotion)
|
||||
{
|
||||
mLLArticulation->getGeneralizedGravityForce(mScene.getGravity(), cache, rootMotion);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::computeCoriolisAndCentrifugalForce(PxArticulationCache& cache, const bool rootMotion)
|
||||
{
|
||||
mLLArticulation->getCoriolisAndCentrifugalForce(cache, rootMotion);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::computeGeneralizedExternalForce(PxArticulationCache& cache)
|
||||
{
|
||||
mLLArticulation->getGeneralizedExternalForce(cache);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::computeJointAcceleration(PxArticulationCache& cache)
|
||||
{
|
||||
mLLArticulation->getJointAcceleration(mScene.getGravity(), cache);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::computeJointForce(PxArticulationCache& cache)
|
||||
{
|
||||
mLLArticulation->getJointForce(cache);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::computeDenseJacobian(PxArticulationCache& cache, PxU32& nRows, PxU32& nCols)
|
||||
{
|
||||
mLLArticulation->getDenseJacobian(cache, nRows, nCols);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::computeCoefficientMatrix(PxArticulationCache& cache)
|
||||
{
|
||||
mLLArticulation->getCoefficientMatrixWithLoopJoints(mLoopConstraints.begin(), mLoopConstraints.size(), cache);
|
||||
}
|
||||
|
||||
bool Sc::ArticulationSim::computeLambda(PxArticulationCache& cache, PxArticulationCache& initialState,
|
||||
const PxReal* const jointTorque, const PxVec3 gravity, const PxU32 maxIter)
|
||||
{
|
||||
const PxReal invLengthScale = 1.f / mScene.getLengthScale();
|
||||
return mLLArticulation->getLambda(mLoopConstraints.begin(), mLoopConstraints.size(), cache, initialState, jointTorque, gravity, maxIter, invLengthScale);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::computeGeneralizedMassMatrix(PxArticulationCache& cache, const bool rootMotion)
|
||||
{
|
||||
mLLArticulation->getGeneralizedMassMatrixCRB(cache, rootMotion);
|
||||
|
||||
/*const PxU32 totalDofs = mLLArticulation->getDofs();
|
||||
|
||||
PxReal* massMatrix = reinterpret_cast<PxReal*>(PX_ALLOC(sizeof(PxReal) * totalDofs * totalDofs, "MassMatrix"));
|
||||
PxMemCopy(massMatrix, cache.massMatrix, sizeof(PxReal)*totalDofs * totalDofs);
|
||||
|
||||
mLLArticulation->getGeneralizedMassMatrix(cache);
|
||||
|
||||
PxReal* massMatrix1 = cache.massMatrix;
|
||||
for (PxU32 i = 0; i < totalDofs; ++i)
|
||||
{
|
||||
PxReal* row = &massMatrix1[i * totalDofs];
|
||||
|
||||
for (PxU32 j = 0; j < totalDofs; ++j)
|
||||
{
|
||||
const PxReal dif = row[j] - massMatrix[j*totalDofs + i];
|
||||
PX_ASSERT (PxAbs(dif) < 2e-4f)
|
||||
}
|
||||
}
|
||||
|
||||
PX_FREE(massMatrix);*/
|
||||
}
|
||||
|
||||
PxVec3 Sc::ArticulationSim::computeArticulationCOM(const bool rootFrame)
|
||||
{
|
||||
return mLLArticulation->getArticulationCOM(rootFrame);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::computeCentroidalMomentumMatrix(PxArticulationCache& cache)
|
||||
{
|
||||
mLLArticulation->getCentroidalMomentumMatrix(cache);
|
||||
}
|
||||
|
||||
PxU32 Sc::ArticulationSim::getCoefficientMatrixSize() const
|
||||
{
|
||||
const PxU32 size = mLoopConstraints.size();
|
||||
const PxU32 totalDofs = mLLArticulation->getDofs();
|
||||
return size * totalDofs;
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::setRootLinearVelocity(const PxVec3& velocity)
|
||||
{
|
||||
mLLArticulation->setRootLinearVelocity(velocity);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::setRootAngularVelocity(const PxVec3& velocity)
|
||||
{
|
||||
mLLArticulation->setRootAngularVelocity(velocity);
|
||||
}
|
||||
|
||||
PxSpatialVelocity Sc::ArticulationSim::getLinkVelocity(const PxU32 linkId) const
|
||||
{
|
||||
Cm::SpatialVector vel = mLLArticulation->getLinkScalarVelocity(linkId);
|
||||
return reinterpret_cast<PxSpatialVelocity&>(vel);
|
||||
}
|
||||
|
||||
PxSpatialVelocity Sc::ArticulationSim::getLinkAcceleration(const PxU32 linkId, const bool isGpuSimEnabled) const
|
||||
{
|
||||
Cm::SpatialVector accel = mLLArticulation->getMotionAcceleration(linkId, isGpuSimEnabled);
|
||||
return reinterpret_cast<PxSpatialVelocity&>(accel);
|
||||
}
|
||||
|
||||
// This method allows user teleport the root links and the articulation
|
||||
//system update all other links pose
|
||||
void Sc::ArticulationSim::setGlobalPose()
|
||||
{
|
||||
mLLArticulation->teleportRootLink();
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::setJointDirty(Dy::ArticulationJointCore& jointCore)
|
||||
{
|
||||
PX_UNUSED(jointCore);
|
||||
mScene.getSimulationController()->updateArticulationJoint(mLLArticulation, mIslandNodeIndex);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::setArticulationDirty(PxU32 flag)
|
||||
{
|
||||
Dy::FeatherstoneArticulation* featherstoneArtic = static_cast<Dy::FeatherstoneArticulation*>(mLLArticulation);
|
||||
featherstoneArtic->raiseGPUDirtyFlag(Dy::ArticulationDirtyFlag::Enum(flag));
|
||||
mScene.getSimulationController()->updateArticulation(mLLArticulation, mIslandNodeIndex);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::debugCheckWakeCounterOfLinks(PxReal wakeCounter) const
|
||||
{
|
||||
PX_UNUSED(wakeCounter);
|
||||
|
||||
#if PX_DEBUG
|
||||
// make sure the links are in sync with the articulation
|
||||
for(PxU32 i=0; i < mBodies.size(); i++)
|
||||
{
|
||||
PX_ASSERT(mBodies[i]->getBodyCore().getWakeCounter() == wakeCounter);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::debugCheckSleepStateOfLinks(bool isSleeping) const
|
||||
{
|
||||
PX_UNUSED(isSleeping);
|
||||
|
||||
#if PX_DEBUG
|
||||
// make sure the links are in sync with the articulation
|
||||
for(PxU32 i=0; i < mBodies.size(); i++)
|
||||
{
|
||||
if (isSleeping)
|
||||
{
|
||||
PX_ASSERT(!mBodies[i]->isActive());
|
||||
PX_ASSERT(mBodies[i]->getBodyCore().getWakeCounter() == 0.0f);
|
||||
PX_ASSERT(mBodies[i]->checkSleepReadinessBesidesWakeCounter());
|
||||
}
|
||||
else
|
||||
PX_ASSERT(mBodies[i]->isActive());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PxU32 Sc::ArticulationSim::getRootActorIndex() const
|
||||
{
|
||||
return mBodies[0]->getActorID();
|
||||
}
|
||||
228
engine/third_party/physx/source/simulationcontroller/src/ScArticulationSim.h
vendored
Normal file
228
engine/third_party/physx/source/simulationcontroller/src/ScArticulationSim.h
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ARTICULATION_SIM_H
|
||||
#define SC_ARTICULATION_SIM_H
|
||||
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "ScArticulationCore.h"
|
||||
#include "PxsSimpleIslandManager.h"
|
||||
#include "DyArticulationTendon.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Bp
|
||||
{
|
||||
class BoundsArray;
|
||||
}
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
class BodySim;
|
||||
class BodyCore;
|
||||
class ArticulationJointSim;
|
||||
class ArticulationSpatialTendonSim;
|
||||
class ArticulationFixedTendonSim;
|
||||
class ArticulationMimicJointSim;
|
||||
class ArticulationCore;
|
||||
class Scene;
|
||||
class ConstraintSim;
|
||||
|
||||
struct ArticulationSimDirtyFlag
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eNONE = 0,
|
||||
eUPDATE = 1 << 0
|
||||
};
|
||||
};
|
||||
|
||||
typedef PxFlags<ArticulationSimDirtyFlag::Enum, PxU32> ArticulationSimDirtyFlags;
|
||||
|
||||
class ArticulationSim : public PxUserAllocated
|
||||
{
|
||||
PX_NOCOPY(ArticulationSim)
|
||||
public:
|
||||
ArticulationSim(ArticulationCore& core,
|
||||
Scene& scene,
|
||||
BodyCore& root);
|
||||
|
||||
~ArticulationSim();
|
||||
|
||||
PX_FORCE_INLINE Dy::FeatherstoneArticulation* getLowLevelArticulation() const { return mLLArticulation; }
|
||||
PX_FORCE_INLINE ArticulationCore& getCore() const { return mCore; }
|
||||
|
||||
//we don't need removeBody method anymore because when the articulation is removed from the scene, the articulation sim will
|
||||
//get completely distroy and when we re-add the articulation to the scene, all the data will get recomputed
|
||||
void addBody(BodySim& body,
|
||||
BodySim* parent,
|
||||
ArticulationJointSim* joint);
|
||||
|
||||
void removeBody(BodySim& body);
|
||||
|
||||
//we don't need complementary removeTendon/removeMimicJoint functions because
|
||||
//the articulation sim will be completely destroyed when the articulation is removed from the scene.
|
||||
//When we re-add the articulation to the scene all the data will be recomputed.
|
||||
|
||||
void addTendon(ArticulationSpatialTendonSim* const);
|
||||
|
||||
void addTendon(ArticulationFixedTendonSim* const);
|
||||
|
||||
void addMimicJoint(ArticulationMimicJointSim* const mimicJoint, const PxU32 linkA, const PxU32 linkB);
|
||||
|
||||
|
||||
void createLLStructure(); // resize LL memory if necessary
|
||||
void initializeConfiguration();
|
||||
void debugCheckWakeCounterOfLinks(PxReal wakeCounter) const;
|
||||
void debugCheckSleepStateOfLinks(bool isSleeping) const;
|
||||
|
||||
bool isSleeping() const;
|
||||
void internalWakeUp(PxReal wakeCounter); // called when sim sets sleep timer
|
||||
void sleepCheck(PxReal dt);
|
||||
void putToSleep();
|
||||
void updateCCDLinks(PxArray<BodySim*>& sims);
|
||||
void updateCached(PxBitMapPinned* shapehapeChangedMap);
|
||||
void markShapesUpdated(PxBitMapPinned* shapeChangedMap);
|
||||
void updateContactDistance(PxReal* contactDistance, PxReal dt, const Bp::BoundsArray& boundsArray);
|
||||
|
||||
void setActive(bool b, bool asPartOfCreation=false);
|
||||
|
||||
void updateForces(PxReal dt);
|
||||
void saveLastCCDTransform();
|
||||
|
||||
void clearAcceleration(PxReal dt);
|
||||
|
||||
void setFixedBaseLink(bool value);
|
||||
//external reduced coordinate implementation
|
||||
PxU32 getDofs() const;
|
||||
|
||||
//This function return the dof of the inbound joint, which belong to a link with corresponding linkID
|
||||
PxU32 getDof(const PxU32 linkID) const;
|
||||
|
||||
PxArticulationCache* createCache();
|
||||
|
||||
PxU32 getCacheDataSize() const;
|
||||
|
||||
void zeroCache(PxArticulationCache&) const;
|
||||
|
||||
bool applyCache(PxArticulationCache& cache, const PxArticulationCacheFlags flag) const;
|
||||
|
||||
void copyInternalStateToCache
|
||||
(PxArticulationCache& cache, const PxArticulationCacheFlags flag, const bool isGpuSimEnabled) const;
|
||||
|
||||
void packJointData(const PxReal* maximum, PxReal* reduced) const;
|
||||
|
||||
void unpackJointData(const PxReal* reduced, PxReal* maximum) const;
|
||||
|
||||
void commonInit();
|
||||
|
||||
void computeGeneralizedGravityForce(PxArticulationCache& cache, const bool rootMotion);
|
||||
|
||||
void computeCoriolisAndCentrifugalForce(PxArticulationCache& cache, const bool rootMotion);
|
||||
|
||||
void computeGeneralizedExternalForce(PxArticulationCache& cache);
|
||||
|
||||
void computeJointAcceleration(PxArticulationCache& cache);
|
||||
|
||||
void computeJointForce(PxArticulationCache& cache);
|
||||
|
||||
void computeKinematicJacobian(const PxU32 linkID, PxArticulationCache& cache);
|
||||
|
||||
void computeDenseJacobian(PxArticulationCache& cache, PxU32& nRows, PxU32& nCols);
|
||||
|
||||
void computeCoefficientMatrix(PxArticulationCache& cache);
|
||||
|
||||
bool computeLambda(PxArticulationCache& cache, PxArticulationCache& rollBackCache, const PxReal* jointTorque, const PxVec3 gravity, const PxU32 maxIter);
|
||||
|
||||
void computeGeneralizedMassMatrix(PxArticulationCache& cache, const bool rootMotion);
|
||||
|
||||
PxVec3 computeArticulationCOM(const bool rootFrame);
|
||||
|
||||
void computeCentroidalMomentumMatrix(PxArticulationCache& cache);
|
||||
|
||||
PxU32 getCoefficientMatrixSize() const;
|
||||
|
||||
void setRootLinearVelocity(const PxVec3& velocity);
|
||||
void setRootAngularVelocity(const PxVec3& velocity);
|
||||
PxSpatialVelocity getLinkVelocity(const PxU32 linkId) const;
|
||||
|
||||
PxSpatialVelocity getLinkAcceleration(const PxU32 linkId, const bool isGpuSimEnabled) const;
|
||||
|
||||
//internal method implementation
|
||||
PX_FORCE_INLINE PxNodeIndex getIslandNodeIndex() const { return mIslandNodeIndex; }
|
||||
|
||||
void setGlobalPose();
|
||||
|
||||
PxU32 findBodyIndex(BodySim &body) const;
|
||||
|
||||
void setJointDirty(Dy::ArticulationJointCore& jointCore);
|
||||
|
||||
void addLoopConstraint(ConstraintSim* constraint);
|
||||
void removeLoopConstraint(ConstraintSim* constraint);
|
||||
|
||||
PX_FORCE_INLINE PxU32 getMaxDepth() { return mMaxDepth; }
|
||||
|
||||
void setArticulationDirty(PxU32 flag);
|
||||
|
||||
PX_FORCE_INLINE void setDirtyFlag(ArticulationSimDirtyFlag::Enum flag) { mDirtyFlags = flag; }
|
||||
PX_FORCE_INLINE ArticulationSimDirtyFlags getDirtyFlag() const { return mDirtyFlags; }
|
||||
|
||||
PX_FORCE_INLINE const Dy::ArticulationLink& getLink(const PxU32 linkId) const { return mLinks[linkId]; }
|
||||
|
||||
PxU32 getRootActorIndex() const;
|
||||
|
||||
void updateKinematic(PxArticulationKinematicFlags flags);
|
||||
|
||||
void copyJointStatus(const PxU32 linkIndex);
|
||||
|
||||
PX_FORCE_INLINE bool isLLArticulationInitialized() const { return mIsLLArticulationInitialized; }
|
||||
private:
|
||||
Dy::FeatherstoneArticulation* mLLArticulation;
|
||||
Scene& mScene;
|
||||
ArticulationCore& mCore;
|
||||
PxArray<Dy::ArticulationLink> mLinks;
|
||||
PxArray<BodySim*> mBodies;
|
||||
PxArray<ArticulationJointSim*> mJoints;
|
||||
PxArray<Dy::ArticulationSpatialTendon*> mSpatialTendons;
|
||||
PxArray<Dy::ArticulationFixedTendon*> mFixedTendons;
|
||||
PxArray<Dy::ArticulationMimicJointCore*> mMimicJoints;
|
||||
|
||||
PxNodeIndex mIslandNodeIndex;
|
||||
PxArray <Dy::ArticulationLoopConstraint> mLoopConstraints;
|
||||
PxU32 mMaxDepth;
|
||||
bool mIsLLArticulationInitialized;
|
||||
ArticulationSimDirtyFlags mDirtyFlags;
|
||||
};
|
||||
|
||||
ArticulationSim* getArticulationSim(const IG::IslandSim& islandSim, PxNodeIndex nodeIndex);
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
163
engine/third_party/physx/source/simulationcontroller/src/ScArticulationTendonCore.cpp
vendored
Normal file
163
engine/third_party/physx/source/simulationcontroller/src/ScArticulationTendonCore.cpp
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScArticulationTendonCore.h"
|
||||
#include "ScArticulationTendonSim.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
void Sc::ArticulationSpatialTendonCore::setStiffness(const PxReal stiffness)
|
||||
{
|
||||
mStiffness = stiffness;
|
||||
|
||||
if (mSim)
|
||||
mSim->setStiffness(stiffness);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationSpatialTendonCore::getStiffness() const
|
||||
{
|
||||
return mStiffness;
|
||||
}
|
||||
|
||||
void Sc::ArticulationSpatialTendonCore::setDamping(const PxReal damping)
|
||||
{
|
||||
mDamping = damping;
|
||||
|
||||
if (mSim)
|
||||
mSim->setDamping(damping);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationSpatialTendonCore::getDamping() const
|
||||
{
|
||||
return mDamping;
|
||||
}
|
||||
|
||||
void Sc::ArticulationSpatialTendonCore::setLimitStiffness(const PxReal stiffness)
|
||||
{
|
||||
mLimitStiffness = stiffness;
|
||||
|
||||
if (mSim)
|
||||
mSim->setLimitStiffness(stiffness);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationSpatialTendonCore::getLimitStiffness() const
|
||||
{
|
||||
return mLimitStiffness;
|
||||
}
|
||||
|
||||
void Sc::ArticulationSpatialTendonCore::setOffset(const PxReal offset)
|
||||
{
|
||||
mOffset = offset;
|
||||
|
||||
if (mSim)
|
||||
mSim->setOffset(offset);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationSpatialTendonCore::getOffset() const
|
||||
{
|
||||
return mOffset;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Sc::ArticulationFixedTendonCore::setStiffness(const PxReal stiffness)
|
||||
{
|
||||
mStiffness = stiffness;
|
||||
|
||||
if (mSim)
|
||||
mSim->setStiffness(stiffness);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationFixedTendonCore::getStiffness() const
|
||||
{
|
||||
return mStiffness;
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonCore::setDamping(const PxReal damping)
|
||||
{
|
||||
mDamping = damping;
|
||||
|
||||
if (mSim)
|
||||
mSim->setDamping(damping);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationFixedTendonCore::getDamping() const
|
||||
{
|
||||
return mDamping;
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonCore::setLimitStiffness(const PxReal stiffness)
|
||||
{
|
||||
mLimitStiffness = stiffness;
|
||||
if (mSim)
|
||||
mSim->setLimitStiffness(stiffness);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationFixedTendonCore::getLimitStiffness() const
|
||||
{
|
||||
return mLimitStiffness;
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonCore::setSpringRestLength(const PxReal restLength)
|
||||
{
|
||||
mRestLength = restLength;
|
||||
if (mSim)
|
||||
mSim->setSpringRestLength(restLength);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationFixedTendonCore::getSpringRestLength() const
|
||||
{
|
||||
return mRestLength;
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonCore::setLimitRange(const PxReal lowLimit, const PxReal highLimit)
|
||||
{
|
||||
mLowLimit = lowLimit;
|
||||
mHighLimit = highLimit;
|
||||
|
||||
if (mSim)
|
||||
mSim->setLimitRange(lowLimit, highLimit);
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonCore::getLimitRange(PxReal& lowLimit, PxReal& highLimit) const
|
||||
{
|
||||
lowLimit = mLowLimit;
|
||||
highLimit = mHighLimit;
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonCore::setOffset(const PxReal offset)
|
||||
{
|
||||
mOffset = offset;
|
||||
if (mSim)
|
||||
mSim->setOffset(offset);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationFixedTendonCore::getOffset() const
|
||||
{
|
||||
return mOffset;
|
||||
}
|
||||
44
engine/third_party/physx/source/simulationcontroller/src/ScArticulationTendonJointCore.cpp
vendored
Normal file
44
engine/third_party/physx/source/simulationcontroller/src/ScArticulationTendonJointCore.cpp
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScArticulationTendonJointCore.h"
|
||||
#include "ScArticulationTendonSim.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
void Sc::ArticulationTendonJointCore::setCoefficient(PxArticulationAxis::Enum axis_, const PxReal coefficient_, const PxReal recipCoefficient_)
|
||||
{
|
||||
axis = axis_;
|
||||
coefficient = coefficient_;
|
||||
recipCoefficient = recipCoefficient_;
|
||||
|
||||
if (mTendonSim)
|
||||
{
|
||||
mTendonSim->setTendonJointCoefficient(*this, axis_, coefficient, recipCoefficient);
|
||||
}
|
||||
}
|
||||
373
engine/third_party/physx/source/simulationcontroller/src/ScArticulationTendonSim.cpp
vendored
Normal file
373
engine/third_party/physx/source/simulationcontroller/src/ScArticulationTendonSim.cpp
vendored
Normal file
@@ -0,0 +1,373 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScArticulationTendonSim.h"
|
||||
#include "ScArticulationTendonCore.h"
|
||||
#include "ScArticulationAttachmentCore.h"
|
||||
#include "ScArticulationTendonJointCore.h"
|
||||
#include "ScArticulationJointCore.h"
|
||||
#include "ScScene.h"
|
||||
#include "DyArticulationTendon.h"
|
||||
#include "ScArticulationSim.h"
|
||||
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::ArticulationSpatialTendonSim::ArticulationSpatialTendonSim(ArticulationSpatialTendonCore& tendon, Scene& scene) :
|
||||
mTendonCore(tendon), mScene(scene)
|
||||
{
|
||||
mTendonCore.setSim(this);
|
||||
mLLTendon.mStiffness = tendon.mStiffness;
|
||||
mLLTendon.mDamping = tendon.mDamping;
|
||||
mLLTendon.mOffset = tendon.mOffset;
|
||||
mLLTendon.mLimitStiffness = tendon.mLimitStiffness;
|
||||
}
|
||||
|
||||
|
||||
Sc::ArticulationSpatialTendonSim::~ArticulationSpatialTendonSim()
|
||||
{
|
||||
mTendonCore.setSim(NULL);
|
||||
}
|
||||
|
||||
|
||||
void Sc::ArticulationSpatialTendonSim::setStiffness(const PxReal stiffness)
|
||||
{
|
||||
mLLTendon.mStiffness = stiffness;
|
||||
|
||||
Dy::FeatherstoneArticulation* llArticulation = static_cast<Dy::FeatherstoneArticulation*>(mArtiSim->getLowLevelArticulation());
|
||||
llArticulation->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_SPATIAL_TENDON);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationSpatialTendonSim::getStiffness() const
|
||||
{
|
||||
return mLLTendon.mStiffness;
|
||||
}
|
||||
|
||||
void Sc::ArticulationSpatialTendonSim::setDamping(const PxReal damping)
|
||||
{
|
||||
mLLTendon.mDamping = damping;
|
||||
|
||||
Dy::FeatherstoneArticulation* llArticulation = static_cast<Dy::FeatherstoneArticulation*>(mArtiSim->getLowLevelArticulation());
|
||||
llArticulation->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_SPATIAL_TENDON);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationSpatialTendonSim::getDamping() const
|
||||
{
|
||||
return mLLTendon.mDamping;
|
||||
}
|
||||
|
||||
void Sc::ArticulationSpatialTendonSim::setLimitStiffness(const PxReal stiffness)
|
||||
{
|
||||
mLLTendon.mLimitStiffness = stiffness;
|
||||
|
||||
Dy::FeatherstoneArticulation* llArticulation = static_cast<Dy::FeatherstoneArticulation*>(mArtiSim->getLowLevelArticulation());
|
||||
llArticulation->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_FIXED_TENDON);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationSpatialTendonSim::getLimitStiffness() const
|
||||
{
|
||||
return mLLTendon.mLimitStiffness;
|
||||
}
|
||||
|
||||
void Sc::ArticulationSpatialTendonSim::setOffset(const PxReal offset)
|
||||
{
|
||||
mLLTendon.mOffset = offset;
|
||||
|
||||
Dy::FeatherstoneArticulation* llArticulation = static_cast<Dy::FeatherstoneArticulation*>(mArtiSim->getLowLevelArticulation());
|
||||
llArticulation->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_SPATIAL_TENDON);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationSpatialTendonSim::getOffset() const
|
||||
{
|
||||
return mLLTendon.mOffset;
|
||||
}
|
||||
|
||||
|
||||
void Sc::ArticulationSpatialTendonSim::setAttachmentCoefficient(ArticulationAttachmentCore& core, const PxReal coefficient)
|
||||
{
|
||||
const PxU32 index = core.mAttachmentIndex;
|
||||
|
||||
Dy::ArticulationAttachment& attachment = mLLTendon.getAttachment(index);
|
||||
|
||||
attachment.coefficient = coefficient;
|
||||
|
||||
Dy::FeatherstoneArticulation* llArticulation = static_cast<Dy::FeatherstoneArticulation*>(mArtiSim->getLowLevelArticulation());
|
||||
llArticulation->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_SPATIAL_TENDON_ATTACHMENT);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSpatialTendonSim::setAttachmentRelativeOffset(ArticulationAttachmentCore& core, const PxVec3& offset)
|
||||
{
|
||||
const PxU32 index = core.mAttachmentIndex;
|
||||
|
||||
Dy::ArticulationAttachment& attachment = mLLTendon.getAttachment(index);
|
||||
|
||||
attachment.relativeOffset = offset;
|
||||
|
||||
Dy::FeatherstoneArticulation* llArticulation = static_cast<Dy::FeatherstoneArticulation*>(mArtiSim->getLowLevelArticulation());
|
||||
llArticulation->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_SPATIAL_TENDON_ATTACHMENT);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSpatialTendonSim::setAttachmentLimits(ArticulationAttachmentCore& core, const PxReal lowLimit, const PxReal highLimit)
|
||||
{
|
||||
const PxU32 index = core.mAttachmentIndex;
|
||||
|
||||
Dy::ArticulationAttachment& attachment = mLLTendon.getAttachment(index);
|
||||
|
||||
attachment.lowLimit = lowLimit;
|
||||
attachment.highLimit = highLimit;
|
||||
|
||||
Dy::FeatherstoneArticulation* llArticulation = static_cast<Dy::FeatherstoneArticulation*>(mArtiSim->getLowLevelArticulation());
|
||||
llArticulation->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_SPATIAL_TENDON_ATTACHMENT);
|
||||
}
|
||||
|
||||
void Sc::ArticulationSpatialTendonSim::setAttachmentRestLength(ArticulationAttachmentCore& core, const PxReal restLength)
|
||||
{
|
||||
const PxU32 index = core.mAttachmentIndex;
|
||||
Dy::ArticulationAttachment& attachment = mLLTendon.getAttachment(index);
|
||||
attachment.restLength = restLength;
|
||||
|
||||
Dy::FeatherstoneArticulation* llArticulation = static_cast<Dy::FeatherstoneArticulation*>(mArtiSim->getLowLevelArticulation());
|
||||
llArticulation->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_SPATIAL_TENDON_ATTACHMENT);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Sc::ArticulationSpatialTendonSim::addAttachment(ArticulationAttachmentCore& core)
|
||||
{
|
||||
|
||||
const PxU32 index = mLLTendon.getNewID();
|
||||
|
||||
Dy::ArticulationAttachment& attachment = mLLTendon.getAttachment(index);
|
||||
|
||||
attachment.relativeOffset = core.mRelativeOffset;
|
||||
attachment.linkInd = PxU16(core.mLLLinkIndex);
|
||||
attachment.lowLimit = core.mLowLimit;
|
||||
attachment.highLimit = core.mHighLimit;
|
||||
attachment.coefficient = core.mCoefficient;
|
||||
attachment.myInd = index;
|
||||
attachment.children = 0;
|
||||
attachment.childCount = 0;
|
||||
attachment.restLength = core.mRestLength;
|
||||
|
||||
core.mAttachmentIndex = index;
|
||||
core.mTendonSim = this;
|
||||
|
||||
if (core.mParent)
|
||||
{
|
||||
const PxU32 parentIndex = core.mParent->mAttachmentIndex;
|
||||
attachment.parent = parentIndex;
|
||||
mLLTendon.getAttachment(parentIndex).children |= Dy::ArticulationAttachmentBitField(1) << index;
|
||||
mLLTendon.getAttachment(parentIndex).childCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
attachment.parent = DY_ARTICULATION_ATTACHMENT_NONE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Sc::ArticulationSpatialTendonSim::removeAttachment(ArticulationAttachmentCore& core)
|
||||
{
|
||||
const PxU32 index = core.mAttachmentIndex;
|
||||
|
||||
Dy::ArticulationAttachment& attachment = mLLTendon.getAttachment(index);
|
||||
|
||||
PX_ASSERT(attachment.childCount == 0);
|
||||
|
||||
if (attachment.parent != DY_ARTICULATION_ATTACHMENT_NONE)
|
||||
{
|
||||
Dy::ArticulationAttachment& parent = mLLTendon.getAttachment(attachment.parent);
|
||||
parent.children &= ~(Dy::ArticulationAttachmentBitField(1) << index);
|
||||
parent.childCount--;
|
||||
}
|
||||
|
||||
mLLTendon.freeID(index);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Sc::ArticulationFixedTendonSim::ArticulationFixedTendonSim(ArticulationFixedTendonCore& tendon, Scene& scene) :
|
||||
mTendonCore(tendon), mScene(scene)
|
||||
{
|
||||
mTendonCore.setSim(this);
|
||||
mLLTendon.mStiffness = tendon.mStiffness;
|
||||
mLLTendon.mDamping = tendon.mDamping;
|
||||
mLLTendon.mOffset = tendon.mOffset;
|
||||
mLLTendon.mLimitStiffness = tendon.mLimitStiffness;
|
||||
mLLTendon.mLowLimit = tendon.mLowLimit;
|
||||
mLLTendon.mHighLimit = tendon.mHighLimit;
|
||||
mLLTendon.mRestLength = tendon.mRestLength;
|
||||
}
|
||||
|
||||
Sc::ArticulationFixedTendonSim::~ArticulationFixedTendonSim()
|
||||
{
|
||||
mTendonCore.setSim(NULL);
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonSim::setStiffness(const PxReal stiffness)
|
||||
{
|
||||
mLLTendon.mStiffness = stiffness;
|
||||
|
||||
Dy::FeatherstoneArticulation* llArticulation = static_cast<Dy::FeatherstoneArticulation*>(mArtiSim->getLowLevelArticulation());
|
||||
llArticulation->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_FIXED_TENDON);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationFixedTendonSim::getStiffness() const
|
||||
{
|
||||
return mLLTendon.mStiffness;
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonSim::setDamping(const PxReal damping)
|
||||
{
|
||||
mLLTendon.mDamping = damping;
|
||||
|
||||
Dy::FeatherstoneArticulation* llArticulation = static_cast<Dy::FeatherstoneArticulation*>(mArtiSim->getLowLevelArticulation());
|
||||
llArticulation->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_FIXED_TENDON);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationFixedTendonSim::getDamping() const
|
||||
{
|
||||
return mLLTendon.mDamping;
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonSim::setLimitStiffness(const PxReal stiffness)
|
||||
{
|
||||
mLLTendon.mLimitStiffness = stiffness;
|
||||
|
||||
Dy::FeatherstoneArticulation* llArticulation = static_cast<Dy::FeatherstoneArticulation*>(mArtiSim->getLowLevelArticulation());
|
||||
llArticulation->setGpuDirtyFlag(Dy::ArticulationDirtyFlag::eDIRTY_FIXED_TENDON);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationFixedTendonSim::getLimitStiffness() const
|
||||
{
|
||||
return mLLTendon.mLimitStiffness;
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonSim::setOffset(const PxReal offset)
|
||||
{
|
||||
mLLTendon.mOffset = offset;
|
||||
|
||||
mArtiSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_FIXED_TENDON);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationFixedTendonSim::getOffset() const
|
||||
{
|
||||
return mLLTendon.mOffset;
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonSim::setSpringRestLength(const PxReal restLength)
|
||||
{
|
||||
mLLTendon.mRestLength = restLength;
|
||||
|
||||
mArtiSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_FIXED_TENDON);
|
||||
}
|
||||
|
||||
PxReal Sc::ArticulationFixedTendonSim::getSpringRestLength() const
|
||||
{
|
||||
return mLLTendon.mRestLength;
|
||||
}
|
||||
|
||||
|
||||
void Sc::ArticulationFixedTendonSim::setLimitRange(const PxReal lowLimit, const PxReal highLimit)
|
||||
{
|
||||
mLLTendon.mLowLimit = lowLimit;
|
||||
mLLTendon.mHighLimit = highLimit;
|
||||
|
||||
mArtiSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_FIXED_TENDON);
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonSim::getLimitRange(PxReal& lowLimit, PxReal& highLimit) const
|
||||
{
|
||||
lowLimit = mLLTendon.mLowLimit;
|
||||
highLimit = mLLTendon.mHighLimit;
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonSim::addTendonJoint(ArticulationTendonJointCore& tendonJointCore)
|
||||
{
|
||||
|
||||
const PxU32 jointIndex = mLLTendon.getNewID();
|
||||
|
||||
Dy::ArticulationTendonJoint& tendonJoint = mLLTendon.getTendonJoint(jointIndex);
|
||||
|
||||
tendonJoint.axis = PxU16(tendonJointCore.axis);
|
||||
tendonJoint.coefficient = tendonJointCore.coefficient;
|
||||
tendonJoint.recipCoefficient = tendonJointCore.recipCoefficient;
|
||||
tendonJoint.linkInd = PxU16(tendonJointCore.mLLLinkIndex);
|
||||
tendonJoint.children = 0;
|
||||
tendonJoint.childCount = 0;
|
||||
|
||||
tendonJointCore.mLLTendonJointIndex = jointIndex;
|
||||
//tendonJointCore.mLLTendonJoint = &tendonJoint;
|
||||
tendonJointCore.mTendonSim = this;
|
||||
|
||||
if (tendonJointCore.mParent)
|
||||
{
|
||||
const PxU32 parentIndex = tendonJointCore.mParent->mLLTendonJointIndex;
|
||||
tendonJoint.parent = parentIndex;
|
||||
mLLTendon.getTendonJoint(parentIndex).children |= Dy::ArticulationAttachmentBitField(1) << jointIndex;
|
||||
mLLTendon.getTendonJoint(parentIndex).childCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
tendonJoint.parent = DY_ARTICULATION_ATTACHMENT_NONE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonSim::removeTendonJoint(ArticulationTendonJointCore& core)
|
||||
{
|
||||
const PxU32 index = core.mLLTendonJointIndex;
|
||||
|
||||
Dy::ArticulationTendonJoint& tendonJoint = mLLTendon.getTendonJoint(index);
|
||||
|
||||
PX_ASSERT(tendonJoint.childCount == 0);
|
||||
|
||||
if (tendonJoint.parent != DY_ARTICULATION_ATTACHMENT_NONE)
|
||||
{
|
||||
Dy::ArticulationTendonJoint& parent = mLLTendon.getTendonJoint(tendonJoint.parent);
|
||||
parent.children &= ~(Dy::ArticulationAttachmentBitField(1) << index);
|
||||
parent.childCount--;
|
||||
}
|
||||
|
||||
mLLTendon.freeID(index);
|
||||
}
|
||||
|
||||
void Sc::ArticulationFixedTendonSim::setTendonJointCoefficient(ArticulationTendonJointCore& core, const PxArticulationAxis::Enum axis, const float coefficient, const float recipCoefficient)
|
||||
{
|
||||
const PxU32 index = core.mLLTendonJointIndex;
|
||||
|
||||
Dy::ArticulationTendonJoint& tendonJoint = mLLTendon.getTendonJoint(index);
|
||||
tendonJoint.axis = PxU16(axis);
|
||||
tendonJoint.coefficient = coefficient;
|
||||
tendonJoint.recipCoefficient = recipCoefficient;
|
||||
|
||||
mArtiSim->setArticulationDirty(Dy::ArticulationDirtyFlag::eDIRTY_FIXED_TENDON_JOINT);
|
||||
|
||||
}
|
||||
|
||||
|
||||
123
engine/third_party/physx/source/simulationcontroller/src/ScArticulationTendonSim.h
vendored
Normal file
123
engine/third_party/physx/source/simulationcontroller/src/ScArticulationTendonSim.h
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ARTICULATION_TENDON_SIM_H
|
||||
#define SC_ARTICULATION_TENDON_SIM_H
|
||||
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "DyArticulationTendon.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
|
||||
class ArticulationFixedTendonCore;
|
||||
class ArticulationTendonJointCore;
|
||||
class ArticulationSpatialTendonCore;
|
||||
class ArticulationAttachmentCore;
|
||||
class Scene;
|
||||
class ArticulationJointCore;
|
||||
class ArticulationSim;
|
||||
|
||||
class ArticulationSpatialTendonSim : public PxUserAllocated
|
||||
{
|
||||
PX_NOCOPY(ArticulationSpatialTendonSim)
|
||||
public:
|
||||
ArticulationSpatialTendonSim(ArticulationSpatialTendonCore& tendon, Scene& scene);
|
||||
|
||||
virtual ~ArticulationSpatialTendonSim();
|
||||
|
||||
void setStiffness(const PxReal stiffness);
|
||||
PxReal getStiffness() const;
|
||||
|
||||
void setDamping(const PxReal damping);
|
||||
PxReal getDamping() const;
|
||||
|
||||
void setLimitStiffness(const PxReal stiffness);
|
||||
PxReal getLimitStiffness() const;
|
||||
|
||||
void setOffset(const PxReal offset);
|
||||
PxReal getOffset() const;
|
||||
|
||||
|
||||
void setAttachmentCoefficient(ArticulationAttachmentCore& core, const PxReal coefficient);
|
||||
void setAttachmentRelativeOffset(ArticulationAttachmentCore& core, const PxVec3& offset);
|
||||
void setAttachmentLimits(ArticulationAttachmentCore& core, const PxReal lowLimit, const PxReal highLimit);
|
||||
void setAttachmentRestLength(ArticulationAttachmentCore& core, const PxReal restLength);
|
||||
void addAttachment(ArticulationAttachmentCore& core);
|
||||
void removeAttachment(ArticulationAttachmentCore& core);
|
||||
|
||||
Dy::ArticulationSpatialTendon mLLTendon;
|
||||
ArticulationSpatialTendonCore& mTendonCore;
|
||||
|
||||
ArticulationSim* mArtiSim;
|
||||
Scene& mScene;
|
||||
|
||||
};
|
||||
|
||||
class ArticulationFixedTendonSim : public PxUserAllocated
|
||||
{
|
||||
PX_NOCOPY(ArticulationFixedTendonSim)
|
||||
public:
|
||||
ArticulationFixedTendonSim(ArticulationFixedTendonCore& tendon, Scene& scene);
|
||||
|
||||
virtual ~ArticulationFixedTendonSim();
|
||||
|
||||
void setStiffness(const PxReal stiffness);
|
||||
PxReal getStiffness() const;
|
||||
|
||||
void setDamping(const PxReal damping);
|
||||
PxReal getDamping() const;
|
||||
|
||||
void setLimitStiffness(const PxReal stiffness);
|
||||
PxReal getLimitStiffness() const;
|
||||
|
||||
void setOffset(const PxReal offset);
|
||||
PxReal getOffset() const;
|
||||
|
||||
void setSpringRestLength(const PxReal restLength);
|
||||
PxReal getSpringRestLength() const;
|
||||
|
||||
void setLimitRange(const PxReal lowLimit, const PxReal highLimit);
|
||||
void getLimitRange(PxReal& lowLimit, PxReal& highLimit) const;
|
||||
|
||||
void addTendonJoint(ArticulationTendonJointCore& tendonJointCore);
|
||||
void removeTendonJoint(ArticulationTendonJointCore& core);
|
||||
|
||||
void setTendonJointCoefficient(ArticulationTendonJointCore& core, const PxArticulationAxis::Enum axis, const float coefficient, const float recipCoefficient);
|
||||
|
||||
Dy::ArticulationFixedTendon mLLTendon;
|
||||
ArticulationFixedTendonCore& mTendonCore;
|
||||
|
||||
ArticulationSim* mArtiSim;
|
||||
Scene& mScene;
|
||||
};
|
||||
}//namespace Sc
|
||||
}//namespace physx
|
||||
#endif
|
||||
619
engine/third_party/physx/source/simulationcontroller/src/ScBodyCore.cpp
vendored
Normal file
619
engine/third_party/physx/source/simulationcontroller/src/ScBodyCore.cpp
vendored
Normal file
@@ -0,0 +1,619 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScBodyCore.h"
|
||||
#include "ScBodySim.h"
|
||||
#include "ScPhysics.h"
|
||||
#include "ScScene.h"
|
||||
#include "PxsSimulationController.h"
|
||||
#include "ScArticulationSim.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
static void updateBodySim(Sc::BodyCore& bodyCore)
|
||||
{
|
||||
Sc::BodySim* bodySim = bodyCore.getSim();
|
||||
if(bodySim)
|
||||
bodySim->getScene().updateBodySim(*bodySim);
|
||||
}
|
||||
|
||||
Sc::BodyCore::BodyCore(PxActorType::Enum type, const PxTransform& bodyPose) : RigidCore(type)
|
||||
{
|
||||
const PxTolerancesScale& scale = Physics::getInstance().getTolerancesScale();
|
||||
|
||||
const bool isDynamic = type == PxActorType::eRIGID_DYNAMIC;
|
||||
const float linearDamping = isDynamic ? 0.0f : 0.05f;
|
||||
const float maxLinearVelocitySq = isDynamic ? 1e32f /*PX_MAX_F32*/ : 100.f * 100.f * scale.length * scale.length;
|
||||
const float maxAngularVelocitySq = isDynamic ? 100.0f * 100.0f : 50.0f * 50.0f;
|
||||
|
||||
mCore.init(bodyPose, PxVec3(1.0f), 1.0f, Sc::Physics::sWakeCounterOnCreation, scale.speed, linearDamping, 0.05f, maxLinearVelocitySq, maxAngularVelocitySq,
|
||||
type);
|
||||
}
|
||||
|
||||
Sc::BodyCore::~BodyCore()
|
||||
{
|
||||
PX_ASSERT(getSim() == 0);
|
||||
}
|
||||
|
||||
Sc::BodySim* Sc::BodyCore::getSim() const
|
||||
{
|
||||
return static_cast<BodySim*>(Sc::ActorCore::getSim());
|
||||
}
|
||||
|
||||
void Sc::BodyCore::restoreDynamicData()
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
PX_ASSERT(sim);
|
||||
const SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PxsBodyCore& core = getCore();
|
||||
simStateRestoreBodyProperties(simStateData, core);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
//
|
||||
// BodyCore interface implementation
|
||||
//
|
||||
//--------------------------------------------------------------
|
||||
|
||||
void Sc::BodyCore::setBody2World(const PxTransform& p)
|
||||
{
|
||||
mCore.body2World = p;
|
||||
PX_ASSERT(p.p.isFinite());
|
||||
PX_ASSERT(p.q.isFinite());
|
||||
|
||||
BodySim* sim = getSim();
|
||||
if(sim)
|
||||
{
|
||||
sim->postBody2WorldChange();
|
||||
sim->getScene().updateBodySim(*sim);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setCMassLocalPose(const PxTransform& newBody2Actor)
|
||||
{
|
||||
const PxTransform oldActor2World = mCore.body2World * mCore.getBody2Actor().getInverse();
|
||||
const PxTransform newBody2World = oldActor2World * newBody2Actor;
|
||||
|
||||
PX_ASSERT(newBody2World.p.isFinite());
|
||||
PX_ASSERT(newBody2World.q.isFinite());
|
||||
mCore.body2World = newBody2World;
|
||||
|
||||
setBody2Actor(newBody2Actor);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setLinearVelocity(const PxVec3& v, bool skipBodySimUpdate)
|
||||
{
|
||||
mCore.linearVelocity = v;
|
||||
|
||||
PX_ASSERT(!skipBodySimUpdate || (getFlags() & PxRigidBodyFlag::eKINEMATIC));
|
||||
|
||||
if(!skipBodySimUpdate)
|
||||
updateBodySim(*this);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setAngularVelocity(const PxVec3& v, bool skipBodySimUpdate)
|
||||
{
|
||||
mCore.angularVelocity = v;
|
||||
|
||||
PX_ASSERT(!skipBodySimUpdate || (getFlags() & PxRigidBodyFlag::eKINEMATIC));
|
||||
|
||||
if(!skipBodySimUpdate)
|
||||
updateBodySim(*this);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setCfmScale(PxReal cfmScale)
|
||||
{
|
||||
mCore.cfmScale = cfmScale;
|
||||
|
||||
updateBodySim(*this);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setBody2Actor(const PxTransform& p)
|
||||
{
|
||||
PX_ASSERT(p.p.isFinite());
|
||||
PX_ASSERT(p.q.isFinite());
|
||||
|
||||
mCore.setBody2Actor(p);
|
||||
|
||||
updateBodySim(*this);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::addSpatialAcceleration(const PxVec3* linAcc, const PxVec3* angAcc)
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
PX_ASSERT(sim);
|
||||
sim->addSpatialAcceleration(linAcc, angAcc);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setSpatialAcceleration(const PxVec3* linAcc, const PxVec3* angAcc)
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
PX_ASSERT(sim);
|
||||
sim->setSpatialAcceleration(linAcc, angAcc);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::clearSpatialAcceleration(bool force, bool torque)
|
||||
{
|
||||
PX_ASSERT(force || torque);
|
||||
BodySim* sim = getSim();
|
||||
PX_ASSERT(sim);
|
||||
sim->clearSpatialAcceleration(force, torque);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::addSpatialVelocity(const PxVec3* linVelDelta, const PxVec3* angVelDelta)
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
PX_ASSERT(sim);
|
||||
sim->addSpatialVelocity(linVelDelta, angVelDelta);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::clearSpatialVelocity(bool force, bool torque)
|
||||
{
|
||||
PX_ASSERT(force || torque);
|
||||
BodySim* sim = getSim();
|
||||
PX_ASSERT(sim);
|
||||
sim->clearSpatialVelocity(force, torque);
|
||||
}
|
||||
|
||||
PxReal Sc::BodyCore::getInverseMass() const
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
if(!sim || (!(getFlags() & PxRigidBodyFlag::eKINEMATIC)))
|
||||
{
|
||||
return mCore.inverseMass;
|
||||
}
|
||||
else
|
||||
{
|
||||
const SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PX_ASSERT(simStateData->getKinematicData());
|
||||
return simStateData->getKinematicData()->backupInvMass;
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setInverseMass(PxReal m)
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
if (!sim || (!(getFlags() & PxRigidBodyFlag::eKINEMATIC)))
|
||||
{
|
||||
mCore.inverseMass = m;
|
||||
updateBodySim(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PX_ASSERT(simStateData->getKinematicData());
|
||||
simStateData->getKinematicData()->backupInvMass = m;
|
||||
}
|
||||
}
|
||||
|
||||
const PxVec3& Sc::BodyCore::getInverseInertia() const
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
if (!sim || (!(getFlags() & PxRigidBodyFlag::eKINEMATIC)))
|
||||
{
|
||||
return mCore.inverseInertia;
|
||||
}
|
||||
else
|
||||
{
|
||||
const SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PX_ASSERT(simStateData->getKinematicData());
|
||||
return (simStateData->getKinematicData()->backupInverseInertia);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setInverseInertia(const PxVec3& i)
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
if (!sim || (!(getFlags() & PxRigidBodyFlag::eKINEMATIC)))
|
||||
{
|
||||
mCore.inverseInertia = i;
|
||||
updateBodySim(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PX_ASSERT(simStateData->getKinematicData());
|
||||
simStateData->getKinematicData()->backupInverseInertia = i;
|
||||
}
|
||||
}
|
||||
|
||||
PxReal Sc::BodyCore::getLinearDamping() const
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
if (!sim || (!(getFlags() & PxRigidBodyFlag::eKINEMATIC)))
|
||||
{
|
||||
return mCore.linearDamping;
|
||||
}
|
||||
else
|
||||
{
|
||||
const SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PX_ASSERT(simStateData->getKinematicData());
|
||||
return (simStateData->getKinematicData()->backupLinearDamping);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setLinearDamping(PxReal d)
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
if (!sim || (!(getFlags() & PxRigidBodyFlag::eKINEMATIC)))
|
||||
{
|
||||
mCore.linearDamping = d;
|
||||
updateBodySim(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PX_ASSERT(simStateData->getKinematicData());
|
||||
simStateData->getKinematicData()->backupLinearDamping = d;
|
||||
}
|
||||
}
|
||||
|
||||
PxReal Sc::BodyCore::getAngularDamping() const
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
if (!sim || (!(getFlags() & PxRigidBodyFlag::eKINEMATIC)))
|
||||
{
|
||||
return mCore.angularDamping;
|
||||
}
|
||||
else
|
||||
{
|
||||
const SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PX_ASSERT(simStateData->getKinematicData());
|
||||
return (simStateData->getKinematicData()->backupAngularDamping);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setAngularDamping(PxReal v)
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
if (!sim || (!(getFlags() & PxRigidBodyFlag::eKINEMATIC)))
|
||||
{
|
||||
mCore.angularDamping = v;
|
||||
updateBodySim(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PX_ASSERT(simStateData->getKinematicData());
|
||||
simStateData->getKinematicData()->backupAngularDamping = v;
|
||||
}
|
||||
}
|
||||
|
||||
PxReal Sc::BodyCore::getMaxAngVelSq() const
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
if (!sim || (!(getFlags() & PxRigidBodyFlag::eKINEMATIC)))
|
||||
{
|
||||
return mCore.maxAngularVelocitySq;
|
||||
}
|
||||
else
|
||||
{
|
||||
const SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PX_ASSERT(simStateData->getKinematicData());
|
||||
return (simStateData->getKinematicData()->backupMaxAngVelSq);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setMaxAngVelSq(PxReal v)
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
if (!sim || (!(getFlags() & PxRigidBodyFlag::eKINEMATIC)))
|
||||
{
|
||||
mCore.maxAngularVelocitySq = v;
|
||||
updateBodySim(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PX_ASSERT(simStateData->getKinematicData());
|
||||
simStateData->getKinematicData()->backupMaxAngVelSq = v;
|
||||
}
|
||||
}
|
||||
|
||||
PxReal Sc::BodyCore::getMaxLinVelSq() const
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
if (!sim || (!(getFlags() & PxRigidBodyFlag::eKINEMATIC)))
|
||||
{
|
||||
return mCore.maxLinearVelocitySq;
|
||||
}
|
||||
else
|
||||
{
|
||||
const SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PX_ASSERT(simStateData->getKinematicData());
|
||||
return (simStateData->getKinematicData()->backupMaxLinVelSq);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setMaxLinVelSq(PxReal v)
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
if (!sim || (!(getFlags() & PxRigidBodyFlag::eKINEMATIC)))
|
||||
{
|
||||
mCore.maxLinearVelocitySq = v;
|
||||
updateBodySim(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
SimStateData* simStateData = sim->getSimStateData(true);
|
||||
PX_ASSERT(simStateData);
|
||||
PX_ASSERT(simStateData->getKinematicData());
|
||||
simStateData->getKinematicData()->backupMaxLinVelSq = v;
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setFlags(PxRigidBodyFlags f)
|
||||
{
|
||||
const PxRigidBodyFlags old = mCore.mFlags;
|
||||
if(f != old)
|
||||
{
|
||||
const PxU32 wasKinematic = old & PxRigidBodyFlag::eKINEMATIC;
|
||||
const PxU32 isKinematic = f & PxRigidBodyFlag::eKINEMATIC;
|
||||
const bool switchToKinematic = ((!wasKinematic) && isKinematic);
|
||||
const bool switchToDynamic = (wasKinematic && (!isKinematic));
|
||||
|
||||
mCore.mFlags = f;
|
||||
BodySim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
const PxU32 posePreviewFlag = f & PxRigidBodyFlag::eENABLE_POSE_INTEGRATION_PREVIEW;
|
||||
if(PxU32(old & PxRigidBodyFlag::eENABLE_POSE_INTEGRATION_PREVIEW) != posePreviewFlag)
|
||||
sim->postPosePreviewChange(posePreviewFlag);
|
||||
|
||||
// for those who might wonder about the complexity here:
|
||||
// our current behavior is that you are not allowed to set a kinematic target unless the object is in a scene.
|
||||
// Thus, the kinematic data should only be created/destroyed when we know for sure that we are in a scene.
|
||||
|
||||
if(switchToKinematic)
|
||||
sim->switchToKinematic();
|
||||
else if(switchToDynamic)
|
||||
sim->switchToDynamic();
|
||||
|
||||
const PxU32 wasSpeculativeCCD = old & PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD;
|
||||
const PxU32 isSpeculativeCCD = f & PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD;
|
||||
|
||||
if(wasSpeculativeCCD ^ isSpeculativeCCD)
|
||||
{
|
||||
if(wasSpeculativeCCD)
|
||||
{
|
||||
sim->removeFromSpeculativeCCDMap();
|
||||
|
||||
sim->getLowLevelBody().mInternalFlags &= (~PxsRigidBody::eSPECULATIVE_CCD);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Kinematic body switch puts the body to sleep, so we do not mark the speculative CCD bitmap for this actor to true in this case.
|
||||
if(!switchToKinematic)
|
||||
sim->addToSpeculativeCCDMap();
|
||||
|
||||
sim->getLowLevelBody().mInternalFlags |= (PxsRigidBody::eSPECULATIVE_CCD);
|
||||
}
|
||||
}
|
||||
|
||||
const PxU32 wasIntegrateGyroscopic = old & PxRigidBodyFlag::eENABLE_GYROSCOPIC_FORCES;
|
||||
const PxU32 isIntegrateGyroscopic = f & PxRigidBodyFlag::eENABLE_GYROSCOPIC_FORCES;
|
||||
if (wasIntegrateGyroscopic ^ isIntegrateGyroscopic)
|
||||
{
|
||||
if(wasIntegrateGyroscopic)
|
||||
sim->getLowLevelBody().mInternalFlags &= (~PxsRigidBody::eENABLE_GYROSCOPIC);
|
||||
else
|
||||
sim->getLowLevelBody().mInternalFlags |= (PxsRigidBody::eENABLE_GYROSCOPIC);
|
||||
}
|
||||
|
||||
const PxU32 wasRetainAccel = old & PxRigidBodyFlag::eRETAIN_ACCELERATIONS;
|
||||
const PxU32 isRetainAccel = f & PxRigidBodyFlag::eRETAIN_ACCELERATIONS;
|
||||
|
||||
if (wasRetainAccel ^ isRetainAccel)
|
||||
{
|
||||
if (wasRetainAccel)
|
||||
sim->getLowLevelBody().mInternalFlags &= (~PxsRigidBody::eRETAIN_ACCELERATION);
|
||||
else
|
||||
sim->getLowLevelBody().mInternalFlags |= (PxsRigidBody::eRETAIN_ACCELERATION);
|
||||
}
|
||||
|
||||
//Force flag change through...
|
||||
sim->getScene().updateBodySim(*sim);
|
||||
|
||||
}
|
||||
|
||||
if(switchToKinematic)
|
||||
{
|
||||
if (sim)
|
||||
sim->getLowLevelBody().mInternalFlags |= PxsRigidBody::eVELOCITY_COPY_GPU;
|
||||
putToSleep();
|
||||
|
||||
}
|
||||
|
||||
if(sim)
|
||||
{
|
||||
const PxRigidBodyFlags ktFlags(PxRigidBodyFlag::eUSE_KINEMATIC_TARGET_FOR_SCENE_QUERIES | PxRigidBodyFlag::eKINEMATIC);
|
||||
const bool hadKt = (old & ktFlags) == ktFlags;
|
||||
const bool hasKt = (f & ktFlags) == ktFlags;
|
||||
if(hasKt && !hadKt)
|
||||
sim->destroySqBounds();
|
||||
else if(hadKt && !hasKt)
|
||||
sim->createSqBounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setMaxContactImpulse(PxReal m)
|
||||
{
|
||||
mCore.maxContactImpulse = m;
|
||||
updateBodySim(*this);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setOffsetSlop(PxReal slop)
|
||||
{
|
||||
mCore.offsetSlop = slop;
|
||||
updateBodySim(*this);
|
||||
}
|
||||
|
||||
PxNodeIndex Sc::BodyCore::getInternalIslandNodeIndex() const
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
return sim ? sim->getNodeIndex() : PxNodeIndex(PX_INVALID_NODE);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setWakeCounter(PxReal wakeCounter, bool forceWakeUp)
|
||||
{
|
||||
mCore.wakeCounter = wakeCounter;
|
||||
BodySim* sim = getSim();
|
||||
if(sim)
|
||||
{
|
||||
//wake counter change, we need to trigger dma pxgbodysim data again
|
||||
sim->getScene().updateBodySim(*sim);
|
||||
if ((wakeCounter > 0.0f) || forceWakeUp)
|
||||
sim->wakeUp();
|
||||
sim->postSetWakeCounter(wakeCounter, forceWakeUp);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setSleepThreshold(PxReal t)
|
||||
{
|
||||
mCore.sleepThreshold = t;
|
||||
updateBodySim(*this);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setFreezeThreshold(PxReal t)
|
||||
{
|
||||
mCore.freezeThreshold = t;
|
||||
updateBodySim(*this);
|
||||
}
|
||||
|
||||
bool Sc::BodyCore::isSleeping() const
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
return sim ? !sim->isActive() : true;
|
||||
}
|
||||
|
||||
void Sc::BodyCore::putToSleep()
|
||||
{
|
||||
mCore.linearVelocity = PxVec3(0.0f);
|
||||
mCore.angularVelocity = PxVec3(0.0f);
|
||||
|
||||
// important to clear all values before setting the wake counter because the values decide
|
||||
// whether an object is ready to go to sleep or not.
|
||||
setWakeCounter(0.0f);
|
||||
|
||||
BodySim* sim = getSim();
|
||||
if(sim)
|
||||
sim->putToSleep();
|
||||
}
|
||||
|
||||
void Sc::BodyCore::onOriginShift(const PxVec3& shift)
|
||||
{
|
||||
mCore.body2World.p -= shift;
|
||||
|
||||
BodySim* b = getSim();
|
||||
if(b)
|
||||
b->onOriginShift(shift, getFlags() & PxRigidBodyFlag::eKINEMATIC); // BodySim might not exist if actor has simulation disabled (PxActorFlag::eDISABLE_SIMULATION)
|
||||
}
|
||||
|
||||
// PT: TODO: why do we test against NULL everywhere but not in 'isFrozen' ?
|
||||
PxIntBool Sc::BodyCore::isFrozen() const
|
||||
{
|
||||
return getSim()->isFrozen();
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setSolverIterationCounts(PxU16 c)
|
||||
{
|
||||
mCore.solverIterationCounts = c;
|
||||
Sc::BodySim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
sim->getLowLevelBody().mSolverIterationCounts = c;
|
||||
sim->getScene().setDynamicsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Sc::BodyCore::getKinematicTarget(PxTransform& p) const
|
||||
{
|
||||
PX_ASSERT(mCore.mFlags & PxRigidBodyFlag::eKINEMATIC);
|
||||
const BodySim* sim = getSim();
|
||||
return (sim && simStateGetKinematicTarget(sim->getSimStateData_Unchecked(), p));
|
||||
}
|
||||
|
||||
bool Sc::BodyCore::getHasValidKinematicTarget() const
|
||||
{
|
||||
//The use pattern for this is that we should only look for kinematic data if we know it is kinematic.
|
||||
//We might look for velmod data even if it is kinematic.
|
||||
BodySim* sim = getSim();
|
||||
return (sim && simStateGetHasValidKinematicTarget(sim->getSimStateData_Unchecked()));
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setKinematicTarget(const PxTransform& p, PxReal wakeCounter)
|
||||
{
|
||||
PX_ASSERT(mCore.mFlags & PxRigidBodyFlag::eKINEMATIC);
|
||||
Sc::BodySim* sim = getSim();
|
||||
PX_ASSERT(sim);
|
||||
sim->setKinematicTarget(p);
|
||||
wakeUp(wakeCounter);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::invalidateKinematicTarget()
|
||||
{
|
||||
Sc::BodySim* sim = getSim();
|
||||
PX_ASSERT(sim);
|
||||
simStateInvalidateKinematicTarget(sim->getSimStateData_Unchecked());
|
||||
}
|
||||
|
||||
void Sc::BodyCore::setFixedBaseLink(bool value)
|
||||
{
|
||||
BodySim* sim = getSim();
|
||||
|
||||
if(sim)
|
||||
sim->getLowLevelBody().mCore->fixedBaseLink = PxU8(value);
|
||||
}
|
||||
|
||||
void Sc::BodyCore::onRemoveKinematicFromScene()
|
||||
{
|
||||
PX_ASSERT(mCore.mFlags & PxRigidBodyFlag::eKINEMATIC);
|
||||
PX_ASSERT(getSim() && getSim()->checkSimStateKinematicStatus(true));
|
||||
|
||||
// make sure that a kinematic which is not part of a scene is in the expected state
|
||||
mCore.wakeCounter = 0.0f;
|
||||
mCore.linearVelocity = PxVec3(0.0f);
|
||||
mCore.angularVelocity = PxVec3(0.0f);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
863
engine/third_party/physx/source/simulationcontroller/src/ScBodySim.cpp
vendored
Normal file
863
engine/third_party/physx/source/simulationcontroller/src/ScBodySim.cpp
vendored
Normal file
@@ -0,0 +1,863 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScBodySim.h"
|
||||
#include "ScShapeSim.h"
|
||||
#include "ScScene.h"
|
||||
#include "ScArticulationSim.h"
|
||||
#include "PxsContext.h"
|
||||
#include "PxsSimpleIslandManager.h"
|
||||
#include "PxsSimulationController.h"
|
||||
#include "ScSimStateData.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Dy;
|
||||
using namespace Sc;
|
||||
|
||||
#define PX_FREEZE_INTERVAL 1.5f
|
||||
#define PX_FREE_EXIT_THRESHOLD 4.f
|
||||
#define PX_FREEZE_TOLERANCE 0.25f
|
||||
|
||||
#define PX_SLEEP_DAMPING 0.5f
|
||||
#define PX_FREEZE_SCALE 0.9f
|
||||
|
||||
static void updateBPGroup(ActorSim* sim)
|
||||
{
|
||||
PxU32 nbElems = sim->getNbElements();
|
||||
ElementSim** elems = sim->getElements();
|
||||
while (nbElems--)
|
||||
{
|
||||
ShapeSim* current = static_cast<ShapeSim*>(*elems++);
|
||||
current->updateBPGroup();
|
||||
}
|
||||
}
|
||||
|
||||
BodySim::BodySim(Scene& scene, BodyCore& core, bool compound) :
|
||||
RigidSim (scene, core),
|
||||
mLLBody (&core.getCore(), PX_FREEZE_INTERVAL),
|
||||
mSimStateData (NULL),
|
||||
mVelModState (VMF_GRAVITY_DIRTY),
|
||||
mArticulation (NULL)
|
||||
{
|
||||
core.getCore().numCountedInteractions = 0;
|
||||
core.getCore().disableGravity = core.getActorFlags() & PxActorFlag::eDISABLE_GRAVITY;
|
||||
if(core.getFlags() & PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD)
|
||||
mLLBody.mInternalFlags |= PxsRigidBody::eSPECULATIVE_CCD;
|
||||
|
||||
if(core.getFlags() & PxRigidBodyFlag::eENABLE_GYROSCOPIC_FORCES)
|
||||
mLLBody.mInternalFlags |= PxsRigidBody::eENABLE_GYROSCOPIC;
|
||||
|
||||
if(core.getFlags() & PxRigidBodyFlag::eRETAIN_ACCELERATIONS)
|
||||
mLLBody.mInternalFlags |= PxsRigidBody::eRETAIN_ACCELERATION;
|
||||
|
||||
// PT: don't read the core ptr we just wrote, use input param
|
||||
// PT: at time of writing we get a big L2 here because even though bodycore has been prefetched, the wake counter is 160 bytes away
|
||||
const bool isAwake = (core.getWakeCounter() > 0) ||
|
||||
(!core.getLinearVelocity().isZero()) ||
|
||||
(!core.getAngularVelocity().isZero());
|
||||
|
||||
const bool isKine = isKinematic();
|
||||
|
||||
IG::SimpleIslandManager* simpleIslandManager = scene.getSimpleIslandManager();
|
||||
if(!isArticulationLink())
|
||||
{
|
||||
mNodeIndex = simpleIslandManager->addNode(isAwake, isKine, IG::Node::eRIGID_BODY_TYPE, &mLLBody);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mArticulation)
|
||||
{
|
||||
const PxU32 linkIndex = mArticulation->findBodyIndex(*this);
|
||||
const PxNodeIndex index = mArticulation->getIslandNodeIndex();
|
||||
mNodeIndex.setIndices(index.index(), linkIndex);
|
||||
}
|
||||
}
|
||||
|
||||
PX_ASSERT(mActiveListIndex == SC_NOT_IN_SCENE_INDEX);
|
||||
|
||||
// A.B. need to set the compound rigid flag early enough, so that we add the rigid into
|
||||
// active list and do not create the shape bounds
|
||||
if(compound)
|
||||
raiseInternalFlag(BF_IS_COMPOUND_RIGID);
|
||||
|
||||
setActive(isAwake, true);
|
||||
|
||||
if(isAwake)
|
||||
{
|
||||
scene.addToActiveList(*this);
|
||||
PX_ASSERT(isActive());
|
||||
}
|
||||
else
|
||||
{
|
||||
mActiveListIndex = SC_NOT_IN_ACTIVE_LIST_INDEX;
|
||||
mActiveCompoundListIndex = SC_NOT_IN_ACTIVE_LIST_INDEX;
|
||||
PX_ASSERT(!isActive());
|
||||
|
||||
simpleIslandManager->deactivateNode(mNodeIndex);
|
||||
}
|
||||
|
||||
if(isKine)
|
||||
{
|
||||
initKinematicStateBase(core, true);
|
||||
setupSimStateData(true);
|
||||
notifyPutToSleep(); // sleep state of kinematics is fully controlled by the simulation controller not the island manager
|
||||
|
||||
mFilterFlags |= PxFilterObjectFlag::eKINEMATIC;
|
||||
}
|
||||
}
|
||||
|
||||
BodySim::~BodySim()
|
||||
{
|
||||
Scene& scene = mScene;
|
||||
const bool active = isActive();
|
||||
|
||||
tearDownSimStateData(isKinematic());
|
||||
PX_ASSERT(!mSimStateData);
|
||||
|
||||
// PX-4603. AD: assuming that the articulation code cleans up the dirty state in case this is an articulation link.
|
||||
if (!isArticulationLink())
|
||||
mScene.getVelocityModifyMap().boundedReset(mNodeIndex.index());
|
||||
|
||||
PX_ASSERT(!readInternalFlag(BF_ON_DEATHROW)); // Before 3.0 it could happen that destroy could get called twice. Assert to make sure this is fixed.
|
||||
raiseInternalFlag(BF_ON_DEATHROW);
|
||||
|
||||
scene.removeBody(*this);
|
||||
|
||||
//Articulations are represented by a single node, so they must only be removed by the articulation and not the links!
|
||||
if(mArticulation == NULL && mNodeIndex.articulationLinkId() == 0) //If it wasn't an articulation link, then we can remove it
|
||||
scene.getSimpleIslandManager()->removeNode(mNodeIndex);
|
||||
|
||||
PX_ASSERT(mActiveListIndex != SC_NOT_IN_SCENE_INDEX);
|
||||
|
||||
if (active)
|
||||
scene.removeFromActiveList(*this);
|
||||
|
||||
mActiveListIndex = SC_NOT_IN_SCENE_INDEX;
|
||||
mActiveCompoundListIndex = SC_NOT_IN_SCENE_INDEX;
|
||||
|
||||
mCore.setSim(NULL);
|
||||
}
|
||||
|
||||
void BodySim::updateCached(PxBitMapPinned* shapeChangedMap)
|
||||
{
|
||||
if(!(mLLBody.mInternalFlags & PxsRigidBody::eFROZEN))
|
||||
{
|
||||
PxU32 nbElems = getNbElements();
|
||||
ElementSim** elems = getElements();
|
||||
while (nbElems--)
|
||||
{
|
||||
ShapeSim* current = static_cast<ShapeSim*>(*elems++);
|
||||
current->updateCached(0, shapeChangedMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BodySim::updateCached(PxsTransformCache& transformCache, Bp::BoundsArray& boundsArray)
|
||||
{
|
||||
PX_ASSERT(!(mLLBody.mInternalFlags & PxsRigidBody::eFROZEN)); // PT: should not be called otherwise
|
||||
|
||||
PxU32 nbElems = getNbElements();
|
||||
ElementSim** elems = getElements();
|
||||
while (nbElems--)
|
||||
{
|
||||
ShapeSim* current = static_cast<ShapeSim*>(*elems++);
|
||||
current->updateCached(transformCache, boundsArray);
|
||||
}
|
||||
}
|
||||
|
||||
bool BodySim::setupSimStateData(bool isKinematic)
|
||||
{
|
||||
SimStateData* data = mSimStateData;
|
||||
if(!data)
|
||||
{
|
||||
data = mScene.getSimStateDataPool()->construct();
|
||||
if(!data)
|
||||
return false;
|
||||
}
|
||||
|
||||
if(isKinematic)
|
||||
{
|
||||
PX_ASSERT(!mSimStateData || !mSimStateData->isKine());
|
||||
|
||||
PX_PLACEMENT_NEW(data, SimStateData(SimStateData::eKine));
|
||||
Kinematic* kine = data->getKinematicData();
|
||||
kine->targetValid = 0;
|
||||
simStateBackupAndClearBodyProperties(data, getBodyCore().getCore());
|
||||
}
|
||||
else
|
||||
{
|
||||
PX_ASSERT(!mSimStateData || !mSimStateData->isVelMod());
|
||||
|
||||
PX_PLACEMENT_NEW(data, SimStateData(SimStateData::eVelMod));
|
||||
VelocityMod* velmod = data->getVelocityModData();
|
||||
velmod->clear();
|
||||
}
|
||||
mSimStateData = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
void BodySim::tearDownSimStateData(bool isKinematic)
|
||||
{
|
||||
PX_ASSERT(!mSimStateData || mSimStateData->isKine() == isKinematic);
|
||||
|
||||
if (mSimStateData)
|
||||
{
|
||||
if (isKinematic)
|
||||
simStateRestoreBodyProperties(mSimStateData, getBodyCore().getCore());
|
||||
|
||||
mScene.getSimStateDataPool()->destroy(mSimStateData);
|
||||
mSimStateData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void BodySim::switchToKinematic()
|
||||
{
|
||||
setupSimStateData(true);
|
||||
|
||||
{
|
||||
initKinematicStateBase(getBodyCore(), false);
|
||||
|
||||
// - interactions need to get refiltered to make sure that kinematic-kinematic and kinematic-static pairs get suppressed
|
||||
// - unlike postSwitchToDynamic(), constraint interactions are not marked dirty here because a transition to kinematic will put the object asleep which in turn
|
||||
// triggers onDeactivate() on the constraint pairs that are active. If such pairs get deactivated, they will get removed from the list of active breakable
|
||||
// constraints automatically.
|
||||
setActorsInteractionsDirty(InteractionDirtyFlag::eBODY_KINEMATIC, NULL, InteractionFlag::eFILTERABLE);
|
||||
|
||||
mScene.getSimpleIslandManager()->setKinematic(mNodeIndex);
|
||||
|
||||
updateBPGroup(this);
|
||||
}
|
||||
|
||||
mScene.setDynamicsDirty();
|
||||
|
||||
mFilterFlags |= PxFilterObjectFlag::eKINEMATIC;
|
||||
}
|
||||
|
||||
void BodySim::switchToDynamic()
|
||||
{
|
||||
tearDownSimStateData(true);
|
||||
|
||||
{
|
||||
mScene.getSimpleIslandManager()->setDynamic(mNodeIndex);
|
||||
|
||||
setForcesToDefaults(true);
|
||||
|
||||
// - interactions need to get refiltered to make sure that former kinematic-kinematic and kinematic-static pairs get enabled
|
||||
// - switching from kinematic to dynamic does not change the sleep state of the body. The constraint interactions are marked dirty
|
||||
// to check later whether they need to be activated plus potentially tracked for constraint break testing. This special treatment
|
||||
// is necessary because constraints between two kinematic bodies are considered inactive, no matter whether one of the kinematics
|
||||
// is active (has a target) or not.
|
||||
setActorsInteractionsDirty(InteractionDirtyFlag::eBODY_KINEMATIC, NULL, InteractionFlag::eFILTERABLE | InteractionFlag::eCONSTRAINT);
|
||||
|
||||
clearInternalFlag(BF_KINEMATIC_MOVE_FLAGS);
|
||||
|
||||
if(isActive())
|
||||
mScene.swapInActiveBodyList(*this);
|
||||
|
||||
//
|
||||
updateBPGroup(this);
|
||||
}
|
||||
|
||||
mScene.setDynamicsDirty();
|
||||
|
||||
mFilterFlags &= ~PxFilterObjectFlag::eKINEMATIC;
|
||||
}
|
||||
|
||||
void BodySim::setKinematicTarget(const PxTransform& p)
|
||||
{
|
||||
PX_ASSERT(getSimStateData(true));
|
||||
PX_ASSERT(getSimStateData(true)->isKine());
|
||||
simStateSetKinematicTarget(getSimStateData_Unchecked(), p);
|
||||
PX_ASSERT(getSimStateData(true)->getKinematicData()->targetValid);
|
||||
|
||||
raiseInternalFlag(BF_KINEMATIC_MOVED); // Important to set this here already because trigger interactions need to have this information when being activated.
|
||||
clearInternalFlag(BF_KINEMATIC_SURFACE_VELOCITY);
|
||||
}
|
||||
|
||||
void BodySim::addSpatialAcceleration(const PxVec3* linAcc, const PxVec3* angAcc)
|
||||
{
|
||||
notifyDirtySpatialAcceleration();
|
||||
|
||||
if (!mSimStateData || !mSimStateData->isVelMod())
|
||||
setupSimStateData(false);
|
||||
|
||||
VelocityMod* velmod = mSimStateData->getVelocityModData();
|
||||
if (linAcc)
|
||||
velmod->accumulateLinearVelModPerSec(*linAcc);
|
||||
if (angAcc)
|
||||
velmod->accumulateAngularVelModPerSec(*angAcc);
|
||||
}
|
||||
|
||||
void BodySim::setSpatialAcceleration(const PxVec3* linAcc, const PxVec3* angAcc)
|
||||
{
|
||||
notifyDirtySpatialAcceleration();
|
||||
|
||||
if (!mSimStateData || !mSimStateData->isVelMod())
|
||||
setupSimStateData(false);
|
||||
|
||||
VelocityMod* velmod = mSimStateData->getVelocityModData();
|
||||
if (linAcc)
|
||||
velmod->setLinearVelModPerSec(*linAcc);
|
||||
if (angAcc)
|
||||
velmod->setAngularVelModPerSec(*angAcc);
|
||||
}
|
||||
|
||||
void BodySim::clearSpatialAcceleration(bool force, bool torque)
|
||||
{
|
||||
PX_ASSERT(force || torque);
|
||||
|
||||
notifyDirtySpatialAcceleration();
|
||||
|
||||
if (mSimStateData)
|
||||
{
|
||||
PX_ASSERT(mSimStateData->isVelMod());
|
||||
VelocityMod* velmod = mSimStateData->getVelocityModData();
|
||||
if (force)
|
||||
velmod->clearLinearVelModPerSec();
|
||||
if (torque)
|
||||
velmod->clearAngularVelModPerSec();
|
||||
}
|
||||
}
|
||||
|
||||
void BodySim::addSpatialVelocity(const PxVec3* linVelDelta, const PxVec3* angVelDelta)
|
||||
{
|
||||
notifyDirtySpatialVelocity();
|
||||
|
||||
if (!mSimStateData || !mSimStateData->isVelMod())
|
||||
setupSimStateData(false);
|
||||
|
||||
VelocityMod* velmod = mSimStateData->getVelocityModData();
|
||||
if (linVelDelta)
|
||||
velmod->accumulateLinearVelModPerStep(*linVelDelta);
|
||||
if (angVelDelta)
|
||||
velmod->accumulateAngularVelModPerStep(*angVelDelta);
|
||||
}
|
||||
|
||||
void BodySim::clearSpatialVelocity(bool force, bool torque)
|
||||
{
|
||||
PX_ASSERT(force || torque);
|
||||
|
||||
notifyDirtySpatialVelocity();
|
||||
|
||||
if (mSimStateData)
|
||||
{
|
||||
PX_ASSERT(mSimStateData->isVelMod());
|
||||
VelocityMod* velmod = mSimStateData->getVelocityModData();
|
||||
if (force)
|
||||
velmod->clearLinearVelModPerStep();
|
||||
if (torque)
|
||||
velmod->clearAngularVelModPerStep();
|
||||
}
|
||||
}
|
||||
|
||||
void BodySim::raiseVelocityModFlagAndNotify(VelocityModFlags flag)
|
||||
{
|
||||
//The dirty flag is stored separately in the BodySim so that we query the dirty flag before going to
|
||||
//the expense of querying the simStateData for the velmod values.
|
||||
raiseVelocityModFlag(flag);
|
||||
|
||||
if (!isArticulationLink())
|
||||
mScene.getVelocityModifyMap().growAndSet(getNodeIndex().index());
|
||||
else
|
||||
mScene.addDirtyArticulationSim(getArticulation());
|
||||
}
|
||||
|
||||
void BodySim::postActorFlagChange(PxU32 oldFlags, PxU32 newFlags)
|
||||
{
|
||||
// PT: don't convert to bool if not needed
|
||||
const PxU32 wasWeightless = oldFlags & PxActorFlag::eDISABLE_GRAVITY;
|
||||
const PxU32 isWeightless = newFlags & PxActorFlag::eDISABLE_GRAVITY;
|
||||
|
||||
if (isWeightless != wasWeightless)
|
||||
{
|
||||
if (mVelModState == 0)
|
||||
raiseVelocityModFlag(VMF_GRAVITY_DIRTY);
|
||||
|
||||
getBodyCore().getCore().disableGravity = isWeightless!=0;
|
||||
|
||||
if(mArticulation)
|
||||
mArticulation->setArticulationDirty(ArticulationDirtyFlag::eDIRTY_LINKS); // forces an update in PxgSimulationController::updateGpuArticulationSim
|
||||
}
|
||||
}
|
||||
|
||||
void BodySim::postBody2WorldChange()
|
||||
{
|
||||
mLLBody.saveLastCCDTransform();
|
||||
notifyShapesOfTransformChange();
|
||||
}
|
||||
|
||||
void BodySim::postSetWakeCounter(PxReal t, bool forceWakeUp)
|
||||
{
|
||||
if ((t > 0.0f) || forceWakeUp)
|
||||
notifyNotReadyForSleeping();
|
||||
else
|
||||
{
|
||||
const bool readyForSleep = checkSleepReadinessBesidesWakeCounter();
|
||||
if (readyForSleep)
|
||||
notifyReadyForSleeping();
|
||||
}
|
||||
}
|
||||
|
||||
void BodySim::postPosePreviewChange(PxU32 posePreviewFlag)
|
||||
{
|
||||
if (isActive())
|
||||
{
|
||||
if (posePreviewFlag & PxRigidBodyFlag::eENABLE_POSE_INTEGRATION_PREVIEW)
|
||||
mScene.addToPosePreviewList(*this);
|
||||
else
|
||||
mScene.removeFromPosePreviewList(*this);
|
||||
}
|
||||
else
|
||||
PX_ASSERT(!mScene.isInPosePreviewList(*this));
|
||||
}
|
||||
|
||||
void BodySim::activate()
|
||||
{
|
||||
BodyCore& core = getBodyCore();
|
||||
|
||||
// Activate body
|
||||
{
|
||||
PX_ASSERT((!isKinematic()) || notInScene() || readInternalFlag(InternalFlags(BF_KINEMATIC_MOVED | BF_KINEMATIC_SURFACE_VELOCITY))); // kinematics should only get activated when a target is set.
|
||||
// exception: object gets newly added, then the state change will happen later
|
||||
if(!isArticulationLink())
|
||||
{
|
||||
mLLBody.mInternalFlags &= (~PxsRigidBody::eFROZEN);
|
||||
// Put in list of activated bodies. The list gets cleared at the end of a sim step after the sleep callbacks have been fired.
|
||||
mScene.onBodyWakeUp(this);
|
||||
}
|
||||
|
||||
if(core.getFlags() & PxRigidBodyFlag::eENABLE_POSE_INTEGRATION_PREVIEW)
|
||||
{
|
||||
PX_ASSERT(!mScene.isInPosePreviewList(*this));
|
||||
mScene.addToPosePreviewList(*this);
|
||||
}
|
||||
createSqBounds();
|
||||
}
|
||||
|
||||
activateInteractions(*this);
|
||||
|
||||
//set speculative CCD bit map if speculative CCD flag is on
|
||||
if(core.getFlags() & PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD)
|
||||
addToSpeculativeCCDMap();
|
||||
}
|
||||
|
||||
void BodySim::deactivate()
|
||||
{
|
||||
deactivateInteractions(*this);
|
||||
|
||||
BodyCore& core = getBodyCore();
|
||||
|
||||
// Deactivate body
|
||||
{
|
||||
PX_ASSERT((!isKinematic()) || notInScene() || !readInternalFlag(BF_KINEMATIC_MOVED)); // kinematics should only get deactivated when no target is set.
|
||||
// exception: object gets newly added, then the state change will happen later
|
||||
if(!readInternalFlag(BF_ON_DEATHROW))
|
||||
{
|
||||
// Set velocity to 0.
|
||||
// Note: this is also fine if the method gets called because the user puts something to sleep (this behavior is documented in the API)
|
||||
PX_ASSERT(core.getWakeCounter() == 0.0f);
|
||||
const PxVec3 zero(0.0f);
|
||||
core.setLinearVelocityInternal(zero);
|
||||
core.setAngularVelocityInternal(zero);
|
||||
|
||||
setForcesToDefaults(!core.getCore().disableGravity);
|
||||
}
|
||||
|
||||
if(!isArticulationLink()) // Articulations have their own sleep logic.
|
||||
mScene.onBodySleep(this);
|
||||
|
||||
if(core.getFlags() & PxRigidBodyFlag::eENABLE_POSE_INTEGRATION_PREVIEW)
|
||||
{
|
||||
PX_ASSERT(mScene.isInPosePreviewList(*this));
|
||||
mScene.removeFromPosePreviewList(*this);
|
||||
}
|
||||
destroySqBounds();
|
||||
}
|
||||
|
||||
// reset speculative CCD bit map if speculative CCD flag is on
|
||||
if(core.getFlags() & PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD)
|
||||
removeFromSpeculativeCCDMap();
|
||||
}
|
||||
|
||||
void BodySim::wakeUp()
|
||||
{
|
||||
setActive(true);
|
||||
notifyWakeUp();
|
||||
}
|
||||
|
||||
void BodySim::putToSleep()
|
||||
{
|
||||
PX_ASSERT(getBodyCore().getWakeCounter() == 0.0f);
|
||||
PX_ASSERT(getBodyCore().getLinearVelocity().isZero());
|
||||
PX_ASSERT(getBodyCore().getAngularVelocity().isZero());
|
||||
|
||||
notifyDirtySpatialAcceleration();
|
||||
notifyDirtySpatialVelocity();
|
||||
simStateClearVelMod(getSimStateData_Unchecked());
|
||||
|
||||
setActive(false);
|
||||
notifyPutToSleep();
|
||||
}
|
||||
|
||||
void BodySim::internalWakeUp(PxReal wakeCounterValue)
|
||||
{
|
||||
if(mArticulation)
|
||||
mArticulation->internalWakeUp(wakeCounterValue);
|
||||
else
|
||||
internalWakeUpBase(wakeCounterValue);
|
||||
}
|
||||
|
||||
void BodySim::internalWakeUpArticulationLink(PxReal wakeCounterValue)
|
||||
{
|
||||
PX_ASSERT(mArticulation);
|
||||
internalWakeUpBase(wakeCounterValue);
|
||||
}
|
||||
|
||||
void BodySim::internalWakeUpBase(PxReal wakeCounterValue) //this one can only increase the wake counter, not decrease it, so it can't be used to put things to sleep!
|
||||
{
|
||||
if ((!isKinematic()) && (getBodyCore().getWakeCounter() < wakeCounterValue))
|
||||
{
|
||||
PX_ASSERT(wakeCounterValue > 0.0f);
|
||||
getBodyCore().setWakeCounterFromSim(wakeCounterValue);
|
||||
|
||||
//we need to update the gpu body sim because we reset the wake counter for the body core
|
||||
mScene.updateBodySim(*this);
|
||||
setActive(true);
|
||||
notifyWakeUp();
|
||||
|
||||
if(0) // PT: commented-out for PX-2197
|
||||
mLLBody.mInternalFlags &= (~PxsRigidBody::eFROZEN);
|
||||
}
|
||||
}
|
||||
|
||||
void BodySim::notifyReadyForSleeping()
|
||||
{
|
||||
if(mArticulation == NULL)
|
||||
mScene.getSimpleIslandManager()->deactivateNode(mNodeIndex);
|
||||
}
|
||||
|
||||
void BodySim::notifyNotReadyForSleeping()
|
||||
{
|
||||
mScene.getSimpleIslandManager()->activateNode(mNodeIndex);
|
||||
}
|
||||
|
||||
void BodySim::notifyWakeUp()
|
||||
{
|
||||
mScene.getSimpleIslandManager()->activateNode(mNodeIndex);
|
||||
}
|
||||
|
||||
void BodySim::notifyPutToSleep()
|
||||
{
|
||||
mScene.getSimpleIslandManager()->putNodeToSleep(mNodeIndex);
|
||||
}
|
||||
|
||||
//This function will be called by CPU sleepCheck code
|
||||
// PT: TODO: actually this seems to be only called by the articulation sim code, while regular rigid bodies use a copy of that code in LowLevelDynamics?
|
||||
PxReal BodySim::updateWakeCounter(PxReal dt, PxReal energyThreshold, const Cm::SpatialVector& motionVelocity)
|
||||
{
|
||||
// update the body's sleep state and
|
||||
BodyCore& core = getBodyCore();
|
||||
|
||||
const PxReal wakeCounterResetTime = ScInternalWakeCounterResetValue;
|
||||
|
||||
PxReal wc = core.getWakeCounter();
|
||||
|
||||
{
|
||||
PxVec3 bcSleepLinVelAcc = mLLBody.mSleepLinVelAcc;
|
||||
PxVec3 bcSleepAngVelAcc = mLLBody.mSleepAngVelAcc;
|
||||
|
||||
if(wc < wakeCounterResetTime * 0.5f || wc < dt)
|
||||
{
|
||||
const PxTransform& body2World = getBody2World();
|
||||
|
||||
// calculate normalized energy: kinetic energy divided by mass
|
||||
const PxVec3 t = core.getInverseInertia();
|
||||
const PxVec3 inertia(t.x > 0.0f ? 1.0f/t.x : 1.0f, t.y > 0.0f ? 1.0f/t.y : 1.0f, t.z > 0.0f ? 1.0f/t.z : 1.0f);
|
||||
|
||||
PxVec3 sleepLinVelAcc = motionVelocity.linear;
|
||||
PxVec3 sleepAngVelAcc = body2World.q.rotateInv(motionVelocity.angular);
|
||||
|
||||
bcSleepLinVelAcc += sleepLinVelAcc;
|
||||
bcSleepAngVelAcc += sleepAngVelAcc;
|
||||
|
||||
PxReal invMass = core.getInverseMass();
|
||||
if(invMass == 0.0f)
|
||||
invMass = 1.0f;
|
||||
|
||||
const PxReal angular = bcSleepAngVelAcc.multiply(bcSleepAngVelAcc).dot(inertia) * invMass;
|
||||
const PxReal linear = bcSleepLinVelAcc.magnitudeSquared();
|
||||
const PxReal normalizedEnergy = 0.5f * (angular + linear);
|
||||
|
||||
// scale threshold by cluster factor (more contacts => higher sleep threshold)
|
||||
const PxReal clusterFactor = PxReal(1 + getNumCountedInteractions());
|
||||
const PxReal threshold = clusterFactor*energyThreshold;
|
||||
|
||||
if (normalizedEnergy >= threshold)
|
||||
{
|
||||
PX_ASSERT(isActive());
|
||||
mLLBody.resetSleepFilter();
|
||||
const float factor = threshold == 0.0f ? 2.0f : PxMin(normalizedEnergy/threshold, 2.0f);
|
||||
PxReal oldWc = wc;
|
||||
wc = factor * 0.5f * wakeCounterResetTime + dt * (clusterFactor - 1.0f);
|
||||
core.setWakeCounterFromSim(wc);
|
||||
if (oldWc == 0.0f) // for the case where a sleeping body got activated by the system (not the user) AND got processed by the solver as well
|
||||
notifyNotReadyForSleeping();
|
||||
|
||||
return wc;
|
||||
}
|
||||
}
|
||||
|
||||
mLLBody.mSleepLinVelAcc = bcSleepLinVelAcc;
|
||||
mLLBody.mSleepAngVelAcc = bcSleepAngVelAcc;
|
||||
}
|
||||
|
||||
wc = PxMax(wc-dt, 0.0f);
|
||||
core.setWakeCounterFromSim(wc);
|
||||
return wc;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void BodySim::initKinematicStateBase(BodyCore&, bool asPartOfCreation)
|
||||
{
|
||||
PX_ASSERT(!readInternalFlag(BF_KINEMATIC_MOVED));
|
||||
|
||||
if (!asPartOfCreation && isActive())
|
||||
mScene.swapInActiveBodyList(*this);
|
||||
|
||||
//mLLBody.setAccelerationV(Cm::SpatialVector::zero());
|
||||
|
||||
// Need to be before setting setRigidBodyFlag::KINEMATIC
|
||||
}
|
||||
|
||||
bool BodySim::updateForces(PxReal dt, PxsRigidBody** updatedBodySims, PxU32* updatedBodyNodeIndices, PxU32& index, Cm::SpatialVector* acceleration,
|
||||
PxsExternalAccelerationProvider* externalAccelerations, PxU32 maxNumExternalAccelerations)
|
||||
{
|
||||
PxVec3 linVelDt(0.0f), angVelDt(0.0f);
|
||||
|
||||
const bool accDirty = readVelocityModFlag(VMF_ACC_DIRTY);
|
||||
const bool velDirty = readVelocityModFlag(VMF_VEL_DIRTY);
|
||||
|
||||
SimStateData* simStateData = NULL;
|
||||
|
||||
bool forceChangeApplied = false;
|
||||
|
||||
//if we change the logic like this, which means we don't need to have two separate variables in the pxgbodysim to represent linAcc and angAcc. However, this
|
||||
//means angAcc will be always 0
|
||||
if( (accDirty || velDirty) && ((simStateData = getSimStateData(false)) != NULL) )
|
||||
{
|
||||
VelocityMod* velmod = simStateData->getVelocityModData();
|
||||
|
||||
//we don't have support for articulation yet
|
||||
if (updatedBodySims)
|
||||
{
|
||||
updatedBodySims[index] = &getLowLevelBody();
|
||||
updatedBodyNodeIndices[index++] = getNodeIndex().index();
|
||||
}
|
||||
|
||||
if(velDirty)
|
||||
{
|
||||
linVelDt = velmod->getLinearVelModPerStep();
|
||||
angVelDt = velmod->getAngularVelModPerStep();
|
||||
}
|
||||
|
||||
if (accDirty)
|
||||
{
|
||||
linVelDt += velmod->getLinearVelModPerSec()*dt;
|
||||
angVelDt += velmod->getAngularVelModPerSec()*dt;
|
||||
}
|
||||
|
||||
if (acceleration)
|
||||
{
|
||||
const PxReal invDt = 1.f / dt;
|
||||
acceleration->linear = linVelDt * invDt;
|
||||
acceleration->angular = angVelDt * invDt;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mScene.getFlags() & PxSceneFlag::eENABLE_EXTERNAL_FORCES_EVERY_ITERATION_TGS)
|
||||
{
|
||||
if (linVelDt != PxVec3(0.0f) || angVelDt != PxVec3(0.0f))
|
||||
{
|
||||
const PxReal invDt = 1.f / dt;
|
||||
PxsRigidBodyExternalAcceleration acc(linVelDt * invDt, angVelDt * invDt);
|
||||
externalAccelerations->setValue(acc, getNodeIndex().index(), maxNumExternalAccelerations);
|
||||
}
|
||||
}
|
||||
else
|
||||
getBodyCore().updateVelocities(linVelDt, angVelDt);
|
||||
}
|
||||
|
||||
forceChangeApplied = true;
|
||||
}
|
||||
|
||||
setForcesToDefaults(readVelocityModFlag(VMF_ACC_DIRTY));
|
||||
|
||||
return forceChangeApplied;
|
||||
}
|
||||
|
||||
void BodySim::onConstraintDetach()
|
||||
{
|
||||
PX_ASSERT(readInternalFlag(BF_HAS_CONSTRAINTS));
|
||||
|
||||
PxU32 size = getActorInteractionCount();
|
||||
Interaction** interactions = getActorInteractions();
|
||||
unregisterCountedInteraction();
|
||||
|
||||
while(size--)
|
||||
{
|
||||
const Interaction* interaction = *interactions++;
|
||||
if(interaction->getType() == InteractionType::eCONSTRAINTSHADER)
|
||||
return;
|
||||
}
|
||||
|
||||
clearInternalFlag(BF_HAS_CONSTRAINTS); // There are no other constraint interactions left
|
||||
}
|
||||
|
||||
void BodySim::setArticulation(ArticulationSim* a, PxReal wakeCounter, bool asleep, PxU32 bodyIndex)
|
||||
{
|
||||
mArticulation = a;
|
||||
if(a)
|
||||
{
|
||||
PxNodeIndex index = mArticulation->getIslandNodeIndex();
|
||||
mNodeIndex.setIndices(index.index(), bodyIndex);
|
||||
getBodyCore().setWakeCounterFromSim(wakeCounter);
|
||||
|
||||
if (getFlagsFast() & PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD)
|
||||
mScene.setSpeculativeCCDArticulationLink(mNodeIndex.index());
|
||||
|
||||
//Articulations defer registering their shapes with the nphaseContext until the IG node index is known.
|
||||
{
|
||||
// PT: TODO: skip this on CPU
|
||||
PxvNphaseImplementationContext* ctx = mScene.getLowLevelContext()->getNphaseImplementationContext();
|
||||
ElementSim** current = getElements();
|
||||
PxU32 nbElements = getNbElements();
|
||||
while (nbElements--)
|
||||
{
|
||||
ShapeSim* sim = static_cast<ShapeSim*>(*current++);
|
||||
ctx->registerShape(mNodeIndex, sim->getCore().getCore(), sim->getElementID(), sim->getActor().getPxActor());
|
||||
}
|
||||
}
|
||||
|
||||
//Force node index into LL shapes
|
||||
{
|
||||
PxsSimulationController* sc = getScene().getSimulationController();
|
||||
if(sc->mGPU)
|
||||
{
|
||||
const PxNodeIndex nodeIndex = mNodeIndex;
|
||||
PxU32 nbElems = getNbElements();
|
||||
ElementSim** elems = getElements();
|
||||
while (nbElems--)
|
||||
{
|
||||
ShapeSim* sim = static_cast<ShapeSim*>(*elems++);
|
||||
sc->setPxgShapeBodyNodeIndex(nodeIndex, sim->getElementID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (a->getCore().getArticulationFlags() & PxArticulationFlag::eDISABLE_SELF_COLLISION)
|
||||
{
|
||||
//We need to reset the group IDs for all shapes in this body...
|
||||
ElementSim** current = getElements();
|
||||
PxU32 nbElements = getNbElements();
|
||||
|
||||
Bp::AABBManagerBase* aabbMgr = mScene.getAABBManager();
|
||||
|
||||
Bp::FilterGroup::Enum rootGroup = Bp::getFilterGroup(false, a->getRootActorIndex(), false);
|
||||
|
||||
while (nbElements--)
|
||||
{
|
||||
ShapeSim* sim = static_cast<ShapeSim*>(*current++);
|
||||
aabbMgr->setBPGroup(sim->getElementID(), rootGroup);
|
||||
}
|
||||
}
|
||||
|
||||
if (!asleep)
|
||||
{
|
||||
setActive(true);
|
||||
notifyWakeUp();
|
||||
}
|
||||
else
|
||||
{
|
||||
notifyReadyForSleeping();
|
||||
notifyPutToSleep();
|
||||
setActive(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Setting a 1 in the articulation ID to avoid returning the node Index to the node index
|
||||
//manager
|
||||
mNodeIndex.setIndices(PX_INVALID_NODE, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void BodySim::createSqBounds()
|
||||
{
|
||||
if(!isActive() || usingSqKinematicTarget() || readInternalFlag(BF_IS_COMPOUND_RIGID))
|
||||
return;
|
||||
|
||||
PX_ASSERT(!isFrozen());
|
||||
|
||||
PxU32 nbElems = getNbElements();
|
||||
ElementSim** elems = getElements();
|
||||
while (nbElems--)
|
||||
{
|
||||
ShapeSim* current = static_cast<ShapeSim*>(*elems++);
|
||||
current->createSqBounds();
|
||||
}
|
||||
}
|
||||
|
||||
void BodySim::destroySqBounds()
|
||||
{
|
||||
PxU32 nbElems = getNbElements();
|
||||
ElementSim** elems = getElements();
|
||||
while (nbElems--)
|
||||
{
|
||||
ShapeSim* current = static_cast<ShapeSim*>(*elems++);
|
||||
current->destroySqBounds();
|
||||
}
|
||||
}
|
||||
|
||||
void BodySim::freezeTransforms(PxBitMapPinned* shapeChangedMap)
|
||||
{
|
||||
PxU32 nbElems = getNbElements();
|
||||
ElementSim** elems = getElements();
|
||||
while (nbElems--)
|
||||
{
|
||||
ShapeSim* sim = static_cast<ShapeSim*>(*elems++);
|
||||
sim->updateCached(PxsTransformFlag::eFROZEN, shapeChangedMap);
|
||||
sim->destroySqBounds();
|
||||
}
|
||||
}
|
||||
|
||||
void BodySim::disableCompound()
|
||||
{
|
||||
if(isActive())
|
||||
mScene.removeFromActiveCompoundBodyList(*this);
|
||||
clearInternalFlag(BF_IS_COMPOUND_RIGID);
|
||||
}
|
||||
|
||||
275
engine/third_party/physx/source/simulationcontroller/src/ScBodySim.h
vendored
Normal file
275
engine/third_party/physx/source/simulationcontroller/src/ScBodySim.h
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_BODYSIM_H
|
||||
#define SC_BODYSIM_H
|
||||
|
||||
#include "foundation/PxUtilities.h"
|
||||
#include "foundation/PxIntrinsics.h"
|
||||
#include "ScRigidSim.h"
|
||||
#include "PxvDynamics.h"
|
||||
#include "ScBodyCore.h"
|
||||
#include "ScSimStateData.h"
|
||||
#include "PxRigidDynamic.h"
|
||||
#include "PxsRigidBody.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Bp
|
||||
{
|
||||
class BoundsArray;
|
||||
}
|
||||
struct PxsExternalAccelerationProvider;
|
||||
class PxsTransformCache;
|
||||
namespace Sc
|
||||
{
|
||||
class Scene;
|
||||
class ArticulationSim;
|
||||
|
||||
#if PX_VC
|
||||
#pragma warning(push)
|
||||
#pragma warning( disable : 4324 ) // Padding was added at the end of a structure because of a __declspec(align) value.
|
||||
#endif
|
||||
|
||||
class BodySim : public RigidSim
|
||||
{
|
||||
public:
|
||||
BodySim(Scene&, BodyCore&, bool);
|
||||
virtual ~BodySim();
|
||||
|
||||
void switchToKinematic();
|
||||
void switchToDynamic();
|
||||
|
||||
PX_FORCE_INLINE const SimStateData* getSimStateData(bool isKinematic) const { return (mSimStateData && (checkSimStateKinematicStatus(isKinematic)) ? mSimStateData : NULL); }
|
||||
PX_FORCE_INLINE SimStateData* getSimStateData(bool isKinematic) { return (mSimStateData && (checkSimStateKinematicStatus(isKinematic)) ? mSimStateData : NULL); }
|
||||
PX_FORCE_INLINE SimStateData* getSimStateData_Unchecked() const { return mSimStateData; }
|
||||
PX_FORCE_INLINE bool checkSimStateKinematicStatus(bool isKinematic) const
|
||||
{
|
||||
PX_ASSERT(mSimStateData);
|
||||
return mSimStateData->isKine() == isKinematic;
|
||||
}
|
||||
|
||||
void setKinematicTarget(const PxTransform& p);
|
||||
|
||||
void addSpatialAcceleration(const PxVec3* linAcc, const PxVec3* angAcc);
|
||||
void setSpatialAcceleration(const PxVec3* linAcc, const PxVec3* angAcc);
|
||||
void clearSpatialAcceleration(bool force, bool torque);
|
||||
void addSpatialVelocity(const PxVec3* linVelDelta, const PxVec3* angVelDelta);
|
||||
void clearSpatialVelocity(bool force, bool torque);
|
||||
|
||||
void updateCached(PxBitMapPinned* shapeChangedMap);
|
||||
void updateCached(PxsTransformCache& transformCache, Bp::BoundsArray& boundsArray);
|
||||
void updateContactDistance(PxReal* contactDistance, PxReal dt, const Bp::BoundsArray& boundsArray);
|
||||
|
||||
// hooks for actions in body core when it's attached to a sim object. Generally
|
||||
// we get called after the attribute changed.
|
||||
|
||||
virtual void postActorFlagChange(PxU32 oldFlags, PxU32 newFlags) PX_OVERRIDE;
|
||||
void postBody2WorldChange();
|
||||
void postSetWakeCounter(PxReal t, bool forceWakeUp);
|
||||
void postPosePreviewChange(PxU32 posePreviewFlag); // called when PxRigidBodyFlag::eENABLE_POSE_INTEGRATION_PREVIEW changes
|
||||
|
||||
PX_FORCE_INLINE const PxTransform& getBody2World() const { return getBodyCore().getCore().body2World; }
|
||||
PX_FORCE_INLINE const PxTransform& getBody2Actor() const { return getBodyCore().getCore().getBody2Actor(); }
|
||||
PX_FORCE_INLINE const PxsRigidBody& getLowLevelBody() const { return mLLBody; }
|
||||
PX_FORCE_INLINE PxsRigidBody& getLowLevelBody() { return mLLBody; }
|
||||
|
||||
void setActive(bool active, bool asPartOfCreation=false);
|
||||
void wakeUp(); // note: for user API call purposes only, i.e., use from BodyCore. For simulation internal purposes there is internalWakeUp().
|
||||
void putToSleep();
|
||||
|
||||
void disableCompound();
|
||||
|
||||
static PxU32 getRigidBodyOffset() { return PxU32(PX_OFFSET_OF_RT(BodySim, mLLBody));}
|
||||
|
||||
void activate();
|
||||
void deactivate();
|
||||
|
||||
// Kinematics
|
||||
PX_FORCE_INLINE bool isKinematic() const { return getBodyCore().getFlags() & PxRigidBodyFlag::eKINEMATIC; }
|
||||
PX_FORCE_INLINE bool isArticulationLink() const { return getActorType() == PxActorType::eARTICULATION_LINK; }
|
||||
PX_FORCE_INLINE bool hasForcedKinematicNotif() const
|
||||
{
|
||||
return getBodyCore().getFlags() & (PxRigidBodyFlag::eFORCE_KINE_KINE_NOTIFICATIONS|PxRigidBodyFlag::eFORCE_STATIC_KINE_NOTIFICATIONS);
|
||||
}
|
||||
void calculateKinematicVelocity(PxReal oneOverDt);
|
||||
void updateKinematicPose();
|
||||
bool deactivateKinematic();
|
||||
// Sleeping
|
||||
virtual void internalWakeUp(PxReal wakeCounterValue) PX_OVERRIDE; // PT: TODO: does it need to be virtual?
|
||||
void internalWakeUpArticulationLink(PxReal wakeCounterValue); // called by ArticulationSim to wake up this link
|
||||
|
||||
PxReal updateWakeCounter(PxReal dt, PxReal energyThreshold, const Cm::SpatialVector& motionVelocity);
|
||||
|
||||
void notifyReadyForSleeping(); // inform the sleep island generation system that the body is ready for sleeping
|
||||
void notifyNotReadyForSleeping(); // inform the sleep island generation system that the body is not ready for sleeping
|
||||
PX_FORCE_INLINE bool checkSleepReadinessBesidesWakeCounter(); // for API triggered changes to test sleep readiness
|
||||
|
||||
// PT: TODO: this is only used for the rigid bodies' sleep check, the implementations in derived classes look useless
|
||||
virtual void registerCountedInteraction() PX_OVERRIDE { mLLBody.getCore().numCountedInteractions++; PX_ASSERT(mLLBody.getCore().numCountedInteractions); }
|
||||
virtual void unregisterCountedInteraction() PX_OVERRIDE { PX_ASSERT(mLLBody.getCore().numCountedInteractions); mLLBody.getCore().numCountedInteractions--; }
|
||||
// PT: TODO: this is only used for the rigid bodies' sleep check called from the articulation sim code
|
||||
virtual PxU32 getNumCountedInteractions() const PX_OVERRIDE { return mLLBody.getCore().numCountedInteractions; }
|
||||
|
||||
PX_FORCE_INLINE PxIntBool isFrozen() const { return PxIntBool(mLLBody.mInternalFlags & PxsRigidBody::eFROZEN); }
|
||||
|
||||
// External velocity changes - returns true if any forces were applied to this body
|
||||
bool updateForces(PxReal dt, PxsRigidBody** updatedBodySims, PxU32* updatedBodyNodeIndices, PxU32& index, Cm::SpatialVector* acceleration,
|
||||
PxsExternalAccelerationProvider* externalAccelerations = NULL, PxU32 maxNumExternalAccelerations = 0);
|
||||
|
||||
PX_FORCE_INLINE bool readVelocityModFlag(VelocityModFlags f) { return (mVelModState & f) != 0; }
|
||||
|
||||
// Miscellaneous
|
||||
PX_FORCE_INLINE bool notInScene() const { return mActiveListIndex == SC_NOT_IN_SCENE_INDEX; }
|
||||
PX_FORCE_INLINE PxU32 getNbShapes() const { return mShapes.getCount(); }
|
||||
PX_FORCE_INLINE PxU32 getFlagsFast() const { return getBodyCore().getFlags(); }
|
||||
PX_FORCE_INLINE BodyCore& getBodyCore() const { return static_cast<BodyCore&>(getRigidCore()); }
|
||||
|
||||
PX_FORCE_INLINE ArticulationSim* getArticulation() const { return mArticulation; }
|
||||
void setArticulation(ArticulationSim* a, PxReal wakeCounter, bool asleep, PxU32 bodyIndex);
|
||||
|
||||
PX_FORCE_INLINE void onConstraintAttach() { raiseInternalFlag(BF_HAS_CONSTRAINTS); registerCountedInteraction(); }
|
||||
void onConstraintDetach();
|
||||
|
||||
PX_FORCE_INLINE void onOriginShift(const PxVec3& shift, const bool isKinematic)
|
||||
{
|
||||
PX_ASSERT(!mSimStateData || checkSimStateKinematicStatus(isKinematic));
|
||||
mLLBody.mLastTransform.p -= shift;
|
||||
if (mSimStateData && isKinematic && mSimStateData->getKinematicData()->targetValid)
|
||||
mSimStateData->getKinematicData()->targetPose.p -= shift;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE bool usingSqKinematicTarget() const
|
||||
{
|
||||
const PxU32 ktFlags(PxRigidBodyFlag::eUSE_KINEMATIC_TARGET_FOR_SCENE_QUERIES | PxRigidBodyFlag::eKINEMATIC);
|
||||
return (getFlagsFast()&ktFlags) == ktFlags;
|
||||
}
|
||||
|
||||
void createSqBounds();
|
||||
void destroySqBounds();
|
||||
void freezeTransforms(PxBitMapPinned* shapeChangedMap);
|
||||
|
||||
void addToSpeculativeCCDMap();
|
||||
void removeFromSpeculativeCCDMap();
|
||||
private:
|
||||
// Base body
|
||||
PxsRigidBody mLLBody;
|
||||
|
||||
// External velocity changes
|
||||
// VelocityMod data allocated on the fly when the user applies velocity changes
|
||||
// which need to be accumulated.
|
||||
// VelMod dirty flags stored in BodySim so we can save ourselves the expense of looking at
|
||||
// the separate velmod data if no forces have been set.
|
||||
//PxU16 mInternalFlags;
|
||||
SimStateData* mSimStateData;
|
||||
PxU8 mVelModState;
|
||||
|
||||
// Articulation
|
||||
ArticulationSim* mArticulation; // NULL if not in an articulation
|
||||
|
||||
// Joints & joint groups
|
||||
|
||||
bool setupSimStateData(bool isKinematic);
|
||||
void tearDownSimStateData(bool isKinematic);
|
||||
|
||||
void raiseVelocityModFlagAndNotify(VelocityModFlags flag);
|
||||
PX_FORCE_INLINE void notifyDirtySpatialAcceleration() { raiseVelocityModFlagAndNotify(VMF_ACC_DIRTY); }
|
||||
PX_FORCE_INLINE void notifyDirtySpatialVelocity() { raiseVelocityModFlagAndNotify(VMF_VEL_DIRTY); }
|
||||
|
||||
PX_FORCE_INLINE void initKinematicStateBase(BodyCore&, bool asPartOfCreation);
|
||||
|
||||
void notifyWakeUp(); // inform the sleep island generation system that the object got woken up
|
||||
void notifyPutToSleep(); // inform the sleep island generation system that the object was put to sleep
|
||||
void internalWakeUpBase(PxReal wakeCounterValue);
|
||||
|
||||
PX_FORCE_INLINE void raiseVelocityModFlag(VelocityModFlags f) { mVelModState |= f; }
|
||||
PX_FORCE_INLINE void clearVelocityModFlag(VelocityModFlags f) { mVelModState &= ~f; }
|
||||
PX_FORCE_INLINE void setForcesToDefaults(bool enableGravity);
|
||||
};
|
||||
|
||||
#if PX_VC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
PX_FORCE_INLINE void Sc::BodySim::setForcesToDefaults(bool enableGravity)
|
||||
{
|
||||
if (!(mLLBody.mCore->mFlags & PxRigidBodyFlag::eRETAIN_ACCELERATIONS))
|
||||
{
|
||||
SimStateData* simStateData = getSimStateData(false);
|
||||
if(simStateData)
|
||||
{
|
||||
VelocityMod* velmod = simStateData->getVelocityModData();
|
||||
velmod->clear();
|
||||
}
|
||||
|
||||
if (enableGravity)
|
||||
mVelModState = VMF_GRAVITY_DIRTY; // We want to keep the gravity flag to make sure the acceleration gets changed to gravity-only
|
||||
// in the next step (unless the application adds new forces of course)
|
||||
else
|
||||
mVelModState = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SimStateData* simStateData = getSimStateData(false);
|
||||
if (simStateData)
|
||||
{
|
||||
VelocityMod* velmod = simStateData->getVelocityModData();
|
||||
velmod->clearPerStep();
|
||||
}
|
||||
|
||||
mVelModState &= (~(VMF_VEL_DIRTY));
|
||||
}
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE bool Sc::BodySim::checkSleepReadinessBesidesWakeCounter()
|
||||
{
|
||||
const BodyCore& bodyCore = getBodyCore();
|
||||
const SimStateData* simStateData = getSimStateData(false);
|
||||
const VelocityMod* velmod = simStateData ? simStateData->getVelocityModData() : NULL;
|
||||
|
||||
bool readyForSleep = bodyCore.getLinearVelocity().isZero() && bodyCore.getAngularVelocity().isZero();
|
||||
if (readVelocityModFlag(VMF_ACC_DIRTY))
|
||||
{
|
||||
readyForSleep = readyForSleep && (!velmod || velmod->getLinearVelModPerSec().isZero());
|
||||
readyForSleep = readyForSleep && (!velmod || velmod->getAngularVelModPerSec().isZero());
|
||||
}
|
||||
if (readVelocityModFlag(VMF_VEL_DIRTY))
|
||||
{
|
||||
readyForSleep = readyForSleep && (!velmod || velmod->getLinearVelModPerStep().isZero());
|
||||
readyForSleep = readyForSleep && (!velmod || velmod->getAngularVelModPerStep().isZero());
|
||||
}
|
||||
|
||||
return readyForSleep;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
139
engine/third_party/physx/source/simulationcontroller/src/ScBroadphase.cpp
vendored
Normal file
139
engine/third_party/physx/source/simulationcontroller/src/ScBroadphase.cpp
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScBroadphase.h"
|
||||
#include "BpAABBManagerBase.h"
|
||||
#include "ScShapeSim.h"
|
||||
#include "common/PxProfileZone.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
using namespace Bp;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BroadphaseManager::BroadphaseManager() :
|
||||
mBroadPhaseCallback (NULL),
|
||||
mOutOfBoundsIDs ("sceneOutOfBoundsIds")
|
||||
{
|
||||
}
|
||||
|
||||
BroadphaseManager::~BroadphaseManager()
|
||||
{
|
||||
}
|
||||
|
||||
void BroadphaseManager::prepareOutOfBoundsCallbacks(AABBManagerBase* aabbManager)
|
||||
{
|
||||
AABBManagerBase::OutOfBoundsData data;
|
||||
if(!aabbManager->getOutOfBoundsObjects(data))
|
||||
return;
|
||||
|
||||
PxU32 nbOut = data.mNbOutOfBoundsObjects;
|
||||
void** outObjects = data.mOutOfBoundsObjects;
|
||||
|
||||
mOutOfBoundsIDs.clear();
|
||||
|
||||
while(nbOut--)
|
||||
{
|
||||
const ElementSim* volume = reinterpret_cast<const ElementSim*>(*outObjects++);
|
||||
|
||||
const Sc::ShapeSim* sim = static_cast<const Sc::ShapeSim*>(volume);
|
||||
|
||||
mOutOfBoundsIDs.pushBack(sim->getElementID());
|
||||
}
|
||||
}
|
||||
|
||||
bool BroadphaseManager::fireOutOfBoundsCallbacks(Bp::AABBManagerBase* aabbManager, const ObjectIDTracker& tracker, PxU64 contextID)
|
||||
{
|
||||
PX_UNUSED(contextID);
|
||||
|
||||
AABBManagerBase::OutOfBoundsData data;
|
||||
if(!aabbManager->getOutOfBoundsObjects(data))
|
||||
return false;
|
||||
|
||||
bool outputWarning = false;
|
||||
|
||||
PxBroadPhaseCallback* cb = mBroadPhaseCallback;
|
||||
|
||||
// Actors
|
||||
{
|
||||
PxU32 nbOut = data.mNbOutOfBoundsObjects;
|
||||
void** outObjects = data.mOutOfBoundsObjects;
|
||||
|
||||
for(PxU32 i=0;i<nbOut;i++)
|
||||
{
|
||||
ElementSim* volume = reinterpret_cast<ElementSim*>(outObjects[i]);
|
||||
|
||||
Sc::ShapeSim* sim = static_cast<Sc::ShapeSim*>(volume);
|
||||
|
||||
// PT: TODO: I'm not sure the split between prepareOutOfBoundsCallbacks / fireOutOfBoundsCallbacks
|
||||
// and the test for deletion is still needed after the removal of SCB
|
||||
if(tracker.isDeletedID(mOutOfBoundsIDs[i]))
|
||||
continue;
|
||||
|
||||
if(cb)
|
||||
{
|
||||
PX_PROFILE_ZONE("USERCODE - PxBroadPhaseCallback::onObjectOutOfBounds", contextID);
|
||||
ActorSim& actor = volume->getActor();
|
||||
RigidSim& rigidSim = static_cast<RigidSim&>(actor);
|
||||
PxActor* pxActor = rigidSim.getPxActor();
|
||||
PxShape* px = sim->getPxShape();
|
||||
cb->onObjectOutOfBounds(*px, *pxActor);
|
||||
}
|
||||
else
|
||||
outputWarning = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Aggregates
|
||||
{
|
||||
PxU32 nbOut = data.mNbOutOfBoundsAggregates;
|
||||
void** outAgg = data.mOutOfBoundsAggregates;
|
||||
|
||||
for(PxU32 i=0;i<nbOut;i++)
|
||||
{
|
||||
PxAggregate* px = reinterpret_cast<PxAggregate*>(outAgg[i]);
|
||||
if(cb)
|
||||
{
|
||||
PX_PROFILE_ZONE("USERCODE - PxBroadPhaseCallback::onObjectOutOfBounds", contextID);
|
||||
cb->onObjectOutOfBounds(*px);
|
||||
}
|
||||
else
|
||||
outputWarning = true;
|
||||
}
|
||||
}
|
||||
|
||||
aabbManager->clearOutOfBoundsObjects();
|
||||
|
||||
return outputWarning;
|
||||
}
|
||||
|
||||
void BroadphaseManager::flush(Bp::AABBManagerBase* /*aabbManager*/)
|
||||
{
|
||||
mOutOfBoundsIDs.reset();
|
||||
}
|
||||
720
engine/third_party/physx/source/simulationcontroller/src/ScCCD.cpp
vendored
Normal file
720
engine/third_party/physx/source/simulationcontroller/src/ScCCD.cpp
vendored
Normal file
@@ -0,0 +1,720 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "common/PxProfileZone.h"
|
||||
#include "ScBodySim.h"
|
||||
#include "ScShapeSim.h"
|
||||
#include "ScArticulationSim.h"
|
||||
#include "ScScene.h"
|
||||
#include "DyIslandManager.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void BodySim::addToSpeculativeCCDMap()
|
||||
{
|
||||
if(mNodeIndex.isValid())
|
||||
{
|
||||
if(isArticulationLink())
|
||||
mScene.setSpeculativeCCDArticulationLink(mNodeIndex.index());
|
||||
else
|
||||
mScene.setSpeculativeCCDRigidBody(mNodeIndex.index());
|
||||
}
|
||||
}
|
||||
|
||||
void BodySim::removeFromSpeculativeCCDMap()
|
||||
{
|
||||
if(mNodeIndex.isValid())
|
||||
{
|
||||
if(isArticulationLink())
|
||||
mScene.resetSpeculativeCCDArticulationLink(mNodeIndex.index());
|
||||
else
|
||||
mScene.resetSpeculativeCCDRigidBody(mNodeIndex.index());
|
||||
}
|
||||
}
|
||||
|
||||
// PT: TODO: consider using a non-member function for this one
|
||||
void BodySim::updateContactDistance(PxReal* contactDistance, PxReal dt, const Bp::BoundsArray& boundsArray)
|
||||
{
|
||||
const PxsRigidBody& llBody = getLowLevelBody();
|
||||
|
||||
const PxRigidBodyFlags flags = llBody.getCore().mFlags;
|
||||
|
||||
// PT: TODO: no need to test eENABLE_SPECULATIVE_CCD if we parsed mSpeculativeCCDRigidBodyBitMap initially
|
||||
if((flags & PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD) && !(llBody.mInternalFlags & PxsRigidBody::eFROZEN))
|
||||
{
|
||||
// PT: if both CCD flags are enabled we're in "hybrid mode" and we only use speculative contacts for the angular part
|
||||
const PxReal linearInflation = (flags & PxRigidBodyFlag::eENABLE_CCD) ? 0.0f : llBody.getLinearVelocity().magnitude() * dt;
|
||||
|
||||
const float angVelMagTimesDt = llBody.getAngularVelocity().magnitude() * dt;
|
||||
|
||||
PxU32 nbElems = getNbElements();
|
||||
ElementSim** elems = getElements();
|
||||
while(nbElems--)
|
||||
{
|
||||
ShapeSim* current = static_cast<ShapeSim*>(*elems++);
|
||||
|
||||
const PxU32 index = current->getElementID();
|
||||
|
||||
const PxBounds3& bounds = boundsArray.getBounds(index);
|
||||
|
||||
const PxReal radius = bounds.getExtents().magnitude();
|
||||
|
||||
//Heuristic for angular velocity...
|
||||
const PxReal angularInflation = angVelMagTimesDt * radius;
|
||||
|
||||
contactDistance[index] = linearInflation + current->getContactOffset() + angularInflation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::updateContactDistance(PxReal* contactDistance, PxReal dt, const Bp::BoundsArray& boundsArray)
|
||||
{
|
||||
const PxU32 size = mBodies.size();
|
||||
for(PxU32 i=0; i<size; i++)
|
||||
mBodies[i]->updateContactDistance(contactDistance, dt, boundsArray);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class SpeculativeCCDBaseTask : public Cm::Task
|
||||
{
|
||||
PX_NOCOPY(SpeculativeCCDBaseTask)
|
||||
public:
|
||||
const Bp::BoundsArray& mBoundsArray;
|
||||
float* mContactDistances;
|
||||
const float mDt;
|
||||
|
||||
SpeculativeCCDBaseTask(PxU64 contextID, const Bp::BoundsArray& boundsArray, PxReal* contactDistances, PxReal dt) :
|
||||
Cm::Task (contextID),
|
||||
mBoundsArray (boundsArray),
|
||||
mContactDistances (contactDistances),
|
||||
mDt (dt)
|
||||
{}
|
||||
};
|
||||
|
||||
class SpeculativeCCDContactDistanceUpdateTask : public SpeculativeCCDBaseTask
|
||||
{
|
||||
public:
|
||||
static const PxU32 MaxBodies = 128;
|
||||
BodySim* mBodySims[MaxBodies];
|
||||
PxU32 mNbBodies;
|
||||
|
||||
SpeculativeCCDContactDistanceUpdateTask(PxU64 contextID, PxReal* contactDistances, PxReal dt, const Bp::BoundsArray& boundsArray) :
|
||||
SpeculativeCCDBaseTask (contextID, boundsArray, contactDistances, dt),
|
||||
mNbBodies (0)
|
||||
{}
|
||||
|
||||
virtual void runInternal()
|
||||
{
|
||||
const PxU32 nb = mNbBodies;
|
||||
for(PxU32 i=0; i<nb; i++)
|
||||
mBodySims[i]->updateContactDistance(mContactDistances, mDt, mBoundsArray);
|
||||
}
|
||||
|
||||
virtual const char* getName() const { return "SpeculativeCCDContactDistanceUpdateTask"; }
|
||||
|
||||
private:
|
||||
PX_NOCOPY(SpeculativeCCDContactDistanceUpdateTask)
|
||||
};
|
||||
|
||||
class SpeculativeCCDContactDistanceArticulationUpdateTask : public SpeculativeCCDBaseTask
|
||||
{
|
||||
public:
|
||||
ArticulationSim* mArticulation;
|
||||
|
||||
SpeculativeCCDContactDistanceArticulationUpdateTask(PxU64 contextID, PxReal* contactDistances, PxReal dt, const Bp::BoundsArray& boundsArray, ArticulationSim* sim) :
|
||||
SpeculativeCCDBaseTask (contextID, boundsArray, contactDistances, dt),
|
||||
mArticulation (sim)
|
||||
{}
|
||||
|
||||
virtual void runInternal()
|
||||
{
|
||||
mArticulation->updateContactDistance(mContactDistances, mDt, mBoundsArray);
|
||||
}
|
||||
|
||||
virtual const char* getName() const { return "SpeculativeCCDContactDistanceArticulationUpdateTask"; }
|
||||
|
||||
private:
|
||||
PX_NOCOPY(SpeculativeCCDContactDistanceArticulationUpdateTask)
|
||||
};
|
||||
}
|
||||
|
||||
static SpeculativeCCDContactDistanceUpdateTask* createCCDTask(Cm::FlushPool& pool, PxU64 contextID, PxReal* contactDistances, PxReal dt, const Bp::BoundsArray& boundsArray)
|
||||
{
|
||||
return PX_PLACEMENT_NEW(pool.allocate(sizeof(SpeculativeCCDContactDistanceUpdateTask)), SpeculativeCCDContactDistanceUpdateTask)(contextID, contactDistances, dt, boundsArray);
|
||||
}
|
||||
|
||||
void Sc::Scene::updateContactDistances(PxBaseTask* continuation)
|
||||
{
|
||||
PX_PROFILE_ZONE("Scene.updateContactDistances", mContextId);
|
||||
|
||||
Cm::FlushPool& pool = mLLContext->getTaskPool();
|
||||
IG::IslandSim& islandSim = mSimpleIslandManager->getAccurateIslandSim();
|
||||
bool hasContactDistanceChanged = mHasContactDistanceChanged;
|
||||
|
||||
// PT: TODO: it is quite unfortunate that we cannot shortcut parsing the bitmaps. Consider switching to arrays.
|
||||
// We remove sleeping bodies from the map but we never shrink it....
|
||||
|
||||
// PT: TODO: why do we need to involve the island manager here?
|
||||
// PT: TODO: why do we do that on sleeping bodies? Why don't we use mActiveBodies?
|
||||
// PxArray<BodyCore*> mActiveBodies; // Sorted: kinematic before dynamic
|
||||
// ===> because we remove bodies from the bitmap in BodySim::deactivate()
|
||||
|
||||
//calculate contact distance for speculative CCD shapes
|
||||
if(1)
|
||||
{
|
||||
PxBitMap::Iterator speculativeCCDIter(mSpeculativeCCDRigidBodyBitMap);
|
||||
|
||||
SpeculativeCCDContactDistanceUpdateTask* ccdTask = createCCDTask(pool, mContextId, mContactDistance->begin(), mDt, *mBoundsArray);
|
||||
|
||||
PxBitMapPinned& changedMap = mAABBManager->getChangedAABBMgActorHandleMap();
|
||||
|
||||
const size_t bodyOffset = PX_OFFSET_OF_RT(BodySim, getLowLevelBody());
|
||||
|
||||
//printf("\n");
|
||||
//PxU32 count = 0;
|
||||
|
||||
PxU32 nbBodies = 0;
|
||||
PxU32 index;
|
||||
while((index = speculativeCCDIter.getNext()) != PxBitMap::Iterator::DONE)
|
||||
{
|
||||
PxsRigidBody* rigidBody = getRigidBodyFromIG(islandSim, PxNodeIndex(index));
|
||||
BodySim* bodySim = reinterpret_cast<BodySim*>(reinterpret_cast<PxU8*>(rigidBody)-bodyOffset);
|
||||
if(bodySim)
|
||||
{
|
||||
//printf("%d\n", bodySim->getActiveListIndex());
|
||||
//printf("%d: %d\n", count++, bodySim->isActive());
|
||||
|
||||
hasContactDistanceChanged = true;
|
||||
ccdTask->mBodySims[nbBodies++] = bodySim;
|
||||
|
||||
// PT: ### changedMap pattern #1
|
||||
// PT: TODO: isn't there a problem here? The task function will only touch the shapes whose body has the
|
||||
// speculative flag and isn't frozen, but here we mark all shapes as changed no matter what.
|
||||
//
|
||||
// Also we test some bodySim data and one bit of each ShapeSim here, not great.
|
||||
PxU32 nbElems = bodySim->getNbElements();
|
||||
ElementSim** elems = bodySim->getElements();
|
||||
while(nbElems--)
|
||||
{
|
||||
ShapeSim* sim = static_cast<ShapeSim*>(*elems++);
|
||||
if(sim->getFlags() & PxShapeFlag::eSIMULATION_SHAPE)
|
||||
changedMap.growAndSet(sim->getElementID());
|
||||
}
|
||||
|
||||
// PT: TODO: better load balancing?
|
||||
if(nbBodies == SpeculativeCCDContactDistanceUpdateTask::MaxBodies)
|
||||
{
|
||||
ccdTask->mNbBodies = nbBodies;
|
||||
nbBodies = 0;
|
||||
startTask(ccdTask, continuation);
|
||||
|
||||
if(continuation)
|
||||
ccdTask = createCCDTask(pool, mContextId, mContactDistance->begin(), mDt, *mBoundsArray);
|
||||
else
|
||||
ccdTask->mNbBodies = 0; // PT: no need to create a new task in single-threaded mode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(nbBodies)
|
||||
{
|
||||
ccdTask->mNbBodies = nbBodies;
|
||||
startTask(ccdTask, continuation);
|
||||
}
|
||||
}
|
||||
/* else
|
||||
{
|
||||
// PT: codepath without mSpeculativeCCDRigidBodyBitMap
|
||||
PxU32 nb = mActiveBodies.size();
|
||||
BodyCore** bodies = mActiveBodies.begin();
|
||||
|
||||
while(nb--)
|
||||
{
|
||||
const BodyCore* current = *bodies++;
|
||||
BodySim* bodySim = current->getSim();
|
||||
if(bodySim)
|
||||
{
|
||||
...
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
//calculate contact distance for articulation links
|
||||
{
|
||||
PxBitMap::Iterator articulateCCDIter(mSpeculativeCDDArticulationBitMap);
|
||||
PxU32 index;
|
||||
while((index = articulateCCDIter.getNext()) != PxBitMap::Iterator::DONE)
|
||||
{
|
||||
ArticulationSim* articulationSim = getArticulationSim(islandSim, PxNodeIndex(index));
|
||||
if(articulationSim)
|
||||
{
|
||||
hasContactDistanceChanged = true;
|
||||
if(continuation)
|
||||
{
|
||||
SpeculativeCCDContactDistanceArticulationUpdateTask* articulationUpdateTask = PX_PLACEMENT_NEW(pool.allocate(sizeof(SpeculativeCCDContactDistanceArticulationUpdateTask)), SpeculativeCCDContactDistanceArticulationUpdateTask)(mContextId, mContactDistance->begin(), mDt, *mBoundsArray, articulationSim);
|
||||
articulationUpdateTask->setContinuation(continuation);
|
||||
articulationUpdateTask->removeReference();
|
||||
}
|
||||
else
|
||||
{
|
||||
articulationSim->updateContactDistance(mContactDistance->begin(), mDt, *mBoundsArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mHasContactDistanceChanged = hasContactDistanceChanged;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ScNPhaseCore.h"
|
||||
#include "ScShapeInteraction.h"
|
||||
#include "PxsCCD.h"
|
||||
#include "PxsSimulationController.h"
|
||||
#include "CmTransformUtils.h"
|
||||
|
||||
void Sc::Scene::setCCDContactModifyCallback(PxCCDContactModifyCallback* callback)
|
||||
{
|
||||
mCCDContext->setCCDContactModifyCallback(callback);
|
||||
}
|
||||
|
||||
PxCCDContactModifyCallback* Sc::Scene::getCCDContactModifyCallback() const
|
||||
{
|
||||
return mCCDContext->getCCDContactModifyCallback();
|
||||
}
|
||||
|
||||
void Sc::Scene::setCCDMaxPasses(PxU32 ccdMaxPasses)
|
||||
{
|
||||
mCCDContext->setCCDMaxPasses(ccdMaxPasses);
|
||||
}
|
||||
|
||||
PxU32 Sc::Scene::getCCDMaxPasses() const
|
||||
{
|
||||
return mCCDContext->getCCDMaxPasses();
|
||||
}
|
||||
|
||||
void Sc::Scene::setCCDThreshold(PxReal t)
|
||||
{
|
||||
mCCDContext->setCCDThreshold(t);
|
||||
}
|
||||
|
||||
PxReal Sc::Scene::getCCDThreshold() const
|
||||
{
|
||||
return mCCDContext->getCCDThreshold();
|
||||
}
|
||||
|
||||
void Sc::Scene::collectPostSolverVelocitiesBeforeCCD()
|
||||
{
|
||||
if(mContactReportsNeedPostSolverVelocity)
|
||||
{
|
||||
ActorPairReport*const* actorPairs = mNPhaseCore->getContactReportActorPairs();
|
||||
PxU32 nbActorPairs = mNPhaseCore->getNbContactReportActorPairs();
|
||||
for(PxU32 i=0; i < nbActorPairs; i++)
|
||||
{
|
||||
if(i < (nbActorPairs - 1))
|
||||
PxPrefetchLine(actorPairs[i+1]);
|
||||
|
||||
ActorPairReport* aPair = actorPairs[i];
|
||||
|
||||
ContactStreamManager& cs = aPair->getContactStreamManager();
|
||||
|
||||
PxU32 streamManagerFlag = cs.getFlags();
|
||||
if(streamManagerFlag & ContactStreamManagerFlag::eINVALID_STREAM)
|
||||
continue;
|
||||
|
||||
PxU8* stream = mNPhaseCore->getContactReportPairData(cs.bufferIndex);
|
||||
|
||||
if(i + 1 < nbActorPairs)
|
||||
PxPrefetch(&(actorPairs[i+1]->getContactStreamManager()));
|
||||
|
||||
if(!cs.extraDataSize)
|
||||
continue;
|
||||
else if (streamManagerFlag & ContactStreamManagerFlag::eNEEDS_POST_SOLVER_VELOCITY)
|
||||
cs.setContactReportPostSolverVelocity(stream, aPair->getActorA(), aPair->getActorB());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::Scene::updateCCDMultiPass(PxBaseTask* parentContinuation)
|
||||
{
|
||||
getCcdBodies().forceSize_Unsafe(mSimulationControllerCallback->getNbCcdBodies());
|
||||
|
||||
// second run of the broadphase for making sure objects we have integrated did not tunnel.
|
||||
if(mPublicFlags & PxSceneFlag::eENABLE_CCD)
|
||||
{
|
||||
if(mContactReportsNeedPostSolverVelocity)
|
||||
{
|
||||
// the CCD code will overwrite the post solver body velocities, hence, we need to extract the info
|
||||
// first if any CCD enabled pair requested it.
|
||||
collectPostSolverVelocitiesBeforeCCD();
|
||||
}
|
||||
|
||||
//We use 2 CCD task chains to be able to chain together an arbitrary number of ccd passes
|
||||
if(mPostCCDPass.size() != 2)
|
||||
{
|
||||
mPostCCDPass.clear();
|
||||
mUpdateCCDSinglePass.clear();
|
||||
mCCDBroadPhase.clear();
|
||||
mCCDBroadPhaseAABB.clear();
|
||||
mPostCCDPass.reserve(2);
|
||||
mUpdateCCDSinglePass.reserve(2);
|
||||
mUpdateCCDSinglePass2.reserve(2);
|
||||
mUpdateCCDSinglePass3.reserve(2);
|
||||
mCCDBroadPhase.reserve(2);
|
||||
mCCDBroadPhaseAABB.reserve(2);
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
mPostCCDPass.pushBack(Cm::DelegateTask<Sc::Scene, &Sc::Scene::postCCDPass>(mContextId, this, "ScScene.postCCDPass"));
|
||||
mUpdateCCDSinglePass.pushBack(Cm::DelegateTask<Sc::Scene, &Sc::Scene::updateCCDSinglePass>(mContextId, this, "ScScene.updateCCDSinglePass"));
|
||||
mUpdateCCDSinglePass2.pushBack(Cm::DelegateTask<Sc::Scene, &Sc::Scene::updateCCDSinglePassStage2>(mContextId, this, "ScScene.updateCCDSinglePassStage2"));
|
||||
mUpdateCCDSinglePass3.pushBack(Cm::DelegateTask<Sc::Scene, &Sc::Scene::updateCCDSinglePassStage3>(mContextId, this, "ScScene.updateCCDSinglePassStage3"));
|
||||
mCCDBroadPhase.pushBack(Cm::DelegateTask<Sc::Scene, &Sc::Scene::ccdBroadPhase>(mContextId, this, "ScScene.ccdBroadPhase"));
|
||||
mCCDBroadPhaseAABB.pushBack(Cm::DelegateTask<Sc::Scene, &Sc::Scene::ccdBroadPhaseAABB>(mContextId, this, "ScScene.ccdBroadPhaseAABB"));
|
||||
}
|
||||
}
|
||||
|
||||
//reset thread context in a place we know all tasks possibly accessing it, are in sync with. (see US6664)
|
||||
mLLContext->resetThreadContexts();
|
||||
|
||||
mCCDContext->updateCCDBegin();
|
||||
|
||||
mCCDBroadPhase[0].setContinuation(parentContinuation);
|
||||
mCCDBroadPhaseAABB[0].setContinuation(&mCCDBroadPhase[0]);
|
||||
mCCDBroadPhase[0].removeReference();
|
||||
mCCDBroadPhaseAABB[0].removeReference();
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class UpdateCCDBoundsTask : public Cm::Task
|
||||
{
|
||||
Bp::BoundsArray* mBoundArray;
|
||||
PxsTransformCache* mTransformCache;
|
||||
BodySim** mBodySims;
|
||||
PxU32 mNbToProcess;
|
||||
PxI32* mNumFastMovingShapes;
|
||||
|
||||
public:
|
||||
|
||||
static const PxU32 MaxPerTask = 256;
|
||||
|
||||
UpdateCCDBoundsTask(PxU64 contextID, Bp::BoundsArray* boundsArray, PxsTransformCache* transformCache, BodySim** bodySims, PxU32 nbToProcess, PxI32* numFastMovingShapes) :
|
||||
Cm::Task (contextID),
|
||||
mBoundArray (boundsArray),
|
||||
mTransformCache (transformCache),
|
||||
mBodySims (bodySims),
|
||||
mNbToProcess (nbToProcess),
|
||||
mNumFastMovingShapes(numFastMovingShapes)
|
||||
{
|
||||
}
|
||||
|
||||
virtual const char* getName() const { return "UpdateCCDBoundsTask";}
|
||||
|
||||
PxIntBool updateSweptBounds(ShapeSim* sim, BodySim* body)
|
||||
{
|
||||
PX_ASSERT(body==sim->getBodySim());
|
||||
|
||||
const PxU32 elementID = sim->getElementID();
|
||||
|
||||
const ShapeCore& shapeCore = sim->getCore();
|
||||
const PxTransform& endPose = mTransformCache->getTransformCache(elementID).transform;
|
||||
|
||||
const PxGeometry& shapeGeom = shapeCore.getGeometry();
|
||||
|
||||
const PxsRigidBody& rigidBody = body->getLowLevelBody();
|
||||
const PxsBodyCore& bodyCore = body->getBodyCore().getCore();
|
||||
PX_ALIGN(16, PxTransform shape2World);
|
||||
Cm::getDynamicGlobalPoseAligned(rigidBody.mLastTransform, shapeCore.getShape2Actor(), bodyCore.getBody2Actor(), shape2World);
|
||||
|
||||
const float ccdThreshold = computeCCDThreshold(shapeGeom);
|
||||
PxBounds3 bounds = Gu::computeBounds(shapeGeom, endPose);
|
||||
PxIntBool isFastMoving;
|
||||
if(1)
|
||||
{
|
||||
// PT: this alternative implementation avoids computing the start bounds for slow moving objects.
|
||||
isFastMoving = (shape2World.p - endPose.p).magnitudeSquared() >= ccdThreshold * ccdThreshold ? 1 : 0;
|
||||
if(isFastMoving)
|
||||
{
|
||||
const PxBounds3 startBounds = Gu::computeBounds(shapeGeom, shape2World);
|
||||
bounds.include(startBounds);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const PxBounds3 startBounds = Gu::computeBounds(shapeGeom, shape2World);
|
||||
|
||||
isFastMoving = (startBounds.getCenter() - bounds.getCenter()).magnitudeSquared() >= ccdThreshold * ccdThreshold ? 1 : 0;
|
||||
|
||||
if(isFastMoving)
|
||||
bounds.include(startBounds);
|
||||
}
|
||||
|
||||
PX_ASSERT(bounds.minimum.x <= bounds.maximum.x
|
||||
&& bounds.minimum.y <= bounds.maximum.y
|
||||
&& bounds.minimum.z <= bounds.maximum.z);
|
||||
|
||||
mBoundArray->setBounds(bounds, elementID);
|
||||
|
||||
return isFastMoving;
|
||||
}
|
||||
|
||||
virtual void runInternal()
|
||||
{
|
||||
PxU32 activeShapes = 0;
|
||||
const PxU32 nb = mNbToProcess;
|
||||
for(PxU32 i=0; i<nb; i++)
|
||||
{
|
||||
PxU32 isFastMoving = 0;
|
||||
BodySim& bodySim = *mBodySims[i];
|
||||
|
||||
PxU32 nbElems = bodySim.getNbElements();
|
||||
ElementSim** elems = bodySim.getElements();
|
||||
while(nbElems--)
|
||||
{
|
||||
ShapeSim* sim = static_cast<ShapeSim*>(*elems++);
|
||||
if(sim->getFlags() & PxU32(PxShapeFlag::eSIMULATION_SHAPE | PxShapeFlag::eTRIGGER_SHAPE))
|
||||
{
|
||||
const PxIntBool fastMovingShape = updateSweptBounds(sim, &bodySim);
|
||||
activeShapes += fastMovingShape;
|
||||
|
||||
isFastMoving = isFastMoving | fastMovingShape;
|
||||
}
|
||||
}
|
||||
|
||||
bodySim.getLowLevelBody().getCore().isFastMoving = isFastMoving!=0;
|
||||
}
|
||||
|
||||
PxAtomicAdd(mNumFastMovingShapes, PxI32(activeShapes));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void Sc::Scene::ccdBroadPhaseAABB(PxBaseTask* continuation)
|
||||
{
|
||||
PX_PROFILE_START_CROSSTHREAD("Sim.ccdBroadPhaseComplete", mContextId);
|
||||
PX_PROFILE_ZONE("Sim.ccdBroadPhaseAABB", mContextId);
|
||||
PX_UNUSED(continuation);
|
||||
|
||||
PxU32 currentPass = mCCDContext->getCurrentCCDPass();
|
||||
|
||||
Cm::FlushPool& flushPool = mLLContext->getTaskPool();
|
||||
|
||||
mNumFastMovingShapes = 0;
|
||||
|
||||
//If we are on the 1st pass or we had some sweep hits previous CCD pass, we need to run CCD again
|
||||
if(currentPass == 0 || mCCDContext->getNumSweepHits())
|
||||
{
|
||||
PxsTransformCache& transformCache = getLowLevelContext()->getTransformCache();
|
||||
for(PxU32 i = 0; i < mCcdBodies.size(); i+= UpdateCCDBoundsTask::MaxPerTask)
|
||||
{
|
||||
const PxU32 nbToProcess = PxMin(UpdateCCDBoundsTask::MaxPerTask, mCcdBodies.size() - i);
|
||||
UpdateCCDBoundsTask* task = PX_PLACEMENT_NEW(flushPool.allocate(sizeof(UpdateCCDBoundsTask)), UpdateCCDBoundsTask)(mContextId, mBoundsArray, &transformCache, &mCcdBodies[i], nbToProcess, &mNumFastMovingShapes);
|
||||
task->setContinuation(continuation);
|
||||
task->removeReference();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::Scene::ccdBroadPhase(PxBaseTask* continuation)
|
||||
{
|
||||
PX_PROFILE_ZONE("Sim.ccdBroadPhase", mContextId);
|
||||
|
||||
PxU32 currentPass = mCCDContext->getCurrentCCDPass();
|
||||
const PxU32 ccdMaxPasses = mCCDContext->getCCDMaxPasses();
|
||||
mCCDPass = currentPass+1;
|
||||
|
||||
//If we are on the 1st pass or we had some sweep hits previous CCD pass, we need to run CCD again
|
||||
if( (currentPass == 0 || mCCDContext->getNumSweepHits()) && mNumFastMovingShapes != 0)
|
||||
{
|
||||
const PxU32 currIndex = currentPass & 1;
|
||||
const PxU32 nextIndex = 1 - currIndex;
|
||||
//Initialize the CCD task chain unless this is the final pass
|
||||
if(currentPass != (ccdMaxPasses - 1))
|
||||
{
|
||||
mCCDBroadPhase[nextIndex].setContinuation(continuation);
|
||||
mCCDBroadPhaseAABB[nextIndex].setContinuation(&mCCDBroadPhase[nextIndex]);
|
||||
}
|
||||
mPostCCDPass[currIndex].setContinuation(currentPass == ccdMaxPasses-1 ? continuation : &mCCDBroadPhaseAABB[nextIndex]);
|
||||
mUpdateCCDSinglePass3[currIndex].setContinuation(&mPostCCDPass[currIndex]);
|
||||
mUpdateCCDSinglePass2[currIndex].setContinuation(&mUpdateCCDSinglePass3[currIndex]);
|
||||
mUpdateCCDSinglePass[currIndex].setContinuation(&mUpdateCCDSinglePass2[currIndex]);
|
||||
|
||||
//Do the actual broad phase
|
||||
PxBaseTask* continuationTask = &mUpdateCCDSinglePass[currIndex];
|
||||
// const PxU32 numCpuTasks = continuationTask->getTaskManager()->getCpuDispatcher()->getWorkerCount();
|
||||
|
||||
mCCDBp = true;
|
||||
|
||||
setupBroadPhaseFirstAndSecondPassTasks(continuationTask);
|
||||
|
||||
//mAABBManager->updateAABBsAndBP(numCpuTasks, mLLContext->getTaskPool(), &mLLContext->getScratchAllocator(), false, continuationTask, NULL);
|
||||
|
||||
//Allow the CCD task chain to continue
|
||||
mPostCCDPass[currIndex].removeReference();
|
||||
mUpdateCCDSinglePass3[currIndex].removeReference();
|
||||
mUpdateCCDSinglePass2[currIndex].removeReference();
|
||||
mUpdateCCDSinglePass[currIndex].removeReference();
|
||||
if(currentPass != (ccdMaxPasses - 1))
|
||||
{
|
||||
mCCDBroadPhase[nextIndex].removeReference();
|
||||
mCCDBroadPhaseAABB[nextIndex].removeReference();
|
||||
}
|
||||
}
|
||||
else if (currentPass == 0)
|
||||
{
|
||||
PX_PROFILE_STOP_CROSSTHREAD("Sim.ccdBroadPhaseComplete", mContextId);
|
||||
mCCDContext->resetContactManagers();
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::Scene::updateCCDSinglePass(PxBaseTask* continuation)
|
||||
{
|
||||
PX_PROFILE_ZONE("Sim.updateCCDSinglePass", mContextId);
|
||||
mReportShapePairTimeStamp++; // This will makes sure that new report pairs will get created instead of re-using the existing ones.
|
||||
|
||||
mAABBManager->postBroadPhase(NULL, *getFlushPool());
|
||||
finishBroadPhase(continuation);
|
||||
|
||||
const PxU32 currentPass = mCCDContext->getCurrentCCDPass() + 1; // 0 is reserved for discrete collision phase
|
||||
if(currentPass == 1) // reset the handle map so we only update CCD objects from here on
|
||||
{
|
||||
PxBitMapPinned& changedAABBMgrActorHandles = mAABBManager->getChangedAABBMgActorHandleMap();
|
||||
//changedAABBMgrActorHandles.clear();
|
||||
for(PxU32 i = 0; i < mCcdBodies.size();i++)
|
||||
{
|
||||
// PT: ### changedMap pattern #1
|
||||
PxU32 nbElems = mCcdBodies[i]->getNbElements();
|
||||
ElementSim** elems = mCcdBodies[i]->getElements();
|
||||
while(nbElems--)
|
||||
{
|
||||
ShapeSim* sim = static_cast<ShapeSim*>(*elems++);
|
||||
if(sim->getFlags()&PxU32(PxShapeFlag::eSIMULATION_SHAPE | PxShapeFlag::eTRIGGER_SHAPE)) // TODO: need trigger shape here?
|
||||
changedAABBMgrActorHandles.growAndSet(sim->getElementID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::Scene::updateCCDSinglePassStage2(PxBaseTask* continuation)
|
||||
{
|
||||
PX_PROFILE_ZONE("Sim.updateCCDSinglePassStage2", mContextId);
|
||||
postBroadPhaseStage2(continuation);
|
||||
}
|
||||
|
||||
void Sc::Scene::updateCCDSinglePassStage3(PxBaseTask* continuation)
|
||||
{
|
||||
PX_PROFILE_ZONE("Sim.updateCCDSinglePassStage3", mContextId);
|
||||
mReportShapePairTimeStamp++; // This will makes sure that new report pairs will get created instead of re-using the existing ones.
|
||||
|
||||
const PxU32 currentPass = mCCDContext->getCurrentCCDPass() + 1; // 0 is reserved for discrete collision phase
|
||||
finishBroadPhaseStage2(currentPass);
|
||||
PX_PROFILE_STOP_CROSSTHREAD("Sim.ccdBroadPhaseComplete", mContextId);
|
||||
|
||||
//reset thread context in a place we know all tasks possibly accessing it, are in sync with. (see US6664)
|
||||
mLLContext->resetThreadContexts();
|
||||
|
||||
mCCDContext->updateCCD(mDt, continuation, mSimpleIslandManager->getAccurateIslandSim(), (mPublicFlags & PxSceneFlag::eDISABLE_CCD_RESWEEP), mNumFastMovingShapes);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE Sc::ShapeInteraction* getSI(PxvContactManagerTouchEvent& evt)
|
||||
{
|
||||
return reinterpret_cast<Sc::ShapeInteraction*>(evt.getCMTouchEventUserData());
|
||||
}
|
||||
|
||||
void Sc::Scene::postCCDPass(PxBaseTask* /*continuation*/)
|
||||
{
|
||||
// - Performs sleep check
|
||||
// - Updates touch flags
|
||||
|
||||
PxU32 currentPass = mCCDContext->getCurrentCCDPass();
|
||||
PX_ASSERT(currentPass > 0); // to make sure changes to the CCD pass counting get noticed. For contact reports, 0 means discrete collision phase.
|
||||
|
||||
PxU32 newTouchCount, lostTouchCount, ccdTouchCount;
|
||||
mLLContext->getManagerTouchEventCount(&newTouchCount, &lostTouchCount, &ccdTouchCount);
|
||||
PX_ALLOCA(newTouches, PxvContactManagerTouchEvent, newTouchCount);
|
||||
PX_ALLOCA(lostTouches, PxvContactManagerTouchEvent, lostTouchCount);
|
||||
PX_ALLOCA(ccdTouches, PxvContactManagerTouchEvent, ccdTouchCount);
|
||||
|
||||
PxsContactManagerOutputIterator outputs = mLLContext->getNphaseImplementationContext()->getContactManagerOutputs();
|
||||
|
||||
// Note: For contact notifications it is important that the new touch pairs get processed before the lost touch pairs.
|
||||
// This allows to know for sure if a pair of actors lost all touch (see eACTOR_PAIR_LOST_TOUCH).
|
||||
mLLContext->fillManagerTouchEvents(newTouches, newTouchCount, lostTouches, lostTouchCount, ccdTouches, ccdTouchCount);
|
||||
for(PxU32 i=0; i<newTouchCount; ++i)
|
||||
{
|
||||
ShapeInteraction* si = getSI(newTouches[i]);
|
||||
PX_ASSERT(si);
|
||||
mNPhaseCore->managerNewTouch(*si);
|
||||
si->managerNewTouch(currentPass, outputs);
|
||||
if (!si->readFlag(ShapeInteraction::CONTACTS_RESPONSE_DISABLED))
|
||||
{
|
||||
mSimpleIslandManager->setEdgeConnected(si->getEdgeIndex(), IG::Edge::eCONTACT_MANAGER);
|
||||
}
|
||||
}
|
||||
for(PxU32 i=0; i<lostTouchCount; ++i)
|
||||
{
|
||||
ShapeInteraction* si = getSI(lostTouches[i]);
|
||||
PX_ASSERT(si);
|
||||
if (si->managerLostTouch(currentPass, outputs) && !si->readFlag(ShapeInteraction::CONTACTS_RESPONSE_DISABLED))
|
||||
addToLostTouchList(si->getActor0(), si->getActor1());
|
||||
|
||||
mSimpleIslandManager->setEdgeDisconnected(si->getEdgeIndex());
|
||||
}
|
||||
for(PxU32 i=0; i<ccdTouchCount; ++i)
|
||||
{
|
||||
ShapeInteraction* si = getSI(ccdTouches[i]);
|
||||
PX_ASSERT(si);
|
||||
si->sendCCDRetouch(currentPass, outputs);
|
||||
}
|
||||
checkForceThresholdContactEvents(currentPass);
|
||||
{
|
||||
PxBitMapPinned& changedAABBMgrActorHandles = mAABBManager->getChangedAABBMgActorHandleMap();
|
||||
|
||||
for (PxU32 i = 0, s = mCcdBodies.size(); i < s; i++)
|
||||
{
|
||||
BodySim*const body = mCcdBodies[i];
|
||||
if(i+8 < s)
|
||||
PxPrefetch(mCcdBodies[i+8], 512);
|
||||
|
||||
PX_ASSERT(body->getBody2World().p.isFinite());
|
||||
PX_ASSERT(body->getBody2World().q.isFinite());
|
||||
|
||||
body->updateCached(&changedAABBMgrActorHandles);
|
||||
}
|
||||
|
||||
ArticulationCore* const* articList = mArticulations.getEntries();
|
||||
for(PxU32 i=0;i<mArticulations.size();i++)
|
||||
articList[i]->getSim()->updateCached(&changedAABBMgrActorHandles);
|
||||
}
|
||||
}
|
||||
134
engine/third_party/physx/source/simulationcontroller/src/ScConstraintBreakage.cpp
vendored
Normal file
134
engine/third_party/physx/source/simulationcontroller/src/ScConstraintBreakage.cpp
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScScene.h"
|
||||
#include "ScConstraintSim.h"
|
||||
#include "ScConstraintCore.h"
|
||||
#include "ScConstraintInteraction.h"
|
||||
#include "common/PxProfileZone.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
// PT: the breakable constraints are added to / removed from mActiveBreakableConstraints:
|
||||
|
||||
void Sc::Scene::addActiveBreakableConstraint(Sc::ConstraintSim* c, Sc::ConstraintInteraction* ci)
|
||||
{
|
||||
PX_ASSERT(ci && ci->readInteractionFlag(InteractionFlag::eIS_ACTIVE));
|
||||
PX_UNUSED(ci);
|
||||
PX_ASSERT(!mActiveBreakableConstraints.contains(c));
|
||||
PX_ASSERT(!c->isBroken());
|
||||
mActiveBreakableConstraints.insert(c);
|
||||
c->setFlag(ConstraintSim::eCHECK_MAX_FORCE_EXCEEDED);
|
||||
}
|
||||
|
||||
void Sc::Scene::removeActiveBreakableConstraint(Sc::ConstraintSim* c)
|
||||
{
|
||||
const bool exists = mActiveBreakableConstraints.erase(c);
|
||||
PX_ASSERT(exists);
|
||||
PX_UNUSED(exists);
|
||||
c->clearFlag(ConstraintSim::eCHECK_MAX_FORCE_EXCEEDED);
|
||||
}
|
||||
|
||||
// PT: then at runtime we parse mActiveBreakableConstraints, check for max force exceeded,
|
||||
// and add broken constraints to mBrokenConstraints:
|
||||
|
||||
void Sc::Scene::checkConstraintBreakage()
|
||||
{
|
||||
PX_PROFILE_ZONE("Sim.checkConstraintBreakage", mContextId);
|
||||
|
||||
PxU32 count = mActiveBreakableConstraints.size();
|
||||
if(!count)
|
||||
return;
|
||||
|
||||
PxPinnedArray<Dy::ConstraintWriteback>& pool = mDynamicsContext->getConstraintWriteBackPool();
|
||||
|
||||
ConstraintSim* const* constraints = mActiveBreakableConstraints.getEntries();
|
||||
while(count--)
|
||||
{
|
||||
ConstraintSim* sim = constraints[count]; // start from the back because broken constraints get removed from the list
|
||||
|
||||
PX_ASSERT(sim->readFlag(ConstraintSim::eCHECK_MAX_FORCE_EXCEEDED));
|
||||
|
||||
const Dy::ConstraintWriteback& solverOutput = pool[sim->getLowLevelConstraint().index];
|
||||
if(solverOutput.isBroken())
|
||||
{
|
||||
sim->setFlag(ConstraintSim::eBROKEN);
|
||||
|
||||
ConstraintCore& core = sim->getCore();
|
||||
if(mSimulationEventCallback)
|
||||
{
|
||||
PX_ASSERT(mBrokenConstraints.find(&core) == mBrokenConstraints.end());
|
||||
mBrokenConstraints.pushBack(&core);
|
||||
}
|
||||
|
||||
core.breakApart();
|
||||
|
||||
ConstraintInteraction* interaction = const_cast<ConstraintInteraction*>(sim->getInteraction());
|
||||
|
||||
interaction->destroy(); // PT: this will call removeFromActiveBreakableList above
|
||||
|
||||
// update related SIPs
|
||||
{
|
||||
ActorSim& a0 = interaction->getActorSim0();
|
||||
ActorSim& a1 = interaction->getActorSim1();
|
||||
ActorSim& actor = (a0.getActorInteractionCount() < a1.getActorInteractionCount()) ? a0 : a1;
|
||||
|
||||
actor.setActorsInteractionsDirty(InteractionDirtyFlag::eFILTER_STATE, NULL, InteractionFlag::eRB_ELEMENT);
|
||||
// because broken constraints can re-enable contact response between the two bodies
|
||||
}
|
||||
|
||||
PX_ASSERT(!sim->readFlag(ConstraintSim::eCHECK_MAX_FORCE_EXCEEDED));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PT: finally mBrokenConstraints is parsed and callbacks issued:
|
||||
|
||||
void Sc::Scene::fireBrokenConstraintCallbacks()
|
||||
{
|
||||
if(!mSimulationEventCallback)
|
||||
return;
|
||||
|
||||
const PxU32 count = mBrokenConstraints.size();
|
||||
for(PxU32 i=0;i<count;i++)
|
||||
{
|
||||
Sc::ConstraintCore* c = mBrokenConstraints[i];
|
||||
PX_ASSERT(c->getSim());
|
||||
|
||||
PxU32 typeID = 0xffffffff;
|
||||
void* externalRef = c->getPxConnector()->getExternalReference(typeID);
|
||||
PX_CHECK_MSG(typeID != 0xffffffff, "onConstraintBreak: Invalid constraint type ID.");
|
||||
|
||||
PxConstraintInfo constraintInfo(c->getPxConstraint(), externalRef, typeID);
|
||||
{
|
||||
// PT: TODO: batch data and call this only once
|
||||
PX_PROFILE_ZONE("USERCODE - PxSimulationEventCallback::onConstraintBreak", mContextId);
|
||||
mSimulationEventCallback->onConstraintBreak(&constraintInfo, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
115
engine/third_party/physx/source/simulationcontroller/src/ScConstraintCore.cpp
vendored
Normal file
115
engine/third_party/physx/source/simulationcontroller/src/ScConstraintCore.cpp
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScConstraintCore.h"
|
||||
#include "ScPhysics.h"
|
||||
#include "ScConstraintSim.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::ConstraintCore::ConstraintCore(PxConstraintConnector& connector, const PxConstraintShaderTable& shaders, PxU32 dataSize) :
|
||||
mFlags (PxConstraintFlag::eDRIVE_LIMITS_ARE_FORCES),
|
||||
mIsDirty (1),
|
||||
mAppliedForce (PxVec3(0.0f)),
|
||||
mAppliedTorque (PxVec3(0.0f)),
|
||||
mConnector (&connector),
|
||||
mSolverPrep (shaders.solverPrep),
|
||||
mVisualize (shaders.visualize),
|
||||
mDataSize (dataSize),
|
||||
mLinearBreakForce (PX_MAX_F32),
|
||||
mAngularBreakForce (PX_MAX_F32),
|
||||
mMinResponseThreshold (0.0f),
|
||||
mSim (NULL),
|
||||
mResidual ()
|
||||
{
|
||||
}
|
||||
|
||||
void Sc::ConstraintCore::setFlags(PxConstraintFlags flags)
|
||||
{
|
||||
PxConstraintFlags old = mFlags;
|
||||
flags = flags | (old & PxConstraintFlag::eGPU_COMPATIBLE); // eGPU_COMPATIBLE is for internal use only and should keep its initial state
|
||||
if(flags != old)
|
||||
{
|
||||
mFlags = flags;
|
||||
if(mSim)
|
||||
mSim->postFlagChange(old, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ConstraintCore::getForce(PxVec3& force, PxVec3& torque) const
|
||||
{
|
||||
if(!mSim)
|
||||
{
|
||||
force = PxVec3(0.0f);
|
||||
torque = PxVec3(0.0f);
|
||||
}
|
||||
else
|
||||
mSim->getForce(force, torque);
|
||||
}
|
||||
|
||||
void Sc::ConstraintCore::setBodies(RigidCore* r0v, RigidCore* r1v)
|
||||
{
|
||||
if(mSim)
|
||||
mSim->setBodies(r0v, r1v);
|
||||
}
|
||||
|
||||
void Sc::ConstraintCore::setBreakForce(PxReal linear, PxReal angular)
|
||||
{
|
||||
mLinearBreakForce = linear;
|
||||
mAngularBreakForce = angular;
|
||||
|
||||
if(mSim)
|
||||
mSim->setBreakForceLL(linear, angular);
|
||||
}
|
||||
|
||||
void Sc::ConstraintCore::setMinResponseThreshold(PxReal threshold)
|
||||
{
|
||||
mMinResponseThreshold = threshold;
|
||||
|
||||
if(mSim)
|
||||
mSim->setMinResponseThresholdLL(threshold);
|
||||
}
|
||||
|
||||
PxConstraint* Sc::ConstraintCore::getPxConstraint()
|
||||
{
|
||||
return gOffsetTable.convertScConstraint2Px(this);
|
||||
}
|
||||
|
||||
const PxConstraint* Sc::ConstraintCore::getPxConstraint() const
|
||||
{
|
||||
return gOffsetTable.convertScConstraint2Px(this);
|
||||
}
|
||||
|
||||
void Sc::ConstraintCore::breakApart()
|
||||
{
|
||||
// TODO: probably want to do something with the interaction here
|
||||
// as well as remove the constraint from LL.
|
||||
|
||||
mFlags |= PxConstraintFlag::eBROKEN;
|
||||
}
|
||||
|
||||
171
engine/third_party/physx/source/simulationcontroller/src/ScConstraintInteraction.cpp
vendored
Normal file
171
engine/third_party/physx/source/simulationcontroller/src/ScConstraintInteraction.cpp
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScConstraintInteraction.h"
|
||||
#include "ScConstraintSim.h"
|
||||
#include "ScBodySim.h"
|
||||
#include "ScScene.h"
|
||||
#include "PxsRigidBody.h"
|
||||
#include "PxsSimpleIslandManager.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
ConstraintInteraction::ConstraintInteraction(ConstraintSim* constraint, RigidSim& r0, RigidSim& r1) :
|
||||
Interaction (r0, r1, InteractionType::eCONSTRAINTSHADER, InteractionFlag::eCONSTRAINT),
|
||||
mConstraint (constraint)
|
||||
{
|
||||
{
|
||||
onActivate();
|
||||
registerInActors();
|
||||
}
|
||||
|
||||
BodySim* b0 = mConstraint->getBody(0);
|
||||
BodySim* b1 = mConstraint->getBody(1);
|
||||
|
||||
if(b0)
|
||||
b0->onConstraintAttach();
|
||||
if(b1)
|
||||
b1->onConstraintAttach();
|
||||
|
||||
IG::SimpleIslandManager* simpleIslandManager = getScene().getSimpleIslandManager();
|
||||
mEdgeIndex = simpleIslandManager->addConstraint(&mConstraint->getLowLevelConstraint(), b0 ? b0->getNodeIndex() : PxNodeIndex(), b1 ? b1->getNodeIndex() : PxNodeIndex(), this);
|
||||
}
|
||||
|
||||
ConstraintInteraction::~ConstraintInteraction()
|
||||
{
|
||||
PX_ASSERT(!readInteractionFlag(InteractionFlag::eIN_DIRTY_LIST));
|
||||
PX_ASSERT(!getDirtyFlags());
|
||||
PX_ASSERT(!mConstraint->readFlag(ConstraintSim::eCHECK_MAX_FORCE_EXCEEDED));
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void removeFromActiveBreakableList(ConstraintSim* constraint, Scene& s)
|
||||
{
|
||||
if(constraint->readFlag(ConstraintSim::eBREAKABLE | ConstraintSim::eCHECK_MAX_FORCE_EXCEEDED) == (ConstraintSim::eBREAKABLE | ConstraintSim::eCHECK_MAX_FORCE_EXCEEDED))
|
||||
s.removeActiveBreakableConstraint(constraint);
|
||||
}
|
||||
|
||||
void ConstraintInteraction::destroy()
|
||||
{
|
||||
setClean(true); // removes the pair from the dirty interaction list etc.
|
||||
|
||||
Scene& scene = getScene();
|
||||
|
||||
removeFromActiveBreakableList(mConstraint, scene);
|
||||
|
||||
if(mEdgeIndex != IG_INVALID_EDGE)
|
||||
scene.getSimpleIslandManager()->removeConnection(mEdgeIndex);
|
||||
mEdgeIndex = IG_INVALID_EDGE;
|
||||
|
||||
unregisterFromActors();
|
||||
|
||||
BodySim* b0 = mConstraint->getBody(0);
|
||||
BodySim* b1 = mConstraint->getBody(1);
|
||||
|
||||
if(b0)
|
||||
b0->onConstraintDetach(); // Note: Has to be done AFTER the interaction has unregistered from the actors
|
||||
if(b1)
|
||||
b1->onConstraintDetach(); // Note: Has to be done AFTER the interaction has unregistered from the actors
|
||||
|
||||
clearInteractionFlag(InteractionFlag::eIS_ACTIVE); // ensures that broken constraints do not go into the list of active breakable constraints anymore
|
||||
}
|
||||
|
||||
void ConstraintInteraction::updateState()
|
||||
{
|
||||
PX_ASSERT(!mConstraint->isBroken());
|
||||
PX_ASSERT(getDirtyFlags() & InteractionDirtyFlag::eBODY_KINEMATIC); // at the moment this should be the only reason for this method being called
|
||||
|
||||
// at least one of the bodies got switched from kinematic to dynamic. This will not have changed the sleep state of the interactions, so the
|
||||
// constraint interactions are just marked dirty and processed as part of the dirty interaction update system.
|
||||
//
|
||||
// -> need to check whether to activate the constraint and whether constraint break testing
|
||||
// is now necessary
|
||||
//
|
||||
// the transition from dynamic to kinematic will always trigger an onDeactivate() (because the body gets deactivated)
|
||||
// and thus there is no need to consider that case here.
|
||||
//
|
||||
|
||||
onActivate(); // note: this will not activate if the necessary conditions are not met, so it can be called even if the pair has been deactivated again before the
|
||||
// simulation step started
|
||||
}
|
||||
|
||||
bool ConstraintInteraction::onActivate()
|
||||
{
|
||||
PX_ASSERT(!mConstraint->isBroken());
|
||||
|
||||
BodySim* b0 = mConstraint->getBody(0);
|
||||
BodySim* b1 = mConstraint->getBody(1);
|
||||
|
||||
const bool b0Vote = !b0 || b0->isActive();
|
||||
const bool b1Vote = !b1 || b1->isActive();
|
||||
|
||||
const bool b0Dynamic = b0 && (!b0->isKinematic());
|
||||
const bool b1Dynamic = b1 && (!b1->isKinematic());
|
||||
|
||||
//
|
||||
// note: constraints between kinematics and kinematics/statics are always inactive and must not be activated
|
||||
//
|
||||
if((b0Vote || b1Vote) && (b0Dynamic || b1Dynamic))
|
||||
{
|
||||
raiseInteractionFlag(InteractionFlag::eIS_ACTIVE);
|
||||
|
||||
if(mConstraint->readFlag(ConstraintSim::eBREAKABLE | ConstraintSim::eCHECK_MAX_FORCE_EXCEEDED) == ConstraintSim::eBREAKABLE)
|
||||
getScene().addActiveBreakableConstraint(mConstraint, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ConstraintInteraction::onDeactivate()
|
||||
{
|
||||
const BodySim* b0 = mConstraint->getBody(0);
|
||||
const BodySim* b1 = mConstraint->getBody(1);
|
||||
|
||||
const bool b0Dynamic = b0 && (!b0->isKinematic());
|
||||
const bool b1Dynamic = b1 && (!b1->isKinematic());
|
||||
|
||||
PX_ASSERT( (!b0 && b1 && !b1->isActive()) ||
|
||||
(!b1 && b0 && !b0->isActive()) ||
|
||||
((b0 && b1 && (!b0->isActive() || !b1->isActive()))) );
|
||||
|
||||
//
|
||||
// note: constraints between kinematics and kinematics/statics should always get deactivated
|
||||
//
|
||||
if(((!b0 || !b0->isActive()) && (!b1 || !b1->isActive())) || (!b0Dynamic && !b1Dynamic))
|
||||
{
|
||||
removeFromActiveBreakableList(mConstraint, getScene());
|
||||
|
||||
clearInteractionFlag(InteractionFlag::eIS_ACTIVE);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
65
engine/third_party/physx/source/simulationcontroller/src/ScConstraintInteraction.h
vendored
Normal file
65
engine/third_party/physx/source/simulationcontroller/src/ScConstraintInteraction.h
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_CONSTRAINT_INTERACTION_H
|
||||
#define SC_CONSTRAINT_INTERACTION_H
|
||||
|
||||
#include "ScInteraction.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class ConstraintSim;
|
||||
class RigidSim;
|
||||
|
||||
class ConstraintInteraction : public Interaction
|
||||
{
|
||||
public:
|
||||
ConstraintInteraction(ConstraintSim* shader, RigidSim& r0, RigidSim& r1);
|
||||
~ConstraintInteraction();
|
||||
|
||||
bool onActivate();
|
||||
bool onDeactivate();
|
||||
|
||||
void updateState();
|
||||
void destroy(); // disables the interaction and unregisters from the system. Does NOT delete the object. This is used on destruction but also when a constraint breaks.
|
||||
|
||||
PX_FORCE_INLINE ConstraintSim* getConstraint() { return mConstraint; }
|
||||
PX_FORCE_INLINE IG::EdgeIndex getEdgeIndex() const { return mEdgeIndex; }
|
||||
|
||||
private:
|
||||
ConstraintSim* mConstraint;
|
||||
IG::EdgeIndex mEdgeIndex;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
226
engine/third_party/physx/source/simulationcontroller/src/ScConstraintSim.cpp
vendored
Normal file
226
engine/third_party/physx/source/simulationcontroller/src/ScConstraintSim.cpp
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScBodySim.h"
|
||||
#include "ScStaticSim.h"
|
||||
#include "ScConstraintCore.h"
|
||||
#include "ScConstraintSim.h"
|
||||
#include "ScConstraintInteraction.h"
|
||||
#include "ScElementSimInteraction.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
static ConstraintInteraction* createInteraction(ConstraintSim* sim, RigidCore* r0, RigidCore* r1, Scene& scene)
|
||||
{
|
||||
return scene.getConstraintInteractionPool().construct( sim,
|
||||
r0 ? *r0->getSim() : scene.getStaticAnchor(),
|
||||
r1 ? *r1->getSim() : scene.getStaticAnchor());
|
||||
}
|
||||
|
||||
static void releaseInteraction(ConstraintInteraction* interaction, const ConstraintSim* sim, Scene& scene)
|
||||
{
|
||||
if(!sim->isBroken())
|
||||
interaction->destroy();
|
||||
|
||||
scene.getConstraintInteractionPool().destroy(interaction);
|
||||
}
|
||||
|
||||
Sc::ConstraintSim::ConstraintSim(ConstraintCore& core, RigidCore* r0, RigidCore* r1, Scene& scene) :
|
||||
mScene (scene),
|
||||
mCore (core),
|
||||
mInteraction(NULL),
|
||||
mFlags (0)
|
||||
{
|
||||
mBodies[0] = (r0 && (r0->getActorCoreType() != PxActorType::eRIGID_STATIC)) ? static_cast<BodySim*>(r0->getSim()) : 0;
|
||||
mBodies[1] = (r1 && (r1->getActorCoreType() != PxActorType::eRIGID_STATIC)) ? static_cast<BodySim*>(r1->getSim()) : 0;
|
||||
|
||||
const PxU32 id = scene.getConstraintIDTracker().createID();
|
||||
|
||||
mLowLevelConstraint.index = id;
|
||||
PxPinnedArray<Dy::ConstraintWriteback>& writeBackPool = scene.getDynamicsContext()->getConstraintWriteBackPool();
|
||||
if(id >= writeBackPool.capacity())
|
||||
writeBackPool.reserve(writeBackPool.capacity() * 2);
|
||||
|
||||
writeBackPool.resize(PxMax(writeBackPool.size(), id + 1));
|
||||
writeBackPool[id].initialize();
|
||||
|
||||
if(!createLLConstraint())
|
||||
return;
|
||||
|
||||
PxReal linBreakForce, angBreakForce;
|
||||
core.getBreakForce(linBreakForce, angBreakForce);
|
||||
if ((linBreakForce < PX_MAX_F32) || (angBreakForce < PX_MAX_F32))
|
||||
setFlag(eBREAKABLE);
|
||||
|
||||
core.setSim(this);
|
||||
|
||||
mInteraction = createInteraction(this, r0, r1, scene);
|
||||
|
||||
PX_ASSERT(!mInteraction->isRegistered()); // constraint interactions must not register in the scene, there is a list of Sc::ConstraintSim instead
|
||||
}
|
||||
|
||||
Sc::ConstraintSim::~ConstraintSim()
|
||||
{
|
||||
PX_ASSERT(mInteraction); // This is fine now, a body which gets removed from the scene removes all constraints automatically
|
||||
PX_ASSERT(!mInteraction->isRegistered()); // constraint interactions must not register in the scene, there is a list of Sc::ConstraintSim instead
|
||||
|
||||
releaseInteraction(mInteraction, this, mScene);
|
||||
|
||||
mScene.getConstraintIDTracker().releaseID(mLowLevelConstraint.index);
|
||||
destroyLLConstraint();
|
||||
|
||||
mCore.setSim(NULL);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void setLLBodies(Dy::Constraint& c, BodySim* b0, BodySim* b1)
|
||||
{
|
||||
PxsRigidBody* body0 = b0 ? &b0->getLowLevelBody() : NULL;
|
||||
PxsRigidBody* body1 = b1 ? &b1->getLowLevelBody() : NULL;
|
||||
|
||||
c.body0 = body0;
|
||||
c.body1 = body1;
|
||||
|
||||
c.bodyCore0 = body0 ? &body0->getCore() : NULL;
|
||||
c.bodyCore1 = body1 ? &body1->getCore() : NULL;
|
||||
}
|
||||
|
||||
bool Sc::ConstraintSim::createLLConstraint()
|
||||
{
|
||||
ConstraintCore& core = getCore();
|
||||
const PxU32 constantBlockSize = core.getConstantBlockSize();
|
||||
|
||||
void* constantBlock = mScene.allocateConstraintBlock(constantBlockSize);
|
||||
if(!constantBlock)
|
||||
return PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL, "Constraint: could not allocate low-level resources.");
|
||||
|
||||
//Ensure the constant block isn't just random data because some functions may attempt to use it before it is
|
||||
//setup. Specifically pvd visualization of joints
|
||||
//-CN
|
||||
|
||||
PxMemZero(constantBlock, constantBlockSize);
|
||||
|
||||
Dy::Constraint& llc = mLowLevelConstraint;
|
||||
core.getBreakForce(llc.linBreakForce, llc.angBreakForce);
|
||||
llc.flags = core.getFlags();
|
||||
llc.constantBlockSize = PxU16(constantBlockSize);
|
||||
|
||||
llc.solverPrep = core.getSolverPrep();
|
||||
llc.constantBlock = constantBlock;
|
||||
llc.minResponseThreshold = core.getMinResponseThreshold();
|
||||
|
||||
//llc.index = mLowLevelConstraint.index;
|
||||
setLLBodies(llc, mBodies[0], mBodies[1]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sc::ConstraintSim::destroyLLConstraint()
|
||||
{
|
||||
if(mLowLevelConstraint.constantBlock)
|
||||
mScene.deallocateConstraintBlock(mLowLevelConstraint.constantBlock, mLowLevelConstraint.constantBlockSize);
|
||||
}
|
||||
|
||||
void Sc::ConstraintSim::setBodies(RigidCore* r0, RigidCore* r1)
|
||||
{
|
||||
PX_ASSERT(mInteraction);
|
||||
|
||||
mScene.removeConstraintFromMap(*mInteraction);
|
||||
|
||||
releaseInteraction(mInteraction, this, mScene);
|
||||
|
||||
BodySim* b0 = (r0 && (r0->getActorCoreType() != PxActorType::eRIGID_STATIC)) ? static_cast<BodySim*>(r0->getSim()) : 0;
|
||||
BodySim* b1 = (r1 && (r1->getActorCoreType() != PxActorType::eRIGID_STATIC)) ? static_cast<BodySim*>(r1->getSim()) : 0;
|
||||
|
||||
setLLBodies(mLowLevelConstraint, b0, b1);
|
||||
|
||||
mBodies[0] = b0;
|
||||
mBodies[1] = b1;
|
||||
|
||||
mInteraction = createInteraction(this, r0, r1, mScene);
|
||||
|
||||
mScene.addConstraintToMap(mCore, r0, r1);
|
||||
}
|
||||
|
||||
void Sc::ConstraintSim::getForce(PxVec3& lin, PxVec3& ang)
|
||||
{
|
||||
const PxReal recipDt = mScene.getOneOverDt();
|
||||
Dy::ConstraintWriteback& solverOutput = mScene.getDynamicsContext()->getConstraintWriteBackPool()[mLowLevelConstraint.index];
|
||||
lin = solverOutput.linearImpulse * recipDt;
|
||||
ang = solverOutput.angularImpulse * recipDt;
|
||||
}
|
||||
|
||||
void Sc::ConstraintSim::setBreakForceLL(PxReal linear, PxReal angular)
|
||||
{
|
||||
PxU8 wasBreakable = readFlag(eBREAKABLE);
|
||||
PxU8 isBreakable;
|
||||
if ((linear < PX_MAX_F32) || (angular < PX_MAX_F32))
|
||||
isBreakable = eBREAKABLE;
|
||||
else
|
||||
isBreakable = 0;
|
||||
|
||||
if (isBreakable != wasBreakable)
|
||||
{
|
||||
if (isBreakable)
|
||||
{
|
||||
PX_ASSERT(!readFlag(eCHECK_MAX_FORCE_EXCEEDED));
|
||||
setFlag(eBREAKABLE);
|
||||
if (mInteraction->readInteractionFlag(InteractionFlag::eIS_ACTIVE))
|
||||
mScene.addActiveBreakableConstraint(this, mInteraction);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (readFlag(eCHECK_MAX_FORCE_EXCEEDED))
|
||||
mScene.removeActiveBreakableConstraint(this);
|
||||
clearFlag(eBREAKABLE);
|
||||
}
|
||||
}
|
||||
|
||||
mLowLevelConstraint.linBreakForce = linear;
|
||||
mLowLevelConstraint.angBreakForce = angular;
|
||||
}
|
||||
|
||||
void Sc::ConstraintSim::postFlagChange(PxConstraintFlags /*oldFlags*/, PxConstraintFlags newFlags)
|
||||
{
|
||||
mLowLevelConstraint.flags = newFlags;
|
||||
}
|
||||
|
||||
PxConstraintGPUIndex Sc::ConstraintSim::getGPUIndex() const
|
||||
{
|
||||
//
|
||||
// The constraint ID is used as GPU index
|
||||
//
|
||||
|
||||
if (mLowLevelConstraint.flags & PxConstraintFlag::eGPU_COMPATIBLE)
|
||||
{
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(Dy::Constraint::index) <= sizeof(PxConstraintGPUIndex));
|
||||
return static_cast<PxConstraintGPUIndex>(mLowLevelConstraint.index);
|
||||
}
|
||||
else
|
||||
return PX_INVALID_CONSTRAINT_GPU_INDEX;
|
||||
}
|
||||
102
engine/third_party/physx/source/simulationcontroller/src/ScConstraintSim.h
vendored
Normal file
102
engine/third_party/physx/source/simulationcontroller/src/ScConstraintSim.h
vendored
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-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_CONSTRAINT_SIM_H
|
||||
#define SC_CONSTRAINT_SIM_H
|
||||
|
||||
#include "foundation/PxArray.h"
|
||||
#include "PxSimulationEventCallback.h"
|
||||
#include "DyConstraint.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class Scene;
|
||||
class ConstraintInteraction;
|
||||
class ConstraintCore;
|
||||
class RigidCore;
|
||||
class BodySim;
|
||||
class RigidSim;
|
||||
|
||||
class ConstraintSim
|
||||
{
|
||||
PX_NOCOPY(ConstraintSim)
|
||||
public:
|
||||
enum Enum
|
||||
{
|
||||
eBREAKABLE = (1<<1), // The constraint can break
|
||||
eCHECK_MAX_FORCE_EXCEEDED = (1<<2), // This constraint will get tested for breakage at the end of the sim step
|
||||
eBROKEN = (1<<3)
|
||||
};
|
||||
ConstraintSim(ConstraintCore& core, RigidCore* r0, RigidCore* r1, Scene& scene);
|
||||
~ConstraintSim();
|
||||
|
||||
void setBodies(RigidCore* r0, RigidCore* r1);
|
||||
|
||||
void setBreakForceLL(PxReal linear, PxReal angular);
|
||||
PX_FORCE_INLINE void setMinResponseThresholdLL(PxReal threshold) { mLowLevelConstraint.minResponseThreshold = threshold; }
|
||||
PX_FORCE_INLINE const void* getConstantsLL() const { return mLowLevelConstraint.constantBlock; }
|
||||
|
||||
void postFlagChange(PxConstraintFlags oldFlags, PxConstraintFlags newFlags);
|
||||
|
||||
PX_FORCE_INLINE const Dy::Constraint& getLowLevelConstraint() const { return mLowLevelConstraint; }
|
||||
PX_FORCE_INLINE Dy::Constraint& getLowLevelConstraint() { return mLowLevelConstraint; }
|
||||
PX_FORCE_INLINE ConstraintCore& getCore() const { return mCore; }
|
||||
PX_FORCE_INLINE BodySim* getBody(PxU32 i) const // for static actors or world attached constraints NULL is returned
|
||||
{
|
||||
return mBodies[i];
|
||||
}
|
||||
|
||||
void getForce(PxVec3& force, PxVec3& torque);
|
||||
|
||||
PX_FORCE_INLINE PxU8 readFlag(PxU8 flag) const { return PxU8(mFlags & flag); }
|
||||
PX_FORCE_INLINE void setFlag(PxU8 flag) { mFlags |= flag; }
|
||||
PX_FORCE_INLINE void clearFlag(PxU8 flag) { mFlags &= ~flag; }
|
||||
PX_FORCE_INLINE PxU32 isBroken() const { return PxU32(mFlags) & ConstraintSim::eBROKEN; }
|
||||
|
||||
PX_FORCE_INLINE const ConstraintInteraction* getInteraction() const { return mInteraction; }
|
||||
|
||||
PxConstraintGPUIndex getGPUIndex() const;
|
||||
|
||||
private:
|
||||
bool createLLConstraint();
|
||||
void destroyLLConstraint();
|
||||
|
||||
Dy::Constraint mLowLevelConstraint;
|
||||
Scene& mScene;
|
||||
ConstraintCore& mCore;
|
||||
ConstraintInteraction* mInteraction; // PT: why do we have an interaction object here?
|
||||
BodySim* mBodies[2];
|
||||
PxU8 mFlags;
|
||||
};
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
172
engine/third_party/physx/source/simulationcontroller/src/ScContactReportBuffer.h
vendored
Normal file
172
engine/third_party/physx/source/simulationcontroller/src/ScContactReportBuffer.h
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_CONTACT_REPORT_BUFFER_H
|
||||
#define SC_CONTACT_REPORT_BUFFER_H
|
||||
|
||||
#include "common/PxProfileZone.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class ContactReportBuffer
|
||||
{
|
||||
public:
|
||||
PX_FORCE_INLINE ContactReportBuffer(PxU32 initialSize, bool noResizeAllowed)
|
||||
: mBuffer(NULL)
|
||||
,mCurrentBufferIndex(0)
|
||||
,mCurrentBufferSize(initialSize)
|
||||
,mDefaultBufferSize(initialSize)
|
||||
,mLastBufferIndex(0)
|
||||
,mAllocationLocked(noResizeAllowed)
|
||||
{
|
||||
mBuffer = allocateBuffer(initialSize);
|
||||
PX_ASSERT(mBuffer);
|
||||
}
|
||||
|
||||
~ContactReportBuffer()
|
||||
{
|
||||
PX_FREE(mBuffer);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void reset();
|
||||
PX_FORCE_INLINE void flush();
|
||||
|
||||
PX_FORCE_INLINE PxU8* allocateNotThreadSafe(PxU32 size, PxU32& index, PxU32 alignment = 16);
|
||||
PX_FORCE_INLINE PxU8* reallocateNotThreadSafe(PxU32 size, PxU32& index, PxU32 alignment = 16, PxU32 lastIndex = 0xFFFFFFFF);
|
||||
PX_FORCE_INLINE PxU8* getData(const PxU32& index) const { return mBuffer+index; }
|
||||
|
||||
PX_FORCE_INLINE PxU32 getDefaultBufferSize() const {return mDefaultBufferSize;}
|
||||
|
||||
private:
|
||||
PX_FORCE_INLINE PxU8* allocateBuffer(PxU32 size);
|
||||
|
||||
private:
|
||||
PxU8* mBuffer;
|
||||
PxU32 mCurrentBufferIndex;
|
||||
PxU32 mCurrentBufferSize;
|
||||
PxU32 mDefaultBufferSize;
|
||||
PxU32 mLastBufferIndex;
|
||||
bool mAllocationLocked;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PX_FORCE_INLINE void Sc::ContactReportBuffer::reset()
|
||||
{
|
||||
mCurrentBufferIndex = 0;
|
||||
mLastBufferIndex = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Sc::ContactReportBuffer::flush()
|
||||
{
|
||||
mCurrentBufferIndex = 0;
|
||||
mLastBufferIndex = 0xFFFFFFFF;
|
||||
|
||||
if(mCurrentBufferSize != mDefaultBufferSize)
|
||||
{
|
||||
PX_FREE(mBuffer);
|
||||
|
||||
mBuffer = allocateBuffer(mDefaultBufferSize);
|
||||
PX_ASSERT(mBuffer);
|
||||
|
||||
mCurrentBufferSize = mDefaultBufferSize;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxU8* Sc::ContactReportBuffer::allocateNotThreadSafe(PxU32 size, PxU32& index ,PxU32 alignment/* =16 */)
|
||||
{
|
||||
PX_ASSERT(PxIsPowerOfTwo(alignment));
|
||||
|
||||
// padding for alignment
|
||||
PxU32 pad = ((mCurrentBufferIndex+alignment-1)&~(alignment-1)) - mCurrentBufferIndex;
|
||||
|
||||
index = mCurrentBufferIndex + pad;
|
||||
|
||||
if (index + size > mCurrentBufferSize)
|
||||
{
|
||||
PX_PROFILE_ZONE("ContactReportBuffer::Resize", 0);
|
||||
if(mAllocationLocked)
|
||||
return NULL;
|
||||
|
||||
PxU32 oldBufferSize = mCurrentBufferSize;
|
||||
while(index + size > mCurrentBufferSize)
|
||||
{
|
||||
mCurrentBufferSize *= 2;
|
||||
}
|
||||
|
||||
PxU8* tempBuffer = allocateBuffer(mCurrentBufferSize);
|
||||
|
||||
PxMemCopy(tempBuffer,mBuffer,oldBufferSize);
|
||||
|
||||
PX_FREE(mBuffer);
|
||||
|
||||
mBuffer = tempBuffer;
|
||||
}
|
||||
|
||||
|
||||
PxU8* ptr = mBuffer + index;
|
||||
mLastBufferIndex = index;
|
||||
PX_ASSERT((size_t(ptr)&(alignment-1)) == 0);
|
||||
mCurrentBufferIndex += size + pad;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxU8* Sc::ContactReportBuffer::reallocateNotThreadSafe(PxU32 size, PxU32& index ,PxU32 alignment/* =16 */, PxU32 lastIndex)
|
||||
{
|
||||
if(lastIndex != mLastBufferIndex)
|
||||
{
|
||||
return allocateNotThreadSafe(size,index,alignment);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCurrentBufferIndex = mLastBufferIndex;
|
||||
return allocateNotThreadSafe(size,index,alignment);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PX_FORCE_INLINE PxU8* Sc::ContactReportBuffer::allocateBuffer(PxU32 size)
|
||||
{
|
||||
return (static_cast<PxU8*>(PX_ALLOC(size, "ContactReportBuffer")));
|
||||
}
|
||||
|
||||
} // namespace physx
|
||||
|
||||
#endif
|
||||
|
||||
401
engine/third_party/physx/source/simulationcontroller/src/ScContactStream.h
vendored
Normal file
401
engine/third_party/physx/source/simulationcontroller/src/ScContactStream.h
vendored
Normal file
@@ -0,0 +1,401 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_CONTACT_STREAM_H
|
||||
#define SC_CONTACT_STREAM_H
|
||||
|
||||
#include "PxSimulationEventCallback.h"
|
||||
#include "ScObjectIDTracker.h"
|
||||
#include "ScRigidSim.h"
|
||||
#include "ScStaticSim.h"
|
||||
#include "ScBodySim.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxShape;
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
class ActorPair;
|
||||
|
||||
|
||||
// Internal counterpart of PxContactPair
|
||||
struct ContactShapePair
|
||||
{
|
||||
public:
|
||||
PxShape* shapes[2];
|
||||
const PxU8* contactPatches;
|
||||
const PxU8* contactPoints;
|
||||
const PxReal* contactForces;
|
||||
const PxU8* frictionPatches;
|
||||
PxU32 requiredBufferSize;
|
||||
PxU8 contactCount;
|
||||
PxU8 patchCount;
|
||||
PxU16 constraintStreamSize;
|
||||
PxU16 flags;
|
||||
PxU16 events;
|
||||
PxU32 shapeID[2];
|
||||
//38 on 64bit
|
||||
};
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(ContactShapePair) == sizeof(PxContactPair));
|
||||
|
||||
struct ContactStreamManagerFlag
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
/**
|
||||
\brief Need to test stream for shapes that were removed from the actor/scene
|
||||
|
||||
Usually this is the case when a shape gets removed from the scene, however, other operations that remove the
|
||||
broadphase volume of a pair object have to be considered as well since the shape might get removed later after such an
|
||||
operation. The scenarios to consider are:
|
||||
|
||||
\li shape gets removed (this includes raising PxActorFlag::eDISABLE_SIMULATION)
|
||||
\li shape switches to eSCENE_QUERY_SHAPE only
|
||||
\li shape switches to eTRIGGER_SHAPE
|
||||
\li resetFiltering()
|
||||
\li actor gets removed from an aggregate
|
||||
|
||||
*/
|
||||
eTEST_FOR_REMOVED_SHAPES = (1<<0),
|
||||
|
||||
/**
|
||||
\brief Invalid stream memory not allocated
|
||||
*/
|
||||
eINVALID_STREAM = (1<<1),
|
||||
|
||||
/**
|
||||
\brief Incomplete stream will be reported
|
||||
*/
|
||||
eINCOMPLETE_STREAM = (1<<2),
|
||||
|
||||
/**
|
||||
\brief The stream contains extra data with PxContactPairVelocity items where the post solver velocity needs to get written to.
|
||||
Only valid for discrete collision (in CCD the post response velocity is available immediately).
|
||||
*/
|
||||
eNEEDS_POST_SOLVER_VELOCITY = (1<<3),
|
||||
|
||||
/**
|
||||
\brief Marker for the next available free flag
|
||||
*/
|
||||
eNEXT_FREE_FLAG = (1<<4)
|
||||
};
|
||||
};
|
||||
|
||||
struct ContactStreamHeader
|
||||
{
|
||||
PxU16 contactPass; // marker for extra data to know when a new collison pass started (discrete collision -> CCD pass 1 -> CCD pass 2 -> ...)
|
||||
PxU16 pad; // to keep the stream 4byte aligned
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Contact report logic and data management.
|
||||
|
||||
The internal contact report stream has the following format:
|
||||
|
||||
ContactStreamHeader | PxContactPairIndex0 | (PxContactPairPose0, PxContactPairVelocity0) | ... | PxContactPairIndexN | (PxContactPairPoseN, PxContactPairVelocityN) | (unused memory up to maxExtraDataSize ) |
|
||||
PxContactPair0 | ... | PxContactPairM | (unsued pairs up to maxPairCount)
|
||||
*/
|
||||
class ContactStreamManager
|
||||
{
|
||||
public:
|
||||
PX_FORCE_INLINE ContactStreamManager() : maxPairCount(0), flags_and_maxExtraDataBlocks(0) {}
|
||||
PX_FORCE_INLINE ~ContactStreamManager() {}
|
||||
|
||||
PX_FORCE_INLINE void reset();
|
||||
|
||||
PX_FORCE_INLINE PxU16 getFlags() const;
|
||||
PX_FORCE_INLINE void raiseFlags(PxU16 flags);
|
||||
PX_FORCE_INLINE void clearFlags(PxU16 flags);
|
||||
|
||||
PX_FORCE_INLINE PxU32 getMaxExtraDataSize() const;
|
||||
PX_FORCE_INLINE void setMaxExtraDataSize(PxU32 size); // size in bytes (will translate into blocks internally)
|
||||
|
||||
PX_FORCE_INLINE Sc::ContactShapePair* getShapePairs(PxU8* contactReportPairData) const;
|
||||
|
||||
PX_FORCE_INLINE static void convertDeletedShapesInContactStream(ContactShapePair*, PxU32 pairCount, const ObjectIDTracker&);
|
||||
|
||||
PX_FORCE_INLINE static PxU32 computeExtraDataBlockCount(PxU32 extraDataSize);
|
||||
PX_FORCE_INLINE static PxU32 computeExtraDataBlockSize(PxU32 extraDataSize);
|
||||
PX_FORCE_INLINE static PxU16 computeContactReportExtraDataSize(PxU32 extraDataFlags, bool addHeader);
|
||||
PX_FORCE_INLINE static void fillInContactReportExtraData(PxContactPairVelocity*, PxU32 index, const ActorSim&, bool isCCDPass);
|
||||
PX_FORCE_INLINE static void fillInContactReportExtraData(PxContactPairPose*, PxU32 index, const ActorSim&, bool isCCDPass, const bool useCurrentTransform);
|
||||
PX_FORCE_INLINE void fillInContactReportExtraData(PxU8* stream, PxU32 extraDataFlags, const ActorSim&, const ActorSim&, PxU32 ccdPass, const bool useCurrentTransform, PxU32 pairIndex, PxU32 sizeOffset);
|
||||
PX_FORCE_INLINE void setContactReportPostSolverVelocity(PxU8* stream, const ActorSim&, const ActorSim&);
|
||||
|
||||
PxU32 bufferIndex; // marks the start of the shape pair stream of the actor pair (byte offset with respect to global contact buffer stream)
|
||||
PxU32 maxPairCount; // used to reserve the same amount of memory as in the last frame (as an initial guess)
|
||||
PxU32 currentPairCount; // number of shape pairs stored in the buffer
|
||||
PxU16 extraDataSize; // size of the extra data section in the stream
|
||||
private:
|
||||
PxU16 flags_and_maxExtraDataBlocks; // used to reserve the same amount of memory as in the last frame (as an initial guess)
|
||||
|
||||
public:
|
||||
static const PxU32 sExtraDataBlockSizePow2 = 4; // extra data gets allocated as a multiple of 2^sExtraDataBlockSizePow2 to keep memory low of this struct.
|
||||
static const PxU32 sFlagMask = (ContactStreamManagerFlag::eNEXT_FREE_FLAG - 1);
|
||||
static const PxU32 sMaxExtraDataShift = 4; // shift necessary to extract the maximum number of blocks allocated for extra data
|
||||
|
||||
PX_COMPILE_TIME_ASSERT(ContactStreamManagerFlag::eNEXT_FREE_FLAG == (1 << sMaxExtraDataShift));
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
|
||||
PX_FORCE_INLINE void Sc::ContactStreamManager::reset()
|
||||
{
|
||||
currentPairCount = 0;
|
||||
extraDataSize = 0;
|
||||
flags_and_maxExtraDataBlocks &= ~sFlagMask;
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE PxU16 Sc::ContactStreamManager::getFlags() const
|
||||
{
|
||||
return (flags_and_maxExtraDataBlocks & sFlagMask);
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE void Sc::ContactStreamManager::raiseFlags(PxU16 flags)
|
||||
{
|
||||
PX_ASSERT(flags < ContactStreamManagerFlag::eNEXT_FREE_FLAG);
|
||||
|
||||
flags_and_maxExtraDataBlocks |= flags;
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE void Sc::ContactStreamManager::clearFlags(PxU16 flags)
|
||||
{
|
||||
PX_ASSERT(flags < ContactStreamManagerFlag::eNEXT_FREE_FLAG);
|
||||
|
||||
PxU16 tmpFlags = getFlags();
|
||||
tmpFlags &= ~flags;
|
||||
flags_and_maxExtraDataBlocks &= ~sFlagMask;
|
||||
raiseFlags(tmpFlags);
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE PxU32 Sc::ContactStreamManager::getMaxExtraDataSize() const
|
||||
{
|
||||
return PxU32((flags_and_maxExtraDataBlocks >> sMaxExtraDataShift) << sExtraDataBlockSizePow2);
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE void Sc::ContactStreamManager::setMaxExtraDataSize(PxU32 size)
|
||||
{
|
||||
const PxU32 nbBlocks = computeExtraDataBlockCount(size);
|
||||
flags_and_maxExtraDataBlocks = PxTo16((flags_and_maxExtraDataBlocks & sFlagMask) | (nbBlocks << sMaxExtraDataShift));
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE Sc::ContactShapePair* Sc::ContactStreamManager::getShapePairs(PxU8* contactReportPairData) const
|
||||
{
|
||||
return reinterpret_cast<Sc::ContactShapePair*>(contactReportPairData + getMaxExtraDataSize());
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE void Sc::ContactStreamManager::convertDeletedShapesInContactStream(ContactShapePair* shapePairs, PxU32 pairCount, const ObjectIDTracker& tracker)
|
||||
{
|
||||
for(PxU32 i=0; i < pairCount; i++)
|
||||
{
|
||||
ContactShapePair& csp = shapePairs[i];
|
||||
|
||||
PxU32 shape0ID = csp.shapeID[0];
|
||||
PxU32 shape1ID = csp.shapeID[1];
|
||||
|
||||
PxU16 flags = csp.flags;
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(flags) == sizeof((reinterpret_cast<ContactShapePair*>(0))->flags));
|
||||
|
||||
if (tracker.isDeletedID(shape0ID))
|
||||
flags |= PxContactPairFlag::eREMOVED_SHAPE_0;
|
||||
if (tracker.isDeletedID(shape1ID))
|
||||
flags |= PxContactPairFlag::eREMOVED_SHAPE_1;
|
||||
|
||||
csp.flags = flags;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE PxU32 Sc::ContactStreamManager::computeExtraDataBlockCount(PxU32 extraDataSize_)
|
||||
{
|
||||
PxU32 nbBlocks;
|
||||
if (extraDataSize_ & ((1 << sExtraDataBlockSizePow2) - 1)) // not a multiple of block size -> need one block more
|
||||
nbBlocks = (extraDataSize_ >> sExtraDataBlockSizePow2) + 1;
|
||||
else
|
||||
nbBlocks = (extraDataSize_ >> sExtraDataBlockSizePow2);
|
||||
|
||||
return nbBlocks;
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE PxU32 Sc::ContactStreamManager::computeExtraDataBlockSize(PxU32 extraDataSize_)
|
||||
{
|
||||
return (computeExtraDataBlockCount(extraDataSize_) << sExtraDataBlockSizePow2);
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE PxU16 Sc::ContactStreamManager::computeContactReportExtraDataSize(PxU32 extraDataFlags, bool addHeader)
|
||||
{
|
||||
PX_ASSERT(extraDataFlags);
|
||||
|
||||
PxU16 extraDataSize_ = sizeof(PxContactPairIndex);
|
||||
if (extraDataFlags & PxPairFlag::ePRE_SOLVER_VELOCITY)
|
||||
extraDataSize_ += sizeof(PxContactPairVelocity);
|
||||
if (extraDataFlags & PxPairFlag::ePOST_SOLVER_VELOCITY)
|
||||
extraDataSize_ += sizeof(PxContactPairVelocity);
|
||||
if (extraDataFlags & PxPairFlag::eCONTACT_EVENT_POSE)
|
||||
extraDataSize_ += sizeof(PxContactPairPose);
|
||||
if (addHeader)
|
||||
extraDataSize_ += sizeof(ContactStreamHeader);
|
||||
return extraDataSize_;
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE void Sc::ContactStreamManager::fillInContactReportExtraData(PxContactPairVelocity* cpVel, PxU32 index, const ActorSim& rs, bool isCCDPass)
|
||||
{
|
||||
if (rs.getActorType() != PxActorType::eRIGID_STATIC)
|
||||
{
|
||||
const BodySim& bs = static_cast<const BodySim&>(rs);
|
||||
if ((!isCCDPass) || (cpVel->type == PxContactPairExtraDataType::ePOST_SOLVER_VELOCITY))
|
||||
{
|
||||
const BodyCore& bc = bs.getBodyCore();
|
||||
cpVel->linearVelocity[index] = bc.getLinearVelocity();
|
||||
cpVel->angularVelocity[index] = bc.getAngularVelocity();
|
||||
}
|
||||
else
|
||||
{
|
||||
PX_ASSERT(cpVel->type == PxContactPairExtraDataType::ePRE_SOLVER_VELOCITY);
|
||||
const Cm::SpatialVector& vel = bs.getLowLevelBody().getPreSolverVelocities();
|
||||
cpVel->linearVelocity[index] = vel.linear;
|
||||
cpVel->angularVelocity[index] = vel.angular;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cpVel->linearVelocity[index] = PxVec3(0.0f);
|
||||
cpVel->angularVelocity[index] = PxVec3(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE void Sc::ContactStreamManager::fillInContactReportExtraData(PxContactPairPose* cpPose, PxU32 index, const ActorSim& rs, bool isCCDPass, const bool useCurrentTransform)
|
||||
{
|
||||
if(rs.getActorType() != PxActorType::eRIGID_STATIC)
|
||||
{
|
||||
const BodySim& bs = static_cast<const BodySim&>(rs);
|
||||
const BodyCore& bc = bs.getBodyCore();
|
||||
const PxTransform& src = (!isCCDPass && useCurrentTransform) ? bc.getBody2World() : bs.getLowLevelBody().getLastCCDTransform();
|
||||
// PT:: tag: scalar transform*transform
|
||||
cpPose->globalPose[index] = src * bc.getBody2Actor().getInverse();
|
||||
}
|
||||
else
|
||||
{
|
||||
const StaticSim& ss = static_cast<const StaticSim&>(rs);
|
||||
const StaticCore& sc = ss.getStaticCore();
|
||||
cpPose->globalPose[index] = sc.getActor2World();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE void Sc::ContactStreamManager::fillInContactReportExtraData(PxU8* stream, PxU32 extraDataFlags, const ActorSim& rs0, const ActorSim& rs1, PxU32 ccdPass, const bool useCurrentTransform,
|
||||
PxU32 pairIndex, PxU32 sizeOffset)
|
||||
{
|
||||
ContactStreamHeader* strHeader = reinterpret_cast<ContactStreamHeader*>(stream);
|
||||
strHeader->contactPass = PxTo16(ccdPass);
|
||||
|
||||
stream += sizeOffset;
|
||||
PxU8* edStream = stream;
|
||||
bool isCCDPass = (ccdPass != 0);
|
||||
|
||||
{
|
||||
PxContactPairIndex* cpIndex = reinterpret_cast<PxContactPairIndex*>(edStream);
|
||||
cpIndex->type = PxContactPairExtraDataType::eCONTACT_PAIR_INDEX;
|
||||
cpIndex->index = PxTo16(pairIndex);
|
||||
edStream += sizeof(PxContactPairIndex);
|
||||
|
||||
PX_ASSERT(edStream <= reinterpret_cast<PxU8*>(getShapePairs(stream)));
|
||||
}
|
||||
|
||||
// Important: make sure this one is the first after the PxContactPairIndex item for discrete contacts as it needs to get filled in before the reports get sent
|
||||
// (post solver velocity is not available when it gets created)
|
||||
if (extraDataFlags & PxPairFlag::ePOST_SOLVER_VELOCITY)
|
||||
{
|
||||
PxContactPairVelocity* cpVel = reinterpret_cast<PxContactPairVelocity*>(edStream);
|
||||
cpVel->type = PxContactPairExtraDataType::ePOST_SOLVER_VELOCITY;
|
||||
edStream += sizeof(PxContactPairVelocity);
|
||||
|
||||
if (!isCCDPass)
|
||||
raiseFlags(ContactStreamManagerFlag::eNEEDS_POST_SOLVER_VELOCITY); // don't know the post solver velocity yet
|
||||
else
|
||||
{
|
||||
ContactStreamManager::fillInContactReportExtraData(cpVel, 0, rs0, true);
|
||||
ContactStreamManager::fillInContactReportExtraData(cpVel, 1, rs1, true);
|
||||
}
|
||||
|
||||
PX_ASSERT(edStream <= reinterpret_cast<PxU8*>(getShapePairs(stream)));
|
||||
}
|
||||
if (extraDataFlags & PxPairFlag::ePRE_SOLVER_VELOCITY)
|
||||
{
|
||||
PxContactPairVelocity* cpVel = reinterpret_cast<PxContactPairVelocity*>(edStream);
|
||||
cpVel->type = PxContactPairExtraDataType::ePRE_SOLVER_VELOCITY;
|
||||
ContactStreamManager::fillInContactReportExtraData(cpVel, 0, rs0, isCCDPass);
|
||||
ContactStreamManager::fillInContactReportExtraData(cpVel, 1, rs1, isCCDPass);
|
||||
edStream += sizeof(PxContactPairVelocity);
|
||||
|
||||
PX_ASSERT(edStream <= reinterpret_cast<PxU8*>(getShapePairs(stream)));
|
||||
}
|
||||
if (extraDataFlags & PxPairFlag::eCONTACT_EVENT_POSE)
|
||||
{
|
||||
PxContactPairPose* cpPose = reinterpret_cast<PxContactPairPose*>(edStream);
|
||||
cpPose->type = PxContactPairExtraDataType::eCONTACT_EVENT_POSE;
|
||||
ContactStreamManager::fillInContactReportExtraData(cpPose, 0, rs0, isCCDPass, useCurrentTransform);
|
||||
ContactStreamManager::fillInContactReportExtraData(cpPose, 1, rs1, isCCDPass, useCurrentTransform);
|
||||
edStream += sizeof(PxContactPairPose);
|
||||
|
||||
PX_ASSERT(edStream <= reinterpret_cast<PxU8*>(getShapePairs(stream)));
|
||||
}
|
||||
|
||||
extraDataSize = PxTo16(sizeOffset + PxU32(edStream - stream));
|
||||
}
|
||||
|
||||
|
||||
PX_FORCE_INLINE void Sc::ContactStreamManager::setContactReportPostSolverVelocity(PxU8* stream, const ActorSim& rs0, const ActorSim& rs1)
|
||||
{
|
||||
PX_ASSERT(extraDataSize > (sizeof(ContactStreamHeader) + sizeof(PxContactPairIndex)));
|
||||
PxContactPairVelocity* cpVel = reinterpret_cast<PxContactPairVelocity*>(stream + sizeof(ContactStreamHeader) + sizeof(PxContactPairIndex));
|
||||
PX_ASSERT(cpVel->type == PxContactPairExtraDataType::ePOST_SOLVER_VELOCITY);
|
||||
|
||||
fillInContactReportExtraData(cpVel, 0, rs0, false);
|
||||
fillInContactReportExtraData(cpVel, 1, rs1, false);
|
||||
|
||||
clearFlags(ContactStreamManagerFlag::eNEEDS_POST_SOLVER_VELOCITY);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
323
engine/third_party/physx/source/simulationcontroller/src/ScDeformableSurfaceCore.cpp
vendored
Normal file
323
engine/third_party/physx/source/simulationcontroller/src/ScDeformableSurfaceCore.cpp
vendored
Normal file
@@ -0,0 +1,323 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
|
||||
#include "ScDeformableSurfaceCore.h"
|
||||
|
||||
#include "ScPhysics.h"
|
||||
#include "ScDeformableSurfaceSim.h"
|
||||
#include "DyDeformableSurface.h"
|
||||
#include "GuTetrahedronMesh.h"
|
||||
#include "GuBV4.h"
|
||||
#include "geometry/PxTetrahedronMesh.h"
|
||||
#include "cudamanager/PxCudaContextManager.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::DeformableSurfaceCore::DeformableSurfaceCore() :
|
||||
ActorCore(PxActorType::eDEFORMABLE_SURFACE, PxActorFlag::eVISUALIZATION, PX_DEFAULT_CLIENT, 0),
|
||||
mGpuMemStat(0)
|
||||
{
|
||||
const PxTolerancesScale& scale = Physics::getInstance().getTolerancesScale();
|
||||
|
||||
// Dy::DeformableCore
|
||||
mCore.sleepThreshold = 5e-5f * scale.speed * scale.speed;
|
||||
mCore.solverIterationCounts = (1 << 8) | 4;
|
||||
mCore.wakeCounter = Physics::sWakeCounterOnCreation;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
Sc::DeformableSurfaceCore::~DeformableSurfaceCore() { }
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PxActor API
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Sc::DeformableSurfaceCore::setActorFlags(PxActorFlags flags)
|
||||
{
|
||||
mCore.actorFlags = flags;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PxDeformableBody API
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Sc::DeformableSurfaceCore::setBodyFlags(PxDeformableBodyFlags flags)
|
||||
{
|
||||
mCore.bodyFlags = flags;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::setLinearDamping(const PxReal v)
|
||||
{
|
||||
mCore.linearDamping = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::setMaxLinearVelocity(const PxReal v)
|
||||
{
|
||||
mCore.maxLinearVelocity = (v > 1e15f) ? PX_MAX_REAL : v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::setMaxPenetrationBias(const PxReal v)
|
||||
{
|
||||
mCore.maxPenetrationBias = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::setSolverIterationCounts(const PxU16 c)
|
||||
{
|
||||
mCore.solverIterationCounts = c;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::setSleepThreshold(const PxReal v)
|
||||
{
|
||||
mCore.sleepThreshold = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::setSettlingThreshold(const PxReal v)
|
||||
{
|
||||
mCore.settlingThreshold = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::setSettlingDamping(const PxReal v)
|
||||
{
|
||||
mCore.settlingDamping = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::setSelfCollisionFilterDistance(const PxReal v)
|
||||
{
|
||||
mCore.selfCollisionFilterDistance = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
//deprecated
|
||||
void Sc::DeformableSurfaceCore::setSelfCollisionStressTolerance(const PxReal v)
|
||||
{
|
||||
mCore.selfCollisionStressTolerance = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::setWakeCounter(const PxReal v)
|
||||
{
|
||||
setWakeCounterInternal(v);
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::setWakeCounterInternal(const PxReal v)
|
||||
{
|
||||
mCore.wakeCounter = v;
|
||||
mCore.dirty = true;
|
||||
|
||||
Sc::DeformableSurfaceSim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
sim->onSetWakeCounter();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PxDeformableSurface API
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Sc::DeformableSurfaceCore::setSurfaceFlags(PxDeformableSurfaceFlags flags)
|
||||
{
|
||||
mCore.surfaceFlags = flags;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::setNbCollisionPairUpdatesPerTimestep(const PxU32 frequency)
|
||||
{
|
||||
mCore.nbCollisionPairUpdatesPerTimestep = frequency;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::setNbCollisionSubsteps(const PxU32 frequency)
|
||||
{
|
||||
mCore.nbCollisionSubsteps = frequency;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Internal API
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PxU32 Sc::DeformableSurfaceCore::addRigidAttachment(Sc::BodyCore* core, PxU32 particleId, const PxVec3& actorSpacePose, PxConeLimitedConstraint* params)
|
||||
{
|
||||
Sc::DeformableSurfaceSim* sim = getSim();
|
||||
PxU32 handle = 0xFFFFFFFF;
|
||||
if (sim)
|
||||
{
|
||||
handle = sim->getScene().addRigidAttachment(core, *sim, particleId, actorSpacePose, params);
|
||||
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::removeRigidAttachment(Sc::BodyCore* core, PxU32 handle)
|
||||
{
|
||||
Sc::DeformableSurfaceSim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
sim->getScene().removeRigidAttachment(core, *sim, handle);
|
||||
setWakeCounterInternal(ScInternalWakeCounterResetValue);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::addTriRigidFilter(Sc::BodyCore* core, PxU32 triIdx)
|
||||
{
|
||||
Sc::DeformableSurfaceSim* sim = getSim();
|
||||
|
||||
if (sim)
|
||||
sim->getScene().addTriRigidFilter(core, *sim, triIdx);
|
||||
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::removeTriRigidFilter(Sc::BodyCore* core, PxU32 triIdx)
|
||||
{
|
||||
Sc::DeformableSurfaceSim* sim = getSim();
|
||||
if (sim)
|
||||
sim->getScene().removeTriRigidFilter(core, *sim, triIdx);
|
||||
}
|
||||
|
||||
|
||||
PxU32 Sc::DeformableSurfaceCore::addTriRigidAttachment(Sc::BodyCore* core, PxU32 triIdx, const PxVec4& barycentric, const PxVec3& actorSpacePose, PxConeLimitedConstraint* constraint)
|
||||
{
|
||||
Sc::DeformableSurfaceSim* sim = getSim();
|
||||
PxU32 handle = 0xFFFFFFFF;
|
||||
if (sim)
|
||||
handle = sim->getScene().addTriRigidAttachment(core, *sim, triIdx, barycentric, actorSpacePose, constraint);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::removeTriRigidAttachment(Sc::BodyCore* core, PxU32 handle)
|
||||
{
|
||||
Sc::DeformableSurfaceSim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
sim->getScene().removeTriRigidAttachment(core, *sim, handle);
|
||||
setWakeCounterInternal(ScInternalWakeCounterResetValue);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::addClothFilter(Sc::DeformableSurfaceCore* otherCore, PxU32 otherTriIdx, PxU32 triIdx)
|
||||
{
|
||||
Sc::DeformableSurfaceSim* sim = getSim();
|
||||
if (sim)
|
||||
sim->getScene().addClothFilter(*otherCore, otherTriIdx, *sim, triIdx);
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::removeClothFilter(Sc::DeformableSurfaceCore* otherCore, PxU32 otherTriIdx, PxU32 triIdx)
|
||||
{
|
||||
Sc::DeformableSurfaceSim* sim = getSim();
|
||||
if (sim)
|
||||
sim->getScene().removeClothFilter(*otherCore, otherTriIdx, *sim, triIdx);
|
||||
}
|
||||
|
||||
PxU32 Sc::DeformableSurfaceCore::addClothAttachment(Sc::DeformableSurfaceCore* otherCore, PxU32 otherTriIdx, const PxVec4& otherTriBarycentric, PxU32 triIdx, const PxVec4& triBarycentric)
|
||||
{
|
||||
Sc::DeformableSurfaceSim* sim = getSim();
|
||||
PxU32 handle = 0xFFFFFFFF;
|
||||
if (sim)
|
||||
handle = sim->getScene().addTriClothAttachment(*otherCore, otherTriIdx, otherTriBarycentric, *sim, triIdx, triBarycentric);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::removeClothAttachment(Sc::DeformableSurfaceCore* otherCore, PxU32 handle)
|
||||
{
|
||||
Sc::DeformableSurfaceSim* sim = getSim();
|
||||
setWakeCounterInternal(ScInternalWakeCounterResetValue);
|
||||
otherCore->setWakeCounterInternal(ScInternalWakeCounterResetValue);
|
||||
if (sim)
|
||||
sim->getScene().removeTriClothAttachment(*otherCore, *sim, handle);
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::addMaterial(const PxU16 handle)
|
||||
{
|
||||
mCore.materialHandles.pushBack(handle);
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::clearMaterials()
|
||||
{
|
||||
mCore.materialHandles.clear();
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
PxActor* Sc::DeformableSurfaceCore::getPxActor() const
|
||||
{
|
||||
return PxPointerOffset<PxActor*>(const_cast<DeformableSurfaceCore*>(this), gOffsetTable.scCore2PxActor[getActorCoreType()]);
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::attachShapeCore(ShapeCore* shapeCore)
|
||||
{
|
||||
Sc::DeformableSurfaceSim* sim = getSim();
|
||||
if (sim)
|
||||
sim->attachShapeCore(shapeCore);
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceCore::onShapeChange(ShapeCore& shape, ShapeChangeNotifyFlags notifyFlags)
|
||||
{
|
||||
PX_UNUSED(shape);
|
||||
DeformableSurfaceSim* sim = getSim();
|
||||
if (!sim)
|
||||
return;
|
||||
ShapeSimBase& s = sim->getShapeSim();
|
||||
|
||||
if (notifyFlags & ShapeChangeNotifyFlag::eGEOMETRY)
|
||||
s.onVolumeOrTransformChange();
|
||||
if (notifyFlags & ShapeChangeNotifyFlag::eRESET_FILTERING)
|
||||
s.onResetFiltering();
|
||||
if (notifyFlags & ShapeChangeNotifyFlag::eSHAPE2BODY)
|
||||
s.onVolumeOrTransformChange();
|
||||
if (notifyFlags & ShapeChangeNotifyFlag::eFILTERDATA)
|
||||
s.onFilterDataChange();
|
||||
if (notifyFlags & ShapeChangeNotifyFlag::eCONTACTOFFSET)
|
||||
s.onContactOffsetChange();
|
||||
if (notifyFlags & ShapeChangeNotifyFlag::eRESTOFFSET)
|
||||
s.onRestOffsetChange();
|
||||
}
|
||||
|
||||
Sc::DeformableSurfaceSim* Sc::DeformableSurfaceCore::getSim() const
|
||||
{
|
||||
return static_cast<Sc::DeformableSurfaceSim*>(ActorCore::getSim());
|
||||
}
|
||||
|
||||
#endif //PX_SUPPORT_GPU_PHYSX
|
||||
|
||||
102
engine/third_party/physx/source/simulationcontroller/src/ScDeformableSurfaceSim.cpp
vendored
Normal file
102
engine/third_party/physx/source/simulationcontroller/src/ScDeformableSurfaceSim.cpp
vendored
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-2025 NVIDIA Corporation. All rights reserved.
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
|
||||
#include "ScDeformableSurfaceSim.h"
|
||||
|
||||
#include "geometry/PxTriangleMesh.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Dy;
|
||||
|
||||
Sc::DeformableSurfaceSim::DeformableSurfaceSim(DeformableSurfaceCore& core, Scene& scene) :
|
||||
GPUActorSim(scene, core, NULL)
|
||||
{
|
||||
mLLDeformableSurface = scene.createLLDeformableSurface(this);
|
||||
|
||||
mNodeIndex = scene.getSimpleIslandManager()->addNode(false, false, IG::Node::eDEFORMABLE_SURFACE_TYPE, mLLDeformableSurface);
|
||||
|
||||
scene.getSimpleIslandManager()->activateNode(mNodeIndex);
|
||||
|
||||
mLLDeformableSurface->setElementId(mShapeSim.getElementID());
|
||||
}
|
||||
|
||||
Sc::DeformableSurfaceSim::~DeformableSurfaceSim()
|
||||
{
|
||||
if (!mLLDeformableSurface)
|
||||
return;
|
||||
|
||||
mScene.destroyLLDeformableSurface(*mLLDeformableSurface);
|
||||
|
||||
mScene.getSimpleIslandManager()->removeNode(mNodeIndex);
|
||||
|
||||
mCore.setSim(NULL);
|
||||
}
|
||||
|
||||
bool Sc::DeformableSurfaceSim::isSleeping() const
|
||||
{
|
||||
IG::IslandSim& sim = mScene.getSimpleIslandManager()->getAccurateIslandSim();
|
||||
return sim.getActiveNodeIndex(mNodeIndex) == PX_INVALID_NODE;
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceSim::onSetWakeCounter()
|
||||
{
|
||||
mScene.getSimulationController()->setClothWakeCounter(mLLDeformableSurface);
|
||||
if (mLLDeformableSurface->getCore().wakeCounter > 0.f)
|
||||
mScene.getSimpleIslandManager()->activateNode(mNodeIndex);
|
||||
else
|
||||
mScene.getSimpleIslandManager()->deactivateNode(mNodeIndex);
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceSim::attachShapeCore(ShapeCore* core)
|
||||
{
|
||||
mShapeSim.setCore(core);
|
||||
{
|
||||
PX_ASSERT(getWorldBounds().isFinite());
|
||||
|
||||
const PxU32 index = mShapeSim.getElementID();
|
||||
|
||||
mScene.getBoundsArray().setBounds(getWorldBounds(), index);
|
||||
|
||||
addToAABBMgr(Bp::FilterType::DEFORMABLE_SURFACE);
|
||||
}
|
||||
|
||||
PxsShapeCore* shapeCore = const_cast<PxsShapeCore*>(&core->getCore());
|
||||
mLLDeformableSurface->setShapeCore(shapeCore);
|
||||
}
|
||||
|
||||
PxBounds3 Sc::DeformableSurfaceSim::getWorldBounds() const
|
||||
{
|
||||
const PxTriangleMeshGeometry& triGeom = static_cast<const PxTriangleMeshGeometry&>(mShapeSim.getCore().getGeometry());
|
||||
|
||||
// PT: are you sure you want to go through the Px API here?
|
||||
return triGeom.triangleMesh->getLocalBounds();
|
||||
}
|
||||
|
||||
#endif //PX_SUPPORT_GPU_PHYSX
|
||||
78
engine/third_party/physx/source/simulationcontroller/src/ScDeformableSurfaceSim.h
vendored
Normal file
78
engine/third_party/physx/source/simulationcontroller/src/ScDeformableSurfaceSim.h
vendored
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-2025 NVIDIA Corporation. All rights reserved.
|
||||
|
||||
#ifndef SC_DEFORMABLE_SURFACE_SIM_H
|
||||
#define SC_DEFORMABLE_SURFACE_SIM_H
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "DyDeformableSurface.h"
|
||||
#include "ScDeformableSurfaceCore.h"
|
||||
#include "ScGpuActorSim.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
|
||||
class Scene;
|
||||
|
||||
class DeformableSurfaceSim : public GPUActorSim
|
||||
{
|
||||
PX_NOCOPY(DeformableSurfaceSim)
|
||||
public:
|
||||
DeformableSurfaceSim(DeformableSurfaceCore& core, Scene& scene);
|
||||
~DeformableSurfaceSim();
|
||||
|
||||
PX_INLINE Dy::DeformableSurface* getLowLevelDeformableSurface() const { return mLLDeformableSurface; }
|
||||
PX_INLINE DeformableSurfaceCore& getCore() const { return static_cast<DeformableSurfaceCore&>(mCore); }
|
||||
virtual PxActor* getPxActor() const { return getCore().getPxActor(); }
|
||||
|
||||
bool isSleeping() const;
|
||||
PX_FORCE_INLINE bool isActive() const { return !isSleeping(); }
|
||||
|
||||
void setActive(bool active, bool asPartOfCreation=false);
|
||||
|
||||
void onSetWakeCounter();
|
||||
|
||||
void attachShapeCore(ShapeCore* core);
|
||||
PxBounds3 getWorldBounds() const;
|
||||
|
||||
private:
|
||||
Dy::DeformableSurface* mLLDeformableSurface;
|
||||
|
||||
PxU32 mIslandNodeIndex;
|
||||
|
||||
void activate();
|
||||
void deactivate();
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
} // namespace physx
|
||||
|
||||
#endif // PX_SUPPORT_GPU_PHYSX
|
||||
#endif // SC_DEFORMABLE_SURFACE_SIM_H
|
||||
447
engine/third_party/physx/source/simulationcontroller/src/ScDeformableVolumeCore.cpp
vendored
Normal file
447
engine/third_party/physx/source/simulationcontroller/src/ScDeformableVolumeCore.cpp
vendored
Normal file
@@ -0,0 +1,447 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
|
||||
#include "ScDeformableSurfaceCore.h"
|
||||
#include "ScDeformableVolumeCore.h"
|
||||
|
||||
#include "ScPhysics.h"
|
||||
#include "ScDeformableVolumeSim.h"
|
||||
#include "DyDeformableVolume.h"
|
||||
#include "GuTetrahedronMesh.h"
|
||||
#include "GuBV4.h"
|
||||
#include "geometry/PxTetrahedronMesh.h"
|
||||
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::DeformableVolumeCore::DeformableVolumeCore() :
|
||||
ActorCore(PxActorType::eDEFORMABLE_VOLUME, PxActorFlag::eVISUALIZATION, PX_DEFAULT_CLIENT, 0),
|
||||
mGpuMemStat(0)
|
||||
{
|
||||
const PxTolerancesScale& scale = Physics::getInstance().getTolerancesScale();
|
||||
|
||||
// Dy::DeformableCore
|
||||
mCore.sleepThreshold = 5e-5f * scale.speed * scale.speed;
|
||||
mCore.solverIterationCounts = (1 << 8) | 4;
|
||||
mCore.wakeCounter = Physics::sWakeCounterOnCreation;
|
||||
mCore.dirty = true;
|
||||
|
||||
// Dy::DeformableVolumeCore
|
||||
mCore.freezeThreshold = 5e-6f * scale.speed * scale.speed;
|
||||
}
|
||||
|
||||
|
||||
Sc::DeformableVolumeCore::~DeformableVolumeCore() { }
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PxActor API
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Sc::DeformableVolumeCore::setActorFlags(PxActorFlags flags)
|
||||
{
|
||||
mCore.actorFlags = flags;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PxDeformableBody API
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Sc::DeformableVolumeCore::setBodyFlags(PxDeformableBodyFlags flags)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
const bool wasDisabledSelfCollision = mCore.bodyFlags & PxDeformableBodyFlag::eDISABLE_SELF_COLLISION;
|
||||
const bool isDisabledSelfCollision = flags & PxDeformableBodyFlag::eDISABLE_SELF_COLLISION;
|
||||
|
||||
if (wasDisabledSelfCollision != isDisabledSelfCollision)
|
||||
{
|
||||
if (isDisabledSelfCollision)
|
||||
sim->disableSelfCollision();
|
||||
else
|
||||
sim->enableSelfCollision();
|
||||
}
|
||||
}
|
||||
|
||||
mCore.bodyFlags = flags;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::setLinearDamping(const PxReal v)
|
||||
{
|
||||
mCore.linearDamping = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::setMaxLinearVelocity(const PxReal v)
|
||||
{
|
||||
mCore.maxLinearVelocity = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::setMaxPenetrationBias(const PxReal v)
|
||||
{
|
||||
mCore.maxPenetrationBias = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::setSolverIterationCounts(const PxU16 c)
|
||||
{
|
||||
mCore.solverIterationCounts = c;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::setSleepThreshold(const PxReal v)
|
||||
{
|
||||
mCore.sleepThreshold = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::setSettlingThreshold(const PxReal v)
|
||||
{
|
||||
mCore.settlingThreshold = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::setSettlingDamping(const PxReal v)
|
||||
{
|
||||
mCore.settlingDamping = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::setSelfCollisionFilterDistance(const PxReal v)
|
||||
{
|
||||
mCore.selfCollisionFilterDistance = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::setWakeCounter(const PxReal v)
|
||||
{
|
||||
setWakeCounterInternal(v);
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::setWakeCounterInternal(const PxReal v)
|
||||
{
|
||||
mCore.wakeCounter = v;
|
||||
mCore.dirty = true;
|
||||
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
sim->onSetWakeCounter();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PxDeformableVolume API
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Sc::DeformableVolumeCore::setVolumeFlags(PxDeformableVolumeFlags flags)
|
||||
{
|
||||
mCore.volumeFlags = flags;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::setSelfCollisionStressTolerance(const PxReal v)
|
||||
{
|
||||
mCore.selfCollisionStressTolerance = v;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::setKinematicTargets(const PxVec4* positions)
|
||||
{
|
||||
mCore.kinematicTarget = positions;
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
PxU32 Sc::DeformableVolumeCore::getGpuIndex() const
|
||||
{
|
||||
const Sc::DeformableVolumeSim* sim = getSim();
|
||||
return sim ? sim->getGpuIndex() : 0xffffffff;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::addParticleFilter(Sc::ParticleSystemCore* core, PxU32 particleId, PxU32 userBufferId, PxU32 tetId)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
|
||||
if (sim)
|
||||
sim->getScene().addParticleFilter(core, *sim, particleId, userBufferId, tetId);
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::removeParticleFilter(Sc::ParticleSystemCore* core, PxU32 particleId, PxU32 userBufferId, PxU32 tetId)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
|
||||
if (sim)
|
||||
sim->getScene().removeParticleFilter(core, *sim, particleId, userBufferId, tetId);
|
||||
}
|
||||
|
||||
PxU32 Sc::DeformableVolumeCore::addParticleAttachment(Sc::ParticleSystemCore* core, PxU32 particleId, PxU32 userBufferId, PxU32 tetId, const PxVec4& barycentric)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
PxU32 handle = 0xFFFFFFFF;
|
||||
if (sim)
|
||||
handle = sim->getScene().addParticleAttachment(core, *sim, particleId, userBufferId, tetId, barycentric);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::removeParticleAttachment(Sc::ParticleSystemCore* core, PxU32 handle)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
sim->getScene().removeParticleAttachment(core, *sim, handle);
|
||||
setWakeCounterInternal(ScInternalWakeCounterResetValue);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::addRigidFilter(Sc::BodyCore* core, PxU32 vertId)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
|
||||
if (sim)
|
||||
sim->getScene().addRigidFilter(core, *sim, vertId);
|
||||
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::removeRigidFilter(Sc::BodyCore* core, PxU32 vertId)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
sim->getScene().removeRigidFilter(core, *sim, vertId);
|
||||
}
|
||||
|
||||
PxU32 Sc::DeformableVolumeCore::addRigidAttachment(Sc::BodyCore* core, PxU32 particleId, const PxVec3& actorSpacePose, PxConeLimitedConstraint* constraint, bool doConversion)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
PxU32 handle = 0xFFFFFFFF;
|
||||
if(sim)
|
||||
handle = sim->getScene().addRigidAttachment(core, *sim, particleId, actorSpacePose, constraint, doConversion);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::removeRigidAttachment(Sc::BodyCore* core, PxU32 handle)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
sim->getScene().removeRigidAttachment(core, *sim, handle);
|
||||
setWakeCounterInternal(ScInternalWakeCounterResetValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Sc::DeformableVolumeCore::addTetRigidFilter(Sc::BodyCore* core, PxU32 tetIdx)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
sim->getScene().addTetRigidFilter(core, *sim, tetIdx);
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::removeTetRigidFilter(Sc::BodyCore* core, PxU32 tetIdx)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
sim->getScene().removeTetRigidFilter(core, *sim, tetIdx);
|
||||
}
|
||||
}
|
||||
|
||||
PxU32 Sc::DeformableVolumeCore::addTetRigidAttachment(Sc::BodyCore* core, PxU32 tetIdx, const PxVec4& barycentric,
|
||||
const PxVec3& actorSpacePose, PxConeLimitedConstraint* constraint, bool doConversion)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
PxU32 handle = 0xFFFFFFFF;
|
||||
if (sim)
|
||||
handle = sim->getScene().addTetRigidAttachment(core, *sim, tetIdx, barycentric, actorSpacePose, constraint, doConversion);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::addSoftBodyFilter(Sc::DeformableVolumeCore& core, PxU32 tetIdx0, PxU32 tetIdx1)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
sim->getScene().addSoftBodyFilter(core, tetIdx0, *sim, tetIdx1);
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::removeSoftBodyFilter(Sc::DeformableVolumeCore& core, PxU32 tetIdx0, PxU32 tetIdx1)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
sim->getScene().removeSoftBodyFilter(core, tetIdx0, *sim, tetIdx1);
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::addSoftBodyFilters(Sc::DeformableVolumeCore& core, PxU32* tetIndices0, PxU32* tetIndices1, PxU32 tetIndicesSize)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
sim->getScene().addSoftBodyFilters(core, *sim, tetIndices0, tetIndices1, tetIndicesSize);
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::removeSoftBodyFilters(Sc::DeformableVolumeCore& core, PxU32* tetIndices0, PxU32* tetIndices1, PxU32 tetIndicesSize)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
sim->getScene().removeSoftBodyFilters(core, *sim, tetIndices0, tetIndices1, tetIndicesSize);
|
||||
}
|
||||
|
||||
|
||||
PxU32 Sc::DeformableVolumeCore::addSoftBodyAttachment(Sc::DeformableVolumeCore& core, PxU32 tetIdx0, const PxVec4& triBarycentric0, PxU32 tetIdx1, const PxVec4& tetBarycentric1,
|
||||
PxConeLimitedConstraint* constraint, PxReal constraintOffset, bool doConversion)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
PxU32 handle = 0xFFFFFFFF;
|
||||
if (sim)
|
||||
handle = sim->getScene().addSoftBodyAttachment(core, tetIdx0, triBarycentric0, *sim, tetIdx1, tetBarycentric1, constraint, constraintOffset, doConversion);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::removeSoftBodyAttachment(Sc::DeformableVolumeCore& core, PxU32 handle)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
setWakeCounterInternal(ScInternalWakeCounterResetValue);
|
||||
core.setWakeCounterInternal(ScInternalWakeCounterResetValue);
|
||||
if (sim)
|
||||
sim->getScene().removeSoftBodyAttachment(core, *sim, handle);
|
||||
}
|
||||
|
||||
|
||||
void Sc::DeformableVolumeCore::addClothFilter(Sc::DeformableSurfaceCore& core, PxU32 triIdx, PxU32 tetIdx)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
|
||||
if (sim)
|
||||
sim->getScene().addClothFilter(core, triIdx, *sim, tetIdx);
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::removeClothFilter(Sc::DeformableSurfaceCore& core, PxU32 triIdx, PxU32 tetIdx)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
sim->getScene().removeClothFilter(core, triIdx, *sim, tetIdx);
|
||||
}
|
||||
|
||||
PxU32 Sc::DeformableVolumeCore::addClothAttachment(Sc::DeformableSurfaceCore& core, PxU32 triIdx, const PxVec4& triBarycentric, PxU32 tetIdx, const PxVec4& tetBarycentric,
|
||||
PxConeLimitedConstraint* constraint, PxReal constraintOffset, bool doConversion)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
PxU32 handle = 0xFFFFFFFF;
|
||||
if (sim)
|
||||
handle = sim->getScene().addClothAttachment(core, triIdx, triBarycentric, *sim, tetIdx, tetBarycentric, constraint, constraintOffset, doConversion);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::removeClothAttachment(Sc::DeformableSurfaceCore& core, PxU32 handle)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
setWakeCounterInternal(ScInternalWakeCounterResetValue);
|
||||
core.setWakeCounterInternal(ScInternalWakeCounterResetValue);
|
||||
if (sim)
|
||||
sim->getScene().removeClothAttachment(core, *sim, handle);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
// Internal API
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
void Sc::DeformableVolumeCore::addMaterial(const PxU16 handle)
|
||||
{
|
||||
mCore.materialHandles.pushBack(handle);
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::clearMaterials()
|
||||
{
|
||||
mCore.materialHandles.clear();
|
||||
mCore.dirty = true;
|
||||
}
|
||||
|
||||
PxActor* Sc::DeformableVolumeCore::getPxActor() const
|
||||
{
|
||||
return PxPointerOffset<PxActor*>(const_cast<DeformableVolumeCore*>(this), gOffsetTable.scCore2PxActor[getActorCoreType()]);
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::attachShapeCore(ShapeCore* shapeCore)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
sim->attachShapeCore(shapeCore);
|
||||
mCore.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::attachSimulationMesh(PxTetrahedronMesh* simulationMesh, PxDeformableVolumeAuxData* simulationState)
|
||||
{
|
||||
Sc::DeformableVolumeSim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
sim->attachSimulationMesh(simulationMesh, simulationState);
|
||||
mCore.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeCore::onShapeChange(ShapeCore& shape, ShapeChangeNotifyFlags notifyFlags)
|
||||
{
|
||||
PX_UNUSED(shape);
|
||||
DeformableVolumeSim* sim = getSim();
|
||||
if (!sim)
|
||||
return;
|
||||
ShapeSimBase& s = sim->getShapeSim();
|
||||
|
||||
if (notifyFlags & ShapeChangeNotifyFlag::eGEOMETRY)
|
||||
s.onVolumeOrTransformChange();
|
||||
if (notifyFlags & ShapeChangeNotifyFlag::eRESET_FILTERING)
|
||||
s.onResetFiltering();
|
||||
if (notifyFlags & ShapeChangeNotifyFlag::eSHAPE2BODY)
|
||||
s.onVolumeOrTransformChange();
|
||||
if (notifyFlags & ShapeChangeNotifyFlag::eFILTERDATA)
|
||||
s.onFilterDataChange();
|
||||
if (notifyFlags & ShapeChangeNotifyFlag::eCONTACTOFFSET)
|
||||
s.onContactOffsetChange();
|
||||
if (notifyFlags & ShapeChangeNotifyFlag::eRESTOFFSET)
|
||||
s.onRestOffsetChange();
|
||||
}
|
||||
|
||||
Sc::DeformableVolumeSim* Sc::DeformableVolumeCore::getSim() const
|
||||
{
|
||||
return static_cast<Sc::DeformableVolumeSim*>(ActorCore::getSim());
|
||||
}
|
||||
|
||||
#endif //PX_SUPPORT_GPU_PHYSX
|
||||
|
||||
199
engine/third_party/physx/source/simulationcontroller/src/ScDeformableVolumeSim.cpp
vendored
Normal file
199
engine/third_party/physx/source/simulationcontroller/src/ScDeformableVolumeSim.cpp
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
|
||||
#include "ScDeformableVolumeSim.h"
|
||||
#include "geometry/PxTetrahedronMesh.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Dy;
|
||||
|
||||
Sc::DeformableVolumeSim::DeformableVolumeSim(DeformableVolumeCore& core, Scene& scene) :
|
||||
GPUActorSim(scene, core, NULL)
|
||||
{
|
||||
mLLDeformableVolume = scene.createLLDeformableVolume(this);
|
||||
|
||||
mNodeIndex = scene.getSimpleIslandManager()->addNode(false, false, IG::Node::eDEFORMABLE_VOLUME_TYPE, mLLDeformableVolume);
|
||||
|
||||
scene.getSimpleIslandManager()->activateNode(mNodeIndex);
|
||||
|
||||
mLLDeformableVolume->setElementId(mShapeSim.getElementID());
|
||||
}
|
||||
|
||||
Sc::DeformableVolumeSim::~DeformableVolumeSim()
|
||||
{
|
||||
if (!mLLDeformableVolume)
|
||||
return;
|
||||
|
||||
mScene.destroyLLDeformableVolume(*mLLDeformableVolume);
|
||||
|
||||
mScene.getSimpleIslandManager()->removeNode(mNodeIndex);
|
||||
|
||||
mCore.setSim(NULL);
|
||||
}
|
||||
|
||||
bool Sc::DeformableVolumeSim::isSleeping() const
|
||||
{
|
||||
IG::IslandSim& sim = mScene.getSimpleIslandManager()->getAccurateIslandSim();
|
||||
return sim.getActiveNodeIndex(mNodeIndex) == PX_INVALID_NODE;
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeSim::onSetWakeCounter()
|
||||
{
|
||||
mScene.getSimulationController()->setSoftBodyWakeCounter(mLLDeformableVolume);
|
||||
if (mLLDeformableVolume->getCore().wakeCounter > 0.f)
|
||||
mScene.getSimpleIslandManager()->activateNode(mNodeIndex);
|
||||
else
|
||||
mScene.getSimpleIslandManager()->deactivateNode(mNodeIndex);
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeSim::attachShapeCore(ShapeCore* core)
|
||||
{
|
||||
mShapeSim.setCore(core);
|
||||
{
|
||||
PX_ASSERT(getWorldBounds().isFinite());
|
||||
|
||||
const PxU32 index = mShapeSim.getElementID();
|
||||
|
||||
mScene.getBoundsArray().setBounds(getWorldBounds(), index);
|
||||
|
||||
addToAABBMgr(Bp::FilterType::DEFORMABLE_VOLUME);
|
||||
}
|
||||
|
||||
PxsShapeCore* shapeCore = const_cast<PxsShapeCore*>(&core->getCore());
|
||||
mLLDeformableVolume->setShapeCore(shapeCore);
|
||||
}
|
||||
|
||||
PxBounds3 Sc::DeformableVolumeSim::getWorldBounds() const
|
||||
{
|
||||
const PxTetrahedronMeshGeometry& tetGeom = static_cast<const PxTetrahedronMeshGeometry&>(mShapeSim.getCore().getGeometry());
|
||||
|
||||
return tetGeom.tetrahedronMesh->getLocalBounds();
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeSim::attachSimulationMesh(PxTetrahedronMesh* simulationMesh, PxDeformableVolumeAuxData* simulationState)
|
||||
{
|
||||
mLLDeformableVolume->setSimShapeCore(simulationMesh, simulationState);
|
||||
}
|
||||
|
||||
PxTetrahedronMesh* Sc::DeformableVolumeSim::getSimulationMesh()
|
||||
{
|
||||
return mLLDeformableVolume->getSimulationMesh();
|
||||
}
|
||||
|
||||
PxDeformableVolumeAuxData* Sc::DeformableVolumeSim::getAuxData()
|
||||
{
|
||||
return mLLDeformableVolume->getAuxData();
|
||||
}
|
||||
|
||||
PxTetrahedronMesh* Sc::DeformableVolumeSim::getCollisionMesh()
|
||||
{
|
||||
return mLLDeformableVolume->getCollisionMesh();
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeSim::enableSelfCollision()
|
||||
{
|
||||
if (isActive())
|
||||
{
|
||||
mScene.getSimulationController()->activateSoftbodySelfCollision(mLLDeformableVolume);
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeSim::disableSelfCollision()
|
||||
{
|
||||
if (isActive())
|
||||
{
|
||||
mScene.getSimulationController()->deactivateSoftbodySelfCollision(mLLDeformableVolume);
|
||||
}
|
||||
}
|
||||
|
||||
/*void Sc::DeformableVolumeSim::activate()
|
||||
{
|
||||
// Activate body
|
||||
//{
|
||||
// PX_ASSERT((!isKinematic()) || notInScene() || readInternalFlag(InternalFlags(BF_KINEMATIC_MOVED | BF_KINEMATIC_SURFACE_VELOCITY))); // kinematics should only get activated when a target is set.
|
||||
// // exception: object gets newly added, then the state change will happen later
|
||||
// if (!isArticulationLink())
|
||||
// {
|
||||
// mLLBody.mInternalFlags &= (~PxsRigidBody::eFROZEN);
|
||||
// // Put in list of activated bodies. The list gets cleared at the end of a sim step after the sleep callbacks have been fired.
|
||||
// getScene().onBodyWakeUp(this);
|
||||
// }
|
||||
|
||||
// BodyCore& core = getBodyCore();
|
||||
// if (core.getFlags() & PxRigidBodyFlag::eENABLE_POSE_INTEGRATION_PREVIEW)
|
||||
// {
|
||||
// PX_ASSERT(!getScene().isInPosePreviewList(*this));
|
||||
// getScene().addToPosePreviewList(*this);
|
||||
// }
|
||||
// createSqBounds();
|
||||
//}
|
||||
|
||||
activateInteractions(*this);
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeSim::deactivate()
|
||||
{
|
||||
deactivateInteractions(*this);
|
||||
|
||||
// Deactivate body
|
||||
//{
|
||||
// PX_ASSERT((!isKinematic()) || notInScene() || !readInternalFlag(BF_KINEMATIC_MOVED)); // kinematics should only get deactivated when no target is set.
|
||||
// // exception: object gets newly added, then the state change will happen later
|
||||
// BodyCore& core = getBodyCore();
|
||||
// if (!readInternalFlag(BF_ON_DEATHROW))
|
||||
// {
|
||||
// // Set velocity to 0.
|
||||
// // Note: this is also fine if the method gets called because the user puts something to sleep (this behavior is documented in the API)
|
||||
// PX_ASSERT(core.getWakeCounter() == 0.0f);
|
||||
// const PxVec3 zero(0.0f);
|
||||
// core.setLinearVelocityInternal(zero);
|
||||
// core.setAngularVelocityInternal(zero);
|
||||
|
||||
// setForcesToDefaults(!(mLLBody.mInternalFlags & PxsRigidBody::eDISABLE_GRAVITY));
|
||||
// }
|
||||
|
||||
// if (!isArticulationLink()) // Articulations have their own sleep logic.
|
||||
// getScene().onBodySleep(this);
|
||||
|
||||
// if (core.getFlags() & PxRigidBodyFlag::eENABLE_POSE_INTEGRATION_PREVIEW)
|
||||
// {
|
||||
// PX_ASSERT(getScene().isInPosePreviewList(*this));
|
||||
// getScene().removeFromPosePreviewList(*this);
|
||||
// }
|
||||
// destroySqBounds();
|
||||
//}
|
||||
}*/
|
||||
|
||||
PxU32 Sc::DeformableVolumeSim::getGpuIndex() const
|
||||
{
|
||||
return mLLDeformableVolume->getGpuIndex();
|
||||
}
|
||||
|
||||
#endif //PX_SUPPORT_GPU_PHYSX
|
||||
89
engine/third_party/physx/source/simulationcontroller/src/ScDeformableVolumeSim.h
vendored
Normal file
89
engine/third_party/physx/source/simulationcontroller/src/ScDeformableVolumeSim.h
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
|
||||
#ifndef SC_DEFORMABLE_VOLUME_SIM_H
|
||||
#define SC_DEFORMABLE_VOLUME_SIM_H
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "DyDeformableVolume.h"
|
||||
#include "ScDeformableVolumeCore.h"
|
||||
#include "ScGpuActorSim.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
|
||||
class Scene;
|
||||
|
||||
class DeformableVolumeSim : public GPUActorSim
|
||||
{
|
||||
PX_NOCOPY(DeformableVolumeSim)
|
||||
public:
|
||||
DeformableVolumeSim(DeformableVolumeCore& core, Scene& scene);
|
||||
~DeformableVolumeSim();
|
||||
|
||||
PX_INLINE Dy::DeformableVolume* getLowLevelDeformableVolume() const { return mLLDeformableVolume; }
|
||||
PX_INLINE DeformableVolumeCore& getCore() const { return static_cast<DeformableVolumeCore&>(mCore); }
|
||||
|
||||
virtual PxActor* getPxActor() const { return getCore().getPxActor(); }
|
||||
|
||||
bool isSleeping() const;
|
||||
bool isActive() const { return !isSleeping(); }
|
||||
|
||||
void setActive(bool active, bool asPartOfCreation=false);
|
||||
|
||||
void enableSelfCollision();
|
||||
void disableSelfCollision();
|
||||
|
||||
void onSetWakeCounter();
|
||||
|
||||
PxBounds3 getWorldBounds() const;
|
||||
|
||||
void attachShapeCore(ShapeCore* core);
|
||||
void attachSimulationMesh(PxTetrahedronMesh* simulationMesh, PxDeformableVolumeAuxData* simulationState);
|
||||
PxTetrahedronMesh* getSimulationMesh();
|
||||
PxDeformableVolumeAuxData* getAuxData();
|
||||
|
||||
PxTetrahedronMesh* getCollisionMesh();
|
||||
|
||||
PxU32 getGpuIndex() const;
|
||||
private:
|
||||
Dy::DeformableVolume* mLLDeformableVolume;
|
||||
PxU32 mIslandNodeIndex;
|
||||
|
||||
// PT: as far as I can tell these are never actually called
|
||||
// void activate();
|
||||
// void deactivate();
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
} // namespace physx
|
||||
|
||||
#endif // PX_SUPPORT_GPU_PHYSX
|
||||
#endif // SC_DEFORMABLE_VOLUME_SIM_H
|
||||
41
engine/third_party/physx/source/simulationcontroller/src/ScElementInteractionMarker.cpp
vendored
Normal file
41
engine/third_party/physx/source/simulationcontroller/src/ScElementInteractionMarker.cpp
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScElementInteractionMarker.h"
|
||||
#include "ScNPhaseCore.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::ElementInteractionMarker::~ElementInteractionMarker()
|
||||
{
|
||||
if(isRegistered())
|
||||
getScene().unregisterInteraction(this);
|
||||
|
||||
unregisterFromActors();
|
||||
}
|
||||
|
||||
64
engine/third_party/physx/source/simulationcontroller/src/ScElementInteractionMarker.h
vendored
Normal file
64
engine/third_party/physx/source/simulationcontroller/src/ScElementInteractionMarker.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ELEMENT_INTERACTION_MARKER_H
|
||||
#define SC_ELEMENT_INTERACTION_MARKER_H
|
||||
|
||||
#include "ScElementSimInteraction.h"
|
||||
#include "ScNPhaseCore.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class ElementInteractionMarker : public ElementSimInteraction
|
||||
{
|
||||
public:
|
||||
PX_INLINE ElementInteractionMarker(ElementSim& element0, ElementSim& element1, bool createParallel/* = false*/);
|
||||
~ElementInteractionMarker();
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
|
||||
PX_INLINE Sc::ElementInteractionMarker::ElementInteractionMarker(ElementSim& element0, ElementSim& element1, bool createParallel) :
|
||||
ElementSimInteraction(element0, element1, InteractionType::eMARKER, InteractionFlag::eRB_ELEMENT|InteractionFlag::eFILTERABLE)
|
||||
{
|
||||
if(!createParallel)
|
||||
{
|
||||
// PT: no call to onActivate() here, interaction markers are always inactive
|
||||
registerInActors();
|
||||
Scene& scene = getScene();
|
||||
scene.registerInteraction(this, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
178
engine/third_party/physx/source/simulationcontroller/src/ScElementSim.cpp
vendored
Normal file
178
engine/third_party/physx/source/simulationcontroller/src/ScElementSim.cpp
vendored
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-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScElementSim.h"
|
||||
#include "ScElementSimInteraction.h"
|
||||
#include "ScSimStats.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
static PX_FORCE_INLINE bool interactionHasElement(const Interaction* it, const ElementSim* elem)
|
||||
{
|
||||
if(it->readInteractionFlag(InteractionFlag::eRB_ELEMENT))
|
||||
{
|
||||
PX_ASSERT( (it->getType() == InteractionType::eMARKER) ||
|
||||
(it->getType() == InteractionType::eOVERLAP) ||
|
||||
(it->getType() == InteractionType::eTRIGGER) );
|
||||
|
||||
const ElementSimInteraction* ei = static_cast<const ElementSimInteraction*>(it);
|
||||
if((&ei->getElement0() == elem) || (&ei->getElement1() == elem))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Sc::ElementSimInteraction* Sc::ElementSim::ElementInteractionIterator::getNext()
|
||||
{
|
||||
while(mInteractions!=mInteractionsLast)
|
||||
{
|
||||
Interaction* it = *mInteractions++;
|
||||
if(interactionHasElement(it, mElement))
|
||||
return static_cast<ElementSimInteraction*>(it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Sc::ElementSimInteraction* Sc::ElementSim::ElementInteractionReverseIterator::getNext()
|
||||
{
|
||||
while(mInteractions!=mInteractionsLast)
|
||||
{
|
||||
Interaction* it = *--mInteractionsLast;
|
||||
if(interactionHasElement(it, mElement))
|
||||
return static_cast<ElementSimInteraction*>(it);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class ElemSimPtrTableStorageManager : public Cm::PtrTableStorageManager, public PxUserAllocated
|
||||
{
|
||||
PX_NOCOPY(ElemSimPtrTableStorageManager)
|
||||
|
||||
public:
|
||||
ElemSimPtrTableStorageManager() {}
|
||||
~ElemSimPtrTableStorageManager() {}
|
||||
|
||||
// PtrTableStorageManager
|
||||
virtual void** allocate(PxU32 capacity) PX_OVERRIDE
|
||||
{
|
||||
return PX_ALLOCATE(void*, capacity, "CmPtrTable pointer array");
|
||||
}
|
||||
|
||||
virtual void deallocate(void** addr, PxU32 /*capacity*/) PX_OVERRIDE
|
||||
{
|
||||
PX_FREE(addr);
|
||||
}
|
||||
|
||||
virtual bool canReuse(PxU32 /*originalCapacity*/, PxU32 /*newCapacity*/) PX_OVERRIDE
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//~PtrTableStorageManager
|
||||
};
|
||||
ElemSimPtrTableStorageManager gElemSimTableStorageManager;
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void onElementAttach(ElementSim& element, ShapeManager& manager)
|
||||
{
|
||||
PX_ASSERT(element.mShapeArrayIndex == 0xffffffff);
|
||||
element.mShapeArrayIndex = manager.mShapes.getCount();
|
||||
manager.mShapes.add(&element, gElemSimTableStorageManager);
|
||||
}
|
||||
|
||||
void Sc::ShapeManager::onElementDetach(ElementSim& element)
|
||||
{
|
||||
const PxU32 index = element.mShapeArrayIndex;
|
||||
PX_ASSERT(index != 0xffffffff);
|
||||
PX_ASSERT(mShapes.getCount());
|
||||
void** ptrs = mShapes.getPtrs();
|
||||
PX_ASSERT(reinterpret_cast<ElementSim*>(ptrs[index]) == &element);
|
||||
|
||||
const PxU32 last = mShapes.getCount() - 1;
|
||||
if (index != last)
|
||||
{
|
||||
ElementSim* moved = reinterpret_cast<ElementSim*>(ptrs[last]);
|
||||
PX_ASSERT(moved->mShapeArrayIndex == last);
|
||||
moved->mShapeArrayIndex = index;
|
||||
}
|
||||
mShapes.replaceWithLast(index, gElemSimTableStorageManager);
|
||||
element.mShapeArrayIndex = 0xffffffff;
|
||||
}
|
||||
|
||||
Sc::ElementSim::ElementSim(ActorSim& actor) :
|
||||
mActor (actor),
|
||||
mInBroadPhase (false),
|
||||
mShapeArrayIndex(0xffffffff)
|
||||
{
|
||||
initID();
|
||||
|
||||
onElementAttach(*this, actor);
|
||||
}
|
||||
|
||||
Sc::ElementSim::~ElementSim()
|
||||
{
|
||||
PX_ASSERT(!mInBroadPhase);
|
||||
releaseID();
|
||||
mActor.onElementDetach(*this);
|
||||
}
|
||||
|
||||
void Sc::ElementSim::addToAABBMgr(PxReal contactDistance, Bp::FilterGroup::Enum group, Bp::ElementType::Enum type)
|
||||
{
|
||||
const ActorCore& actorCore = mActor.getActorCore();
|
||||
const PxU32 aggregateID = actorCore.getAggregateID();
|
||||
const PxU32 envID = actorCore.getEnvID();
|
||||
|
||||
Sc::Scene& scene = getScene();
|
||||
if(!scene.getAABBManager()->addBounds(mElementID, contactDistance, group, this, aggregateID, type, envID))
|
||||
return;
|
||||
|
||||
mInBroadPhase = true;
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
scene.getStatsInternal().incBroadphaseAdds();
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Sc::ElementSim::removeFromAABBMgr()
|
||||
{
|
||||
PX_ASSERT(mInBroadPhase);
|
||||
Sc::Scene& scene = getScene();
|
||||
bool res = scene.getAABBManager()->removeBounds(mElementID);
|
||||
scene.getAABBManager()->getChangedAABBMgActorHandleMap().growAndReset(mElementID);
|
||||
|
||||
mInBroadPhase = false;
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
scene.getStatsInternal().incBroadphaseRemoves();
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
136
engine/third_party/physx/source/simulationcontroller/src/ScElementSim.h
vendored
Normal file
136
engine/third_party/physx/source/simulationcontroller/src/ScElementSim.h
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ELEMENT_SIM_H
|
||||
#define SC_ELEMENT_SIM_H
|
||||
|
||||
#include "PxFiltering.h"
|
||||
#include "PxvConfig.h"
|
||||
#include "ScActorSim.h"
|
||||
#include "ScInteraction.h"
|
||||
#include "BpAABBManager.h"
|
||||
#include "ScObjectIDTracker.h"
|
||||
#include "ScScene.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class ElementSimInteraction;
|
||||
|
||||
// A ElementSim is a part of a ActorSim. It contributes to the activation framework by adding its interactions to the actor.
|
||||
class ElementSim
|
||||
{
|
||||
PX_NOCOPY(ElementSim)
|
||||
|
||||
public:
|
||||
class ElementInteractionIterator
|
||||
{
|
||||
public:
|
||||
PX_FORCE_INLINE ElementInteractionIterator(const ElementSim& e, PxU32 nbInteractions, Interaction** interactions) :
|
||||
mInteractions(interactions), mInteractionsLast(interactions + nbInteractions), mElement(&e) {}
|
||||
ElementSimInteraction* getNext();
|
||||
|
||||
private:
|
||||
Interaction** mInteractions;
|
||||
Interaction** mInteractionsLast;
|
||||
const ElementSim* mElement;
|
||||
};
|
||||
|
||||
class ElementInteractionReverseIterator
|
||||
{
|
||||
public:
|
||||
PX_FORCE_INLINE ElementInteractionReverseIterator(const ElementSim& e, PxU32 nbInteractions, Interaction** interactions) :
|
||||
mInteractions(interactions), mInteractionsLast(interactions + nbInteractions), mElement(&e) {}
|
||||
ElementSimInteraction* getNext();
|
||||
|
||||
private:
|
||||
Interaction** mInteractions;
|
||||
Interaction** mInteractionsLast;
|
||||
const ElementSim* mElement;
|
||||
};
|
||||
|
||||
ElementSim(ActorSim& actor);
|
||||
protected:
|
||||
~ElementSim();
|
||||
public:
|
||||
|
||||
// Get an iterator to the interactions connected to the element
|
||||
// PT: this may seem strange at first glance since the "element interactions" appear to use the "actor interactions". The thing that makes this work is hidden
|
||||
// inside the iterator implementation: it does parse all the actor interactions indeed, but filters out the ones that do not contain "this", i.e. the desired element.
|
||||
// So this is inefficient (parsing potentially many more interactions than needed, imagine in a large compound) but it works, and the iterator has a point - it isn't
|
||||
// just the same as parsing the actor's array.
|
||||
PX_FORCE_INLINE ElementInteractionIterator getElemInteractions() const { return ElementInteractionIterator(*this, mActor.getActorInteractionCount(), mActor.getActorInteractions()); }
|
||||
PX_FORCE_INLINE ElementInteractionReverseIterator getElemInteractionsReverse() const { return ElementInteractionReverseIterator(*this, mActor.getActorInteractionCount(), mActor.getActorInteractions()); }
|
||||
|
||||
PX_FORCE_INLINE ActorSim& getActor() const { return mActor; }
|
||||
|
||||
PX_FORCE_INLINE Scene& getScene() const { return mActor.getScene(); }
|
||||
|
||||
PX_FORCE_INLINE PxU32 getElementID() const { return mElementID; }
|
||||
PX_FORCE_INLINE bool isInBroadPhase() const { return mInBroadPhase; }
|
||||
PX_FORCE_INLINE void setInBroadPhase() { mInBroadPhase = true; }
|
||||
|
||||
void addToAABBMgr(PxReal contactDistance, Bp::FilterGroup::Enum group, Bp::ElementType::Enum type);
|
||||
PX_FORCE_INLINE void addToAABBMgr(PxReal contactOffset, Bp::FilterType::Enum type)
|
||||
{
|
||||
const PxU32 group = Bp::FilterGroup::eDYNAMICS_BASE + mActor.getActorID();
|
||||
addToAABBMgr(contactOffset, Bp::FilterGroup::Enum((group << BP_FILTERING_TYPE_SHIFT_BIT) | type), Bp::ElementType::eSHAPE);
|
||||
}
|
||||
|
||||
bool removeFromAABBMgr();
|
||||
|
||||
PX_FORCE_INLINE void initID()
|
||||
{
|
||||
Scene& scene = getScene();
|
||||
mElementID = scene.getElementIDPool().createID();
|
||||
scene.getBoundsArray().initEntry(mElementID);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void releaseID()
|
||||
{
|
||||
getScene().getElementIDPool().releaseID(mElementID);
|
||||
}
|
||||
protected:
|
||||
ActorSim& mActor;
|
||||
|
||||
PxU32 mElementID : 31; // PT: ID provided by Sc::Scene::mElementIDPool
|
||||
PxU32 mInBroadPhase : 1;
|
||||
public:
|
||||
PxU32 mShapeArrayIndex;
|
||||
};
|
||||
|
||||
PX_FORCE_INLINE void setFilterObjectAttributeType(PxFilterObjectAttributes& attr, PxFilterObjectType::Enum type)
|
||||
{
|
||||
PX_ASSERT((attr & (PxFilterObjectType::eMAX_TYPE_COUNT-1)) == 0);
|
||||
attr |= type;
|
||||
}
|
||||
} // namespace Sc
|
||||
}
|
||||
|
||||
#endif
|
||||
72
engine/third_party/physx/source/simulationcontroller/src/ScElementSimInteraction.h
vendored
Normal file
72
engine/third_party/physx/source/simulationcontroller/src/ScElementSimInteraction.h
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_ELEMENT_SIM_INTERACTION_H
|
||||
#define SC_ELEMENT_SIM_INTERACTION_H
|
||||
|
||||
#include "ScInteraction.h"
|
||||
#include "ScElementSim.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class ElementSimInteraction : public Interaction
|
||||
{
|
||||
public:
|
||||
PX_FORCE_INLINE ElementSim& getElement0() const { return mElement0; }
|
||||
PX_FORCE_INLINE ElementSim& getElement1() const { return mElement1; }
|
||||
|
||||
protected:
|
||||
PX_INLINE ElementSimInteraction(ElementSim& element0, ElementSim& element1, InteractionType::Enum type, PxU8 flags);
|
||||
~ElementSimInteraction() {}
|
||||
|
||||
ElementSimInteraction& operator=(const ElementSimInteraction&);
|
||||
|
||||
ElementSim& mElement0;
|
||||
ElementSim& mElement1;
|
||||
PxU32 mFlags; // PT: moved there in padding bytes, from ShapeInteraction
|
||||
public:
|
||||
IG::EdgeIndex mEdgeIndex; // PT: moved there in padding bytes, from ShapeInteraction
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PX_INLINE Sc::ElementSimInteraction::ElementSimInteraction(ElementSim& element0, ElementSim& element1, InteractionType::Enum type, PxU8 flags) :
|
||||
Interaction (element0.getActor(), element1.getActor(), type, flags),
|
||||
mElement0 (element0),
|
||||
mElement1 (element1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
875
engine/third_party/physx/source/simulationcontroller/src/ScFiltering.cpp
vendored
Normal file
875
engine/third_party/physx/source/simulationcontroller/src/ScFiltering.cpp
vendored
Normal file
@@ -0,0 +1,875 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScFiltering.h"
|
||||
#include "ScShapeInteraction.h"
|
||||
#include "ScTriggerInteraction.h"
|
||||
#include "ScConstraintCore.h"
|
||||
#include "ScArticulationSim.h"
|
||||
#include "geometry/PxTriangleMesh.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PX_IMPLEMENT_OUTPUT_ERROR
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PX_FORCE_INLINE PxU64 getPairID(const ShapeSimBase& s0, const ShapeSimBase& s1)
|
||||
{
|
||||
PxU64 id0 = PxU64(s0.getElementID());
|
||||
PxU64 id1 = PxU64(s1.getElementID());
|
||||
if(id1<id0)
|
||||
PxSwap(id0, id1);
|
||||
const PxU64 pairID = (id0<<32)|id1;
|
||||
return pairID;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<const bool supportTriggers>
|
||||
static PxFilterObjectAttributes getFilterObjectAttributes(const ShapeSimBase& shape)
|
||||
{
|
||||
const ActorSim& actorSim = shape.getActor();
|
||||
|
||||
PxFilterObjectAttributes filterAttr = actorSim.getFilterAttributes();
|
||||
|
||||
if(supportTriggers && (shape.getCore().getFlags() & PxShapeFlag::eTRIGGER_SHAPE))
|
||||
filterAttr |= PxFilterObjectFlag::eTRIGGER;
|
||||
|
||||
if (shape.getGeometryType() == PxGeometryType::eCUSTOM)
|
||||
filterAttr |= PxFilterObjectFlag::eCUSTOM_GEOMETRY;
|
||||
|
||||
#if PX_DEBUG
|
||||
BodySim* b = shape.getBodySim();
|
||||
if(b)
|
||||
{
|
||||
if(!b->isArticulationLink())
|
||||
{
|
||||
if(b->isKinematic())
|
||||
PX_ASSERT(filterAttr & PxFilterObjectFlag::eKINEMATIC);
|
||||
|
||||
PX_ASSERT(PxGetFilterObjectType(filterAttr)==PxFilterObjectType::eRIGID_DYNAMIC);
|
||||
}
|
||||
else
|
||||
{
|
||||
PX_ASSERT(PxGetFilterObjectType(filterAttr)==PxFilterObjectType::eARTICULATION);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
// For deformables and particle system, the bodySim is set to null
|
||||
if(actorSim.isDeformableSurface())
|
||||
{
|
||||
PX_ASSERT(PxGetFilterObjectType(filterAttr)==PxFilterObjectType::eDEFORMABLE_SURFACE);
|
||||
}
|
||||
else if(actorSim.isDeformableVolume())
|
||||
{
|
||||
PX_ASSERT(PxGetFilterObjectType(filterAttr)==PxFilterObjectType::eDEFORMABLE_VOLUME);
|
||||
}
|
||||
else if(actorSim.isParticleSystem())
|
||||
{
|
||||
PX_ASSERT(PxGetFilterObjectType(filterAttr)==PxFilterObjectType::ePARTICLESYSTEM);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
PX_ASSERT(PxGetFilterObjectType(filterAttr)==PxFilterObjectType::eRIGID_STATIC);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return filterAttr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PT: checks that the kill & suppress flags are not both set, disable kill flag if they are.
|
||||
static PX_INLINE void checkFilterFlags(PxFilterFlags& filterFlags)
|
||||
{
|
||||
if((filterFlags & (PxFilterFlag::eKILL | PxFilterFlag::eSUPPRESS)) == (PxFilterFlag::eKILL | PxFilterFlag::eSUPPRESS))
|
||||
{
|
||||
#if PX_CHECKED
|
||||
outputError<PxErrorCode::eDEBUG_WARNING>(__LINE__, "Filtering: eKILL and eSUPPRESS must not be set simultaneously. eSUPPRESS will be used.");
|
||||
#endif
|
||||
filterFlags.clear(PxFilterFlag::eKILL);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const PxPairFlags disableReportsFlags = PxPairFlag::eNOTIFY_CONTACT_POINTS |
|
||||
PxPairFlag::eNOTIFY_TOUCH_FOUND |
|
||||
PxPairFlag::eNOTIFY_TOUCH_LOST |
|
||||
PxPairFlag::eNOTIFY_TOUCH_PERSISTS |
|
||||
PxPairFlag::eNOTIFY_TOUCH_CCD |
|
||||
PxPairFlag::eNOTIFY_THRESHOLD_FORCE_FOUND |
|
||||
PxPairFlag::eNOTIFY_THRESHOLD_FORCE_LOST |
|
||||
PxPairFlag::eNOTIFY_THRESHOLD_FORCE_PERSISTS;
|
||||
|
||||
static PX_INLINE PxPairFlags checkRbPairFlags( const ShapeSimBase& s0, const ShapeSimBase& s1, bool isKinePair,
|
||||
PxPairFlags pairFlags, PxFilterFlags filterFlags, bool isNonRigid, bool isDirectGPU)
|
||||
{
|
||||
if(filterFlags & (PxFilterFlag::eSUPPRESS | PxFilterFlag::eKILL))
|
||||
return pairFlags;
|
||||
|
||||
if (isDirectGPU)
|
||||
{
|
||||
pairFlags &= ~(disableReportsFlags);
|
||||
}
|
||||
|
||||
if(isKinePair && (pairFlags & PxPairFlag::eSOLVE_CONTACT))
|
||||
{
|
||||
#if PX_CHECKED
|
||||
outputError<PxErrorCode::eDEBUG_WARNING>(__LINE__, "Filtering: Resolving contacts between two kinematic objects is invalid. Contacts will not get resolved.");
|
||||
#endif
|
||||
pairFlags.clear(PxPairFlag::eSOLVE_CONTACT);
|
||||
}
|
||||
|
||||
if(isNonRigid && (pairFlags & PxPairFlag::eDETECT_CCD_CONTACT))
|
||||
pairFlags.clear(PxPairFlag::eDETECT_CCD_CONTACT);
|
||||
|
||||
#if PX_CHECKED
|
||||
// we want to avoid to run contact generation for pairs that should not get resolved or have no contact/trigger reports
|
||||
if (!(PxU32(pairFlags) & (PxPairFlag::eSOLVE_CONTACT | ShapeInteraction::CONTACT_REPORT_EVENTS)))
|
||||
outputError<PxErrorCode::eDEBUG_WARNING>(__LINE__, "Filtering: Pair with no contact/trigger reports detected, nor is PxPairFlag::eSOLVE_CONTACT set. It is recommended to suppress/kill such pairs for performance reasons.");
|
||||
else if(!(pairFlags & (PxPairFlag::eDETECT_DISCRETE_CONTACT | PxPairFlag::eDETECT_CCD_CONTACT)))
|
||||
outputError<PxErrorCode::eDEBUG_WARNING>(__LINE__, "Filtering: Pair did not request either eDETECT_DISCRETE_CONTACT or eDETECT_CCD_CONTACT. It is recommended to suppress/kill such pairs for performance reasons.");
|
||||
|
||||
if(((s0.getFlags() & PxShapeFlag::eTRIGGER_SHAPE)!=0 || (s1.getFlags() & PxShapeFlag::eTRIGGER_SHAPE)!=0) &&
|
||||
(pairFlags & PxPairFlag::eTRIGGER_DEFAULT) && (pairFlags & PxPairFlag::eDETECT_CCD_CONTACT))
|
||||
outputError<PxErrorCode::eDEBUG_WARNING>(__LINE__, "Filtering: CCD isn't supported on Triggers yet");
|
||||
#else
|
||||
PX_UNUSED(s0);
|
||||
PX_UNUSED(s1);
|
||||
#endif
|
||||
return pairFlags;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PX_FORCE_INLINE bool createFilterInfo(FilterInfo& filterInfo, const PxFilterFlags filterFlags)
|
||||
{
|
||||
filterInfo = FilterInfo(filterFlags);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void filterRbCollisionPairSecondStage(FilterInfo& filterInfo, const FilteringContext& context, const ShapeSimBase& s0, const ShapeSimBase& s1, bool isKinePair,
|
||||
const PxFilterObjectAttributes fa0, const PxFilterObjectAttributes fa1, bool runCallbacks, bool isNonRigid, PxU64 contextID)
|
||||
{
|
||||
PX_UNUSED(contextID);
|
||||
|
||||
// Run filter shader
|
||||
const PxFilterData& fd0 = s0.getCore().getSimulationFilterData();
|
||||
const PxFilterData& fd1 = s1.getCore().getSimulationFilterData();
|
||||
filterInfo.setFilterFlags(context.mFilterShader(fa0, fd0, fa1, fd1, filterInfo.mPairFlags, context.mFilterShaderData, context.mFilterShaderDataSize));
|
||||
|
||||
if(filterInfo.getFilterFlags() & PxFilterFlag::eCALLBACK)
|
||||
{
|
||||
if(context.mFilterCallback)
|
||||
{
|
||||
if(!runCallbacks)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If a FilterPair is provided, then we use it, else we create a new one
|
||||
// (A FilterPair is provided in the case for a pairLost()-pairFound() sequence after refiltering)
|
||||
|
||||
struct Local
|
||||
{
|
||||
static PX_FORCE_INLINE PxShape* fetchActorAndShape(const ShapeSimBase& sim, const PxFilterObjectAttributes fa, PxActor*& a)
|
||||
{
|
||||
a = sim.getActor().getPxActor();
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
if(PxGetFilterObjectType(fa)==PxFilterObjectType::ePARTICLESYSTEM)
|
||||
return NULL; // Particle system does not have a valid shape so set it to null
|
||||
#endif
|
||||
PX_UNUSED(fa);
|
||||
return sim.getPxShape();
|
||||
}
|
||||
};
|
||||
|
||||
PxActor* a0, *a1;
|
||||
PxShape* shape0 = Local::fetchActorAndShape(s0, fa0, a0);
|
||||
PxShape* shape1 = Local::fetchActorAndShape(s1, fa1, a1);
|
||||
|
||||
{
|
||||
// PT: TODO: should be called "onPairFound"
|
||||
PX_PROFILE_ZONE("USERCODE - PxSimulationFilterCallback::pairFound", contextID);
|
||||
filterInfo.setFilterFlags(context.mFilterCallback->pairFound(getPairID(s0, s1), fa0, fd0, a0, shape0, fa1, fd1, a1, shape1, filterInfo.mPairFlags));
|
||||
}
|
||||
filterInfo.mHasPairID = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
filterInfo.clearFilterFlags(PxFilterFlag::eNOTIFY);
|
||||
outputError<PxErrorCode::eDEBUG_WARNING>(__LINE__, "Filtering: eCALLBACK set but no filter callback defined.");
|
||||
}
|
||||
}
|
||||
|
||||
PxFilterFlags flags = filterInfo.getFilterFlags();
|
||||
checkFilterFlags(flags);
|
||||
filterInfo.setFilterFlags(flags);
|
||||
|
||||
const bool hasNotify = (filterInfo.getFilterFlags() & PxFilterFlag::eNOTIFY) == PxFilterFlag::eNOTIFY;
|
||||
const bool hasKill = filterInfo.getFilterFlags() & PxFilterFlag::eKILL;
|
||||
|
||||
{
|
||||
if(filterInfo.mHasPairID && (hasKill || !hasNotify))
|
||||
{
|
||||
if(hasKill && hasNotify)
|
||||
{
|
||||
// PT: TODO: should be called "onPairLost"
|
||||
PX_PROFILE_ZONE("USERCODE - PxSimulationFilterCallback::pairLost", contextID);
|
||||
context.mFilterCallback->pairLost(getPairID(s0, s1), fa0, fd0, fa1, fd1, false);
|
||||
}
|
||||
if(!hasNotify)
|
||||
{
|
||||
// No notification, hence we don't need to treat it as a filter callback pair anymore.
|
||||
// Make sure that eCALLBACK gets removed as well
|
||||
filterInfo.clearFilterFlags(PxFilterFlag::eNOTIFY);
|
||||
}
|
||||
|
||||
filterInfo.mHasPairID = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity checks
|
||||
PX_ASSERT((!hasKill) || (hasKill && (!filterInfo.mHasPairID)));
|
||||
PX_ASSERT((!hasNotify) || (hasNotify && filterInfo.mHasPairID));
|
||||
|
||||
if(runCallbacks || (!(filterInfo.getFilterFlags() & PxFilterFlag::eCALLBACK)))
|
||||
filterInfo.mPairFlags = checkRbPairFlags(s0, s1, isKinePair, filterInfo.mPairFlags, filterInfo.getFilterFlags(), isNonRigid, context.mIsDirectGPU);
|
||||
}
|
||||
|
||||
static bool filterArticulationLinks(const BodySim* bs0, const BodySim* bs1)
|
||||
{
|
||||
//It's the same articulation, so we can filter based on flags...
|
||||
const ArticulationSim* articulationSim0 = bs0->getArticulation();
|
||||
const ArticulationSim* articulationSim1 = bs1->getArticulation();
|
||||
if(articulationSim0 == articulationSim1)
|
||||
{
|
||||
if(articulationSim0->getCore().getArticulationFlags() & PxArticulationFlag::eDISABLE_SELF_COLLISION)
|
||||
return true;
|
||||
|
||||
//check to see if one link is the parent of the other link, if so disable collision
|
||||
const PxU32 linkId0 = bs0->getNodeIndex().articulationLinkId();
|
||||
const PxU32 linkId1 = bs1->getNodeIndex().articulationLinkId();
|
||||
|
||||
if(linkId1 < linkId0)
|
||||
return articulationSim0->getLink(linkId0).parent == linkId1;
|
||||
else
|
||||
return articulationSim1->getLink(linkId1).parent == linkId0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE bool filterJointedBodies(const ActorSim& rbActor0, const ActorSim& rbActor1)
|
||||
{
|
||||
// If the bodies of the shape pair are connected by a joint, we need to check whether this connection disables the collision.
|
||||
// Note: As an optimization, the dynamic bodies have a flag which specifies whether they have any constraints at all. That works
|
||||
// because a constraint has at least one dynamic body and an interaction is tracked by both objects.
|
||||
|
||||
// PT: the BF_HAS_CONSTRAINTS flag is only raised on dynamic actors in the BodySim class, but it's not raised on static actors.
|
||||
// Thus the only reliable way to use the flag (without casting to BodySim etc) is when both actors don't have the flag set, in
|
||||
// which case we're sure we're not dealing with a jointed pair.
|
||||
if(!rbActor0.readInternalFlag(ActorSim::BF_HAS_CONSTRAINTS) && !rbActor1.readInternalFlag(ActorSim::BF_HAS_CONSTRAINTS))
|
||||
return false;
|
||||
|
||||
ConstraintCore* core = rbActor0.getScene().findConstraintCore(&rbActor0, &rbActor1);
|
||||
return core ? !(core->getFlags() & PxConstraintFlag::eCOLLISION_ENABLED) : false;
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE bool hasForceNotifEnabled(const BodySim* bs, PxRigidBodyFlag::Enum flag)
|
||||
{
|
||||
if(!bs)
|
||||
return false;
|
||||
|
||||
const PxsRigidCore& core = bs->getBodyCore().getCore();
|
||||
return core.mFlags.isSet(flag);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE bool validateSuppress(const BodySim* b0, const BodySim* b1, PxRigidBodyFlag::Enum flag)
|
||||
{
|
||||
if(hasForceNotifEnabled(b0, flag))
|
||||
return false;
|
||||
|
||||
if(hasForceNotifEnabled(b1, flag))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE bool filterKinematics(const BodySim* b0, const BodySim* b1, bool kine0, bool kine1,
|
||||
PxPairFilteringMode::Enum kineKineFilteringMode, PxPairFilteringMode::Enum staticKineFilteringMode)
|
||||
{
|
||||
const bool kinematicPair = kine0 | kine1;
|
||||
if(kinematicPair)
|
||||
{
|
||||
if(staticKineFilteringMode != PxPairFilteringMode::eKEEP)
|
||||
{
|
||||
if(!b0 || !b1)
|
||||
return validateSuppress(b0, b1, PxRigidBodyFlag::eFORCE_STATIC_KINE_NOTIFICATIONS);
|
||||
}
|
||||
|
||||
if(kineKineFilteringMode != PxPairFilteringMode::eKEEP)
|
||||
{
|
||||
if(kine0 && kine1)
|
||||
return validateSuppress(b0, b1, PxRigidBodyFlag::eFORCE_KINE_KINE_NOTIFICATIONS);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<const bool runAllTests>
|
||||
static bool filterRbCollisionPairShared( FilterInfo& filterInfo, bool& isNonRigid, bool& isKinePair,
|
||||
const FilteringContext& context,
|
||||
const ShapeSimBase& s0, const ShapeSimBase& s1,
|
||||
const PxFilterObjectAttributes filterAttr0, const PxFilterObjectAttributes filterAttr1)
|
||||
{
|
||||
const bool kine0 = PxFilterObjectIsKinematic(filterAttr0);
|
||||
const bool kine1 = PxFilterObjectIsKinematic(filterAttr1);
|
||||
|
||||
const ActorSim& rbActor0 = s0.getActor();
|
||||
const BodySim* bs0 = NULL;
|
||||
if(filterAttr0 & PxFilterObjectFlagEx::eRIGID_DYNAMIC)
|
||||
bs0 = static_cast<const BodySim*>(&rbActor0);
|
||||
else if (filterAttr0 & PxFilterObjectFlagEx::eNON_RIGID)
|
||||
{
|
||||
if (filterAttr1 & PxFilterObjectFlag::eCUSTOM_GEOMETRY)
|
||||
{
|
||||
return createFilterInfo(filterInfo, PxFilterFlag::eKILL);
|
||||
}
|
||||
isNonRigid = true;
|
||||
}
|
||||
|
||||
const ActorSim& rbActor1 = s1.getActor();
|
||||
const BodySim* bs1 = NULL;
|
||||
if(filterAttr1 & PxFilterObjectFlagEx::eRIGID_DYNAMIC)
|
||||
bs1 = static_cast<const BodySim*>(&rbActor1);
|
||||
else if (filterAttr1 & PxFilterObjectFlagEx::eNON_RIGID)
|
||||
{
|
||||
if (filterAttr0 & PxFilterObjectFlag::eCUSTOM_GEOMETRY)
|
||||
{
|
||||
return createFilterInfo(filterInfo, PxFilterFlag::eKILL);
|
||||
}
|
||||
isNonRigid = true;
|
||||
}
|
||||
|
||||
if(!isNonRigid && filterKinematics(bs0, bs1, kine0, kine1, context.mKineKineFilteringMode, context.mStaticKineFilteringMode))
|
||||
return createFilterInfo(filterInfo, PxFilterFlag::eSUPPRESS);
|
||||
|
||||
if(filterJointedBodies(rbActor0, rbActor1))
|
||||
return createFilterInfo(filterInfo, PxFilterFlag::eSUPPRESS);
|
||||
|
||||
if (!isNonRigid)
|
||||
{
|
||||
if (s0.getGeometryType() == PxGeometryType::eTRIANGLEMESH &&
|
||||
s1.getGeometryType() == PxGeometryType::eTRIANGLEMESH)
|
||||
{
|
||||
const PxTriangleMeshGeometry& m0 = static_cast<const PxTriangleMeshGeometry&>(s0.getCore().getGeometry());
|
||||
const PxTriangleMeshGeometry& m1 = static_cast<const PxTriangleMeshGeometry&>(s1.getCore().getGeometry());
|
||||
if (m0.triangleMesh->getSDF() == NULL && m1.triangleMesh->getSDF() == NULL)
|
||||
return createFilterInfo(filterInfo, PxFilterFlag::eKILL);
|
||||
}
|
||||
}
|
||||
|
||||
const PxFilterObjectType::Enum filterType0 = PxGetFilterObjectType(filterAttr0);
|
||||
const PxFilterObjectType::Enum filterType1 = PxGetFilterObjectType(filterAttr1);
|
||||
|
||||
// PT: For unknown reasons the filtering code was not the same for triggers/refiltered pairs and for regular "shape sim" pairs
|
||||
// out of the BP. The tests on "runAllTests" below capture that. I did not change what the code
|
||||
// was doing, although it might very well be wrong - we might want to run all these tests in both codepaths.
|
||||
|
||||
if(runAllTests)
|
||||
{
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
if(filterType0==PxFilterObjectType::ePARTICLESYSTEM && filterType1==PxFilterObjectType::ePARTICLESYSTEM)
|
||||
return createFilterInfo(filterInfo, PxFilterFlag::eKILL);
|
||||
#endif
|
||||
}
|
||||
|
||||
const bool link0 = filterType0==PxFilterObjectType::eARTICULATION;
|
||||
const bool link1 = filterType1==PxFilterObjectType::eARTICULATION;
|
||||
|
||||
if(runAllTests)
|
||||
{
|
||||
if(link0 ^ link1)
|
||||
{
|
||||
if(link0)
|
||||
{
|
||||
const PxU8 fixedBaseLink = bs0->getLowLevelBody().mCore->fixedBaseLink;
|
||||
const bool isStaticOrKinematic = (filterType1 == PxFilterObjectType::eRIGID_STATIC) || kine1;
|
||||
if(fixedBaseLink && isStaticOrKinematic)
|
||||
return createFilterInfo(filterInfo, PxFilterFlag::eSUPPRESS);
|
||||
}
|
||||
|
||||
if(link1)
|
||||
{
|
||||
const PxU8 fixedBaseLink = bs1->getLowLevelBody().mCore->fixedBaseLink;
|
||||
const bool isStaticOrKinematic = (filterType0 == PxFilterObjectType::eRIGID_STATIC) || kine0;
|
||||
if(fixedBaseLink && isStaticOrKinematic)
|
||||
return createFilterInfo(filterInfo, PxFilterFlag::eSUPPRESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(link0 && link1)
|
||||
{
|
||||
if(runAllTests)
|
||||
{
|
||||
const PxU8 fixedBaseLink0 = bs0->getLowLevelBody().mCore->fixedBaseLink;
|
||||
const PxU8 fixedBaseLink1 = bs1->getLowLevelBody().mCore->fixedBaseLink;
|
||||
|
||||
if(fixedBaseLink0 && fixedBaseLink1)
|
||||
return createFilterInfo(filterInfo, PxFilterFlag::eSUPPRESS);
|
||||
}
|
||||
|
||||
if(filterArticulationLinks(bs0, bs1))
|
||||
return createFilterInfo(filterInfo, PxFilterFlag::eKILL);
|
||||
}
|
||||
isKinePair = kine0 && kine1;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void filterRbCollisionPair(FilterInfo& filterInfo, const FilteringContext& context, const ShapeSimBase& s0, const ShapeSimBase& s1, bool& isTriggerPair, bool runCallbacks, PxU64 contextID)
|
||||
{
|
||||
const PxFilterObjectAttributes filterAttr0 = getFilterObjectAttributes<true>(s0);
|
||||
const PxFilterObjectAttributes filterAttr1 = getFilterObjectAttributes<true>(s1);
|
||||
|
||||
const bool trigger0 = PxFilterObjectIsTrigger(filterAttr0);
|
||||
const bool trigger1 = PxFilterObjectIsTrigger(filterAttr1);
|
||||
isTriggerPair = trigger0 || trigger1;
|
||||
|
||||
bool isNonRigid = false;
|
||||
bool isKinePair = false;
|
||||
|
||||
if(isTriggerPair)
|
||||
{
|
||||
if(trigger0 && trigger1) // trigger-trigger pairs are not supported
|
||||
{
|
||||
createFilterInfo(filterInfo, PxFilterFlag::eKILL);
|
||||
return;
|
||||
}
|
||||
|
||||
// PT: I think we need to do this here to properly handle kinematic triggers.
|
||||
const bool kine0 = PxFilterObjectIsKinematic(filterAttr0);
|
||||
const bool kine1 = PxFilterObjectIsKinematic(filterAttr1);
|
||||
isKinePair = kine0 && kine1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(filterRbCollisionPairShared<false>(filterInfo, isNonRigid, isKinePair, context, s0, s1, filterAttr0, filterAttr1))
|
||||
return;
|
||||
}
|
||||
|
||||
filterRbCollisionPairSecondStage(filterInfo, context, s0, s1, isKinePair, filterAttr0, filterAttr1, runCallbacks, isNonRigid, contextID);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void filterRbCollisionPairAllTests(FilterInfo& filterInfo, const FilteringContext& context, const ShapeSimBase& s0, const ShapeSimBase& s1, PxU64 contextID)
|
||||
{
|
||||
PX_ASSERT(!(s0.getFlags() & PxShapeFlag::eTRIGGER_SHAPE));
|
||||
PX_ASSERT(!(s1.getFlags() & PxShapeFlag::eTRIGGER_SHAPE));
|
||||
|
||||
const PxFilterObjectAttributes filterAttr0 = getFilterObjectAttributes<false>(s0);
|
||||
const PxFilterObjectAttributes filterAttr1 = getFilterObjectAttributes<false>(s1);
|
||||
|
||||
bool isNonRigid = false;
|
||||
bool isKinePair = false;
|
||||
|
||||
if(filterRbCollisionPairShared<true>(filterInfo, isNonRigid, isKinePair, context, s0, s1, filterAttr0, filterAttr1))
|
||||
return;
|
||||
|
||||
filterRbCollisionPairSecondStage(filterInfo, context, s0, s1, isKinePair, filterAttr0, filterAttr1, true, isNonRigid, contextID);
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE bool testElementSimPointers(const ElementSim* e0, const ElementSim* e1)
|
||||
{
|
||||
PX_ASSERT(e0);
|
||||
PX_ASSERT(e1);
|
||||
|
||||
// PT: a bit of defensive coding added for OM-74224 / PX-3571. In theory this should not be needed, as the broadphase is not
|
||||
// supposed to return null pointers here. But there seems to be an issue somewhere, most probably in the GPU BP kernels,
|
||||
// and this is an attempt at preventing a crash. We could/should remove this eventually.
|
||||
// ### DEFENSIVE
|
||||
if(!e0 || !e1)
|
||||
return outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "NPhaseCore::runOverlapFilters: found null elements!");
|
||||
return true;
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE bool testShapeSimCorePointers(const ShapeSimBase* s0, const ShapeSimBase* s1)
|
||||
{
|
||||
bool isValid0 = s0->isPxsCoreValid();
|
||||
bool isValid1 = s1->isPxsCoreValid();
|
||||
PX_ASSERT(isValid0);
|
||||
PX_ASSERT(isValid1);
|
||||
|
||||
// GW: further defensive coding added for OM-111249 / PX-4478.
|
||||
// This is only a temporary / immediate solution to mitigate crashes
|
||||
// Still need to root-cause what is causing null pointers here
|
||||
//
|
||||
// AD: TODO what are we doing about this now that there is a fix? Can we "deprecate" this test?
|
||||
//
|
||||
// ### DEFENSIVE
|
||||
if(!isValid0 || !isValid1)
|
||||
return outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "NPhaseCore::runOverlapFilters: found null PxsShapeCore pointers!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// PT: called from OverlapFilterTask. This revisited implementation does not use a bitmap anymore.
|
||||
void NPhaseCore::runOverlapFilters( PxU32 nbToProcess, Bp::AABBOverlap* PX_RESTRICT pairs, FilterInfo* PX_RESTRICT filterInfo,
|
||||
PxU32& nbToKeep_, PxU32& nbToSuppress_) const
|
||||
{
|
||||
PxU32 nbToKeep = 0;
|
||||
PxU32 nbToSuppress = 0;
|
||||
|
||||
const PxU64 contextID = mOwnerScene.getContextId();
|
||||
|
||||
const FilteringContext context(mOwnerScene);
|
||||
|
||||
// PT: in this version we write out not just the filter info but also the pairs, and we skip the bitmap entirely. We just do
|
||||
// a local compaction of surviving pairs, similar to what happens later in Scene::preallocateContactManagers(), but only for a single task.
|
||||
PxU32 offset = 0;
|
||||
|
||||
for(PxU32 i=0; i<nbToProcess; i++)
|
||||
{
|
||||
const Bp::AABBOverlap& pair = pairs[i];
|
||||
|
||||
const ElementSim* e0 = reinterpret_cast<const ElementSim*>(pair.mUserData0);
|
||||
const ElementSim* e1 = reinterpret_cast<const ElementSim*>(pair.mUserData1);
|
||||
|
||||
if(!testElementSimPointers(e0, e1))
|
||||
continue;
|
||||
|
||||
PX_ASSERT(!findInteraction(e0, e1));
|
||||
|
||||
const ShapeSimBase* s0 = static_cast<const ShapeSimBase*>(e0);
|
||||
const ShapeSimBase* s1 = static_cast<const ShapeSimBase*>(e1);
|
||||
|
||||
if(!testShapeSimCorePointers(s0, s1))
|
||||
continue;
|
||||
|
||||
PX_ASSERT(&s0->getActor() != &s1->getActor()); // No actor internal interactions
|
||||
|
||||
FilterInfo& filters = filterInfo[offset];
|
||||
filters.setFilterFlags(PxFilterFlags(0));
|
||||
filters.mPairFlags = PxPairFlags(0);
|
||||
filters.mHasPairID = false;
|
||||
filterRbCollisionPairAllTests(filters, context, *s0, *s1, contextID);
|
||||
|
||||
const PxFilterFlags filterFlags = filters.getFilterFlags();
|
||||
|
||||
if(!(filterFlags & PxFilterFlag::eKILL))
|
||||
{
|
||||
if(!(filterFlags & PxFilterFlag::eSUPPRESS))
|
||||
nbToKeep++;
|
||||
else
|
||||
nbToSuppress++;
|
||||
|
||||
pairs[offset++] = pair;
|
||||
}
|
||||
}
|
||||
|
||||
nbToKeep_ = nbToKeep;
|
||||
nbToSuppress_ = nbToSuppress;
|
||||
}
|
||||
|
||||
ElementSimInteraction* NPhaseCore::createTriggerElementInteraction(ShapeSimBase& s0, ShapeSimBase& s1)
|
||||
{
|
||||
PX_ASSERT((s0.getFlags() & PxShapeFlag::eTRIGGER_SHAPE) || (s1.getFlags() & PxShapeFlag::eTRIGGER_SHAPE));
|
||||
|
||||
const FilteringContext context(mOwnerScene);
|
||||
|
||||
bool isTriggerPair;
|
||||
FilterInfo filterInfo;
|
||||
filterRbCollisionPair(filterInfo, context, s0, s1, isTriggerPair, false, mOwnerScene.getContextId());
|
||||
PX_ASSERT(isTriggerPair);
|
||||
|
||||
if(filterInfo.getFilterFlags() & PxFilterFlag::eKILL)
|
||||
{
|
||||
PX_ASSERT(!filterInfo.mHasPairID); // No filter callback pair info for killed pairs
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return createRbElementInteraction(filterInfo, s0, s1, NULL, NULL, NULL, isTriggerPair);
|
||||
}
|
||||
|
||||
void NPhaseCore::onTriggerOverlapCreated(const Bp::AABBOverlap* PX_RESTRICT pairs, PxU32 pairCount)
|
||||
{
|
||||
for(PxU32 i=0; i<pairCount; i++)
|
||||
{
|
||||
ElementSim* volume0 = reinterpret_cast<ElementSim*>(pairs[i].mUserData0);
|
||||
ElementSim* volume1 = reinterpret_cast<ElementSim*>(pairs[i].mUserData1);
|
||||
|
||||
if(!testElementSimPointers(volume0, volume1))
|
||||
continue;
|
||||
|
||||
PX_ASSERT(!findInteraction(volume0, volume1));
|
||||
|
||||
ShapeSimBase* shapeHi = static_cast<ShapeSimBase*>(volume1);
|
||||
ShapeSimBase* shapeLo = static_cast<ShapeSimBase*>(volume0);
|
||||
|
||||
// No actor internal interactions
|
||||
PX_ASSERT(&shapeHi->getActor() != &shapeLo->getActor());
|
||||
|
||||
// PT: this case is only for triggers these days
|
||||
PX_ASSERT((shapeLo->getFlags() & PxShapeFlag::eTRIGGER_SHAPE) || (shapeHi->getFlags() & PxShapeFlag::eTRIGGER_SHAPE));
|
||||
|
||||
createTriggerElementInteraction(*shapeHi, *shapeLo);
|
||||
}
|
||||
}
|
||||
|
||||
void NPhaseCore::callPairLost(const ShapeSimBase& s0, const ShapeSimBase& s1, bool objVolumeRemoved)
|
||||
{
|
||||
const PxFilterObjectAttributes fa0 = getFilterObjectAttributes<true>(s0);
|
||||
const PxFilterObjectAttributes fa1 = getFilterObjectAttributes<true>(s1);
|
||||
|
||||
const PxFilterData& fd0 = s0.getCore().getSimulationFilterData();
|
||||
const PxFilterData& fd1 = s1.getCore().getSimulationFilterData();
|
||||
|
||||
{
|
||||
// PT: TODO: should be called "onPairLost"
|
||||
PX_PROFILE_ZONE("USERCODE - PxSimulationFilterCallback::pairLost", mOwnerScene.getContextId());
|
||||
mOwnerScene.getFilterCallbackFast()->pairLost(getPairID(s0, s1), fa0, fd0, fa1, fd1, objVolumeRemoved);
|
||||
}
|
||||
}
|
||||
|
||||
ElementSimInteraction* NPhaseCore::refilterInteraction(ElementSimInteraction* pair, const FilterInfo* filterInfo, bool removeFromDirtyList, PxsContactManagerOutputIterator& outputs)
|
||||
{
|
||||
const InteractionType::Enum oldType = pair->getType();
|
||||
|
||||
switch (oldType)
|
||||
{
|
||||
case InteractionType::eTRIGGER:
|
||||
case InteractionType::eMARKER:
|
||||
case InteractionType::eOVERLAP:
|
||||
{
|
||||
ShapeSimBase& s0 = static_cast<ShapeSimBase&>(pair->getElement0());
|
||||
ShapeSimBase& s1 = static_cast<ShapeSimBase&>(pair->getElement1());
|
||||
|
||||
FilterInfo finfo;
|
||||
if(filterInfo)
|
||||
{
|
||||
// The filter changes are provided by an outside source (the user filter callback)
|
||||
|
||||
finfo = *filterInfo;
|
||||
PX_ASSERT(finfo.mHasPairID);
|
||||
|
||||
if((finfo.getFilterFlags() & PxFilterFlag::eKILL) &&
|
||||
((finfo.getFilterFlags() & PxFilterFlag::eNOTIFY) == PxFilterFlag::eNOTIFY) )
|
||||
{
|
||||
callPairLost(s0, s1, false);
|
||||
finfo.mHasPairID = false;
|
||||
}
|
||||
|
||||
ActorSim& bs0 = s0.getActor();
|
||||
ActorSim& bs1 = s1.getActor();
|
||||
|
||||
const bool isKinePair = PxFilterObjectIsKinematic(bs0.getFilterAttributes()) && PxFilterObjectIsKinematic(bs1.getFilterAttributes());
|
||||
finfo.mPairFlags = checkRbPairFlags(s0, s1, isKinePair, finfo.mPairFlags, finfo.getFilterFlags(), bs0.isNonRigid() || bs1.isNonRigid(), mOwnerScene.getFlags() & PxSceneFlag::eENABLE_DIRECT_GPU_API);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pair->readInteractionFlag(InteractionFlag::eIS_FILTER_PAIR))
|
||||
callPairLost(s0, s1, false);
|
||||
|
||||
const FilteringContext context(mOwnerScene);
|
||||
|
||||
bool isTriggerPair;
|
||||
filterRbCollisionPair(finfo, context, s0, s1, isTriggerPair, true, mOwnerScene.getContextId());
|
||||
PX_UNUSED(isTriggerPair);
|
||||
}
|
||||
|
||||
if(pair->readInteractionFlag(InteractionFlag::eIS_FILTER_PAIR) &&
|
||||
((finfo.getFilterFlags() & PxFilterFlag::eNOTIFY) != PxFilterFlag::eNOTIFY) )
|
||||
{
|
||||
// The pair was a filter callback pair but not any longer
|
||||
pair->clearInteractionFlag(InteractionFlag::eIS_FILTER_PAIR);
|
||||
|
||||
finfo.mHasPairID = false;
|
||||
}
|
||||
|
||||
struct Local
|
||||
{
|
||||
static InteractionType::Enum getRbElementInteractionType(const ShapeSimBase* primitive0, const ShapeSimBase* primitive1, PxFilterFlags filterFlag)
|
||||
{
|
||||
if(filterFlag & PxFilterFlag::eKILL)
|
||||
return InteractionType::eINVALID;
|
||||
|
||||
if(filterFlag & PxFilterFlag::eSUPPRESS)
|
||||
return InteractionType::eMARKER;
|
||||
|
||||
if(primitive0->getFlags() & PxShapeFlag::eTRIGGER_SHAPE
|
||||
|| primitive1->getFlags() & PxShapeFlag::eTRIGGER_SHAPE)
|
||||
return InteractionType::eTRIGGER;
|
||||
|
||||
PX_ASSERT( (primitive0->getGeometryType() != PxGeometryType::eTRIANGLEMESH) ||
|
||||
(primitive1->getGeometryType() != PxGeometryType::eTRIANGLEMESH));
|
||||
|
||||
return InteractionType::eOVERLAP;
|
||||
}
|
||||
};
|
||||
|
||||
const InteractionType::Enum newType = Local::getRbElementInteractionType(&s0, &s1, finfo.getFilterFlags());
|
||||
if(pair->getType() != newType) //Only convert interaction type if the type has changed
|
||||
{
|
||||
return convert(pair, newType, finfo, removeFromDirtyList, outputs);
|
||||
}
|
||||
else
|
||||
{
|
||||
//The pair flags might have changed, we need to forward the new ones
|
||||
if(oldType == InteractionType::eOVERLAP)
|
||||
{
|
||||
ShapeInteraction* si = static_cast<ShapeInteraction*>(pair);
|
||||
|
||||
const PxU32 newPairFlags = finfo.mPairFlags;
|
||||
const PxU32 oldPairFlags = si->getPairFlags();
|
||||
PX_ASSERT((newPairFlags & ShapeInteraction::PAIR_FLAGS_MASK) == newPairFlags);
|
||||
PX_ASSERT((oldPairFlags & ShapeInteraction::PAIR_FLAGS_MASK) == oldPairFlags);
|
||||
|
||||
if(newPairFlags != oldPairFlags)
|
||||
{
|
||||
if(!(oldPairFlags & ShapeInteraction::CONTACT_REPORT_EVENTS) && (newPairFlags & ShapeInteraction::CONTACT_REPORT_EVENTS) && (si->getActorPair() == NULL || !si->getActorPair()->isReportPair()))
|
||||
{
|
||||
// for this actor pair there was no shape pair that requested contact reports but now there is one
|
||||
// -> all the existing shape pairs need to get re-adjusted to point to an ActorPairReport instance instead.
|
||||
ActorPair* actorPair = findActorPair(&s0, &s1, PxIntTrue);
|
||||
if (si->getActorPair() == NULL)
|
||||
{
|
||||
actorPair->incRefCount();
|
||||
si->setActorPair(*actorPair);
|
||||
}
|
||||
}
|
||||
|
||||
if(si->readFlag(ShapeInteraction::IN_PERSISTENT_EVENT_LIST) && (!(newPairFlags & PxPairFlag::eNOTIFY_TOUCH_PERSISTS)))
|
||||
{
|
||||
// the new report pair flags don't require persistent checks anymore -> remove from persistent list
|
||||
// Note: The pair might get added to the force threshold list later
|
||||
if(si->readFlag(ShapeInteraction::IS_IN_PERSISTENT_EVENT_LIST))
|
||||
removeFromPersistentContactEventPairs(si);
|
||||
else
|
||||
si->clearFlag(ShapeInteraction::WAS_IN_PERSISTENT_EVENT_LIST);
|
||||
}
|
||||
|
||||
if(newPairFlags & ShapeInteraction::CONTACT_FORCE_THRESHOLD_PAIRS)
|
||||
{
|
||||
PX_ASSERT((si->mReportPairIndex == INVALID_REPORT_PAIR_ID) || (!si->readFlag(ShapeInteraction::WAS_IN_PERSISTENT_EVENT_LIST)));
|
||||
|
||||
if(si->mReportPairIndex == INVALID_REPORT_PAIR_ID && si->readInteractionFlag(InteractionFlag::eIS_ACTIVE))
|
||||
{
|
||||
PX_ASSERT(!si->readFlag(ShapeInteraction::WAS_IN_PERSISTENT_EVENT_LIST)); // sanity check: an active pair should never have this flag set
|
||||
|
||||
if(si->hasTouch())
|
||||
addToForceThresholdContactEventPairs(si);
|
||||
}
|
||||
}
|
||||
else if((oldPairFlags & ShapeInteraction::CONTACT_FORCE_THRESHOLD_PAIRS))
|
||||
{
|
||||
// no force threshold events needed any longer -> clear flags
|
||||
si->clearFlag(ShapeInteraction::FORCE_THRESHOLD_EXCEEDED_FLAGS);
|
||||
|
||||
if(si->readFlag(ShapeInteraction::IS_IN_FORCE_THRESHOLD_EVENT_LIST))
|
||||
removeFromForceThresholdContactEventPairs(si);
|
||||
}
|
||||
}
|
||||
si->setPairFlags(finfo.mPairFlags);
|
||||
}
|
||||
else if(oldType == InteractionType::eTRIGGER)
|
||||
static_cast<TriggerInteraction*>(pair)->setTriggerFlags(finfo.mPairFlags);
|
||||
|
||||
return pair;
|
||||
}
|
||||
}
|
||||
case InteractionType::eCONSTRAINTSHADER:
|
||||
case InteractionType::eARTICULATION:
|
||||
case InteractionType::eTRACKED_IN_SCENE_COUNT:
|
||||
case InteractionType::eINVALID:
|
||||
PX_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool callStatusChange(PxSimulationFilterCallback* callback, PxU64& pairID, PxPairFlags& pairFlags, PxFilterFlags& filterFlags, PxU64 contextID)
|
||||
{
|
||||
PX_UNUSED(contextID);
|
||||
// PT: TODO: should be called "onStatusChange"
|
||||
PX_PROFILE_ZONE("USERCODE - PxSimulationFilterCallback::statusChange", contextID);
|
||||
return callback->statusChange(pairID, pairFlags, filterFlags);
|
||||
}
|
||||
|
||||
void NPhaseCore::fireCustomFilteringCallbacks(PxsContactManagerOutputIterator& outputs)
|
||||
{
|
||||
PX_PROFILE_ZONE("Sim.fireCustomFilteringCallbacks", mOwnerScene.getContextId());
|
||||
|
||||
PxSimulationFilterCallback* callback = mOwnerScene.getFilterCallbackFast();
|
||||
|
||||
if(callback)
|
||||
{
|
||||
const PxU64 contextID = mOwnerScene.getContextId();
|
||||
|
||||
// Ask user for pair filter status changes
|
||||
PxU64 pairID;
|
||||
PxFilterFlags filterFlags;
|
||||
PxPairFlags pairFlags;
|
||||
while(callStatusChange(callback, pairID, pairFlags, filterFlags, contextID))
|
||||
{
|
||||
const PxU32 id0 = PxU32(pairID);
|
||||
const PxU32 id1 = PxU32(pairID>>32);
|
||||
const PxHashMap<ElementSimKey, ElementSimInteraction*>::Entry* pair = mElementSimMap.find(ElementSimKey(id0, id1));
|
||||
ElementSimInteraction* ei = pair ? pair->second : NULL;
|
||||
PX_ASSERT(ei);
|
||||
// Check if the user tries to update a pair even though he deleted it earlier in the same frame
|
||||
|
||||
checkFilterFlags(filterFlags);
|
||||
|
||||
PX_ASSERT(ei->readInteractionFlag(InteractionFlag::eIS_FILTER_PAIR));
|
||||
|
||||
FilterInfo finfo;
|
||||
finfo.setFilterFlags(filterFlags);
|
||||
finfo.mPairFlags = pairFlags;
|
||||
finfo.mHasPairID = true;
|
||||
ElementSimInteraction* refInt = refilterInteraction(ei, &finfo, true, outputs);
|
||||
|
||||
// this gets called at the end of the simulation -> there should be no dirty interactions around
|
||||
PX_ASSERT(!refInt->readInteractionFlag(InteractionFlag::eIN_DIRTY_LIST));
|
||||
PX_ASSERT(!refInt->getDirtyFlags());
|
||||
|
||||
if((refInt == ei) && (refInt->getType() == InteractionType::eOVERLAP)) // No interaction conversion happened, the pairFlags were just updated
|
||||
static_cast<ShapeInteraction*>(refInt)->updateState(InteractionDirtyFlag::eFILTER_STATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
60
engine/third_party/physx/source/simulationcontroller/src/ScFiltering.h
vendored
Normal file
60
engine/third_party/physx/source/simulationcontroller/src/ScFiltering.h
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_FILTERING_H
|
||||
#define SC_FILTERING_H
|
||||
|
||||
#include "PxFiltering.h"
|
||||
#include "foundation/PxUtilities.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
struct FilterInfo
|
||||
{
|
||||
PX_FORCE_INLINE FilterInfo() : mPairFlags(0), mFilterFlags8(0), mHasPairID(false) {}
|
||||
PX_FORCE_INLINE FilterInfo(PxFilterFlags filterFlags) : mPairFlags(0), mFilterFlags8(filterFlags), mHasPairID(false) {}
|
||||
|
||||
PX_FORCE_INLINE PxFilterFlags getFilterFlags() const { return PxFilterFlags(mFilterFlags8); }
|
||||
PX_FORCE_INLINE void setFilterFlags(PxFilterFlags flags) { mFilterFlags8 = PxTo8(PxU16(flags)); }
|
||||
PX_FORCE_INLINE void clearFilterFlags(PxFilterFlag::Enum flag)
|
||||
{
|
||||
PxFilterFlags flags = getFilterFlags();
|
||||
flags.clear(flag);
|
||||
setFilterFlags(flags);
|
||||
}
|
||||
|
||||
PxPairFlags mPairFlags;
|
||||
PxU8 mFilterFlags8; // PT: PxFilterFlags but only using 8 bits
|
||||
PxU8 mHasPairID;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
69
engine/third_party/physx/source/simulationcontroller/src/ScGpuActorSim.cpp
vendored
Normal file
69
engine/third_party/physx/source/simulationcontroller/src/ScGpuActorSim.cpp
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScGpuActorSim.h"
|
||||
#include "ScNPhaseCore.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
Sc::GPUActorSim::GPUActorSim(Scene& scene, ActorCore& core, const ShapeCore* shapeCore) :
|
||||
ActorSim (scene, core),
|
||||
mShapeSim (*this, shapeCore)
|
||||
{
|
||||
}
|
||||
|
||||
Sc::GPUActorSim::~GPUActorSim()
|
||||
{
|
||||
destroyLowLevelVolume();
|
||||
}
|
||||
|
||||
void Sc::GPUActorSim::addToAABBMgr(Bp::FilterType::Enum type)
|
||||
{
|
||||
const PxReal contactOffset = mShapeSim.getContactOffset();
|
||||
mShapeSim.addToAABBMgr(contactOffset, type);
|
||||
|
||||
const PxU32 index = mShapeSim.getElementID();
|
||||
mScene.updateContactDistance(index, contactOffset);
|
||||
|
||||
PxsTransformCache& cache = mScene.getLowLevelContext()->getTransformCache();
|
||||
cache.initEntry(index);
|
||||
|
||||
cache.setTransformCache(PxTransform(PxIdentity), 0, index, index);
|
||||
}
|
||||
|
||||
void Sc::GPUActorSim::destroyLowLevelVolume()
|
||||
{
|
||||
if(mShapeSim.isInBroadPhase())
|
||||
{
|
||||
PxsContactManagerOutputIterator outputs = mScene.getLowLevelContext()->getNphaseImplementationContext()->getContactManagerOutputs();
|
||||
mScene.getNPhaseCore()->onVolumeRemoved(&mShapeSim, 0, outputs);
|
||||
mShapeSim.removeFromAABBMgr();
|
||||
}
|
||||
PX_ASSERT(!mShapeSim.isInBroadPhase());
|
||||
}
|
||||
56
engine/third_party/physx/source/simulationcontroller/src/ScGpuActorSim.h
vendored
Normal file
56
engine/third_party/physx/source/simulationcontroller/src/ScGpuActorSim.h
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_GPU_ACTOR_SIM_H
|
||||
#define SC_GPU_ACTOR_SIM_H
|
||||
|
||||
#include "ScActorSim.h"
|
||||
#include "ScShapeSimBase.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class GPUActorSim : public ActorSim
|
||||
{
|
||||
public:
|
||||
ShapeSimBase mShapeSim;
|
||||
|
||||
GPUActorSim(Scene& scene, ActorCore& core, const ShapeCore* shapeCore);
|
||||
virtual ~GPUActorSim();
|
||||
|
||||
const ShapeSimBase& getShapeSim() const { return mShapeSim; }
|
||||
ShapeSimBase& getShapeSim() { return mShapeSim; }
|
||||
|
||||
void addToAABBMgr(Bp::FilterType::Enum type);
|
||||
void destroyLowLevelVolume();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
69
engine/third_party/physx/source/simulationcontroller/src/ScInteraction.cpp
vendored
Normal file
69
engine/third_party/physx/source/simulationcontroller/src/ScInteraction.cpp
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#include "ScInteraction.h"
|
||||
#include "ScNPhaseCore.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::Interaction::Interaction(ActorSim& actor0, ActorSim& actor1, InteractionType::Enum type, PxU8 flags) :
|
||||
mActor0 (actor0),
|
||||
mActor1 (actor1),
|
||||
mSceneId (PX_INVALID_INTERACTION_SCENE_ID),
|
||||
mActorId0 (PX_INVALID_INTERACTION_ACTOR_ID),
|
||||
mActorId1 (PX_INVALID_INTERACTION_ACTOR_ID),
|
||||
mInteractionType (PxTo8(type)),
|
||||
mInteractionFlags (flags),
|
||||
mDirtyFlags (0)
|
||||
{
|
||||
PX_ASSERT_WITH_MESSAGE(&actor0.getScene() == &actor1.getScene(),"Cannot create an interaction between actors belonging to different scenes.");
|
||||
PX_ASSERT(PxU32(type)<256); // PT: type is now stored on a byte
|
||||
}
|
||||
|
||||
void Sc::Interaction::addToDirtyList()
|
||||
{
|
||||
getActorSim0().getScene().getNPhaseCore()->addToDirtyInteractionList(this);
|
||||
}
|
||||
|
||||
void Sc::Interaction::removeFromDirtyList()
|
||||
{
|
||||
getActorSim0().getScene().getNPhaseCore()->removeFromDirtyInteractionList(this);
|
||||
}
|
||||
|
||||
void Sc::Interaction::setClean(bool removeFromList)
|
||||
{
|
||||
if (readInteractionFlag(InteractionFlag::eIN_DIRTY_LIST))
|
||||
{
|
||||
if (removeFromList) // if we process all dirty interactions anyway, then we can just clear the list at the end and save the work here.
|
||||
removeFromDirtyList();
|
||||
clearInteractionFlag(InteractionFlag::eIN_DIRTY_LIST);
|
||||
}
|
||||
|
||||
mDirtyFlags = 0;
|
||||
}
|
||||
205
engine/third_party/physx/source/simulationcontroller/src/ScInteraction.h
vendored
Normal file
205
engine/third_party/physx/source/simulationcontroller/src/ScInteraction.h
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_INTERACTION_H
|
||||
#define SC_INTERACTION_H
|
||||
|
||||
#include "ScInteractionFlags.h"
|
||||
#include "ScActorSim.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "foundation/PxUtilities.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
#define PX_INVALID_INTERACTION_ACTOR_ID 0xffffffff
|
||||
#define PX_INVALID_INTERACTION_SCENE_ID 0xffffffff
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
struct InteractionType
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eOVERLAP = 0, // corresponds to ShapeInteraction
|
||||
eTRIGGER, // corresponds to TriggerInteraction
|
||||
eMARKER, // corresponds to ElementInteractionMarker
|
||||
eTRACKED_IN_SCENE_COUNT, // not a real type, interactions above this limit are tracked in the scene
|
||||
eCONSTRAINTSHADER, // corresponds to ConstraintInteraction
|
||||
eARTICULATION, // corresponds to ArticulationJointSim
|
||||
|
||||
eINVALID
|
||||
};
|
||||
};
|
||||
|
||||
// Interactions are used for connecting actors into activation groups. An interaction always connects exactly two actors.
|
||||
// An interaction is implicitly active if at least one of the two actors it connects is active.
|
||||
|
||||
class Interaction
|
||||
{
|
||||
PX_NOCOPY(Interaction)
|
||||
Interaction(ActorSim& actor0, ActorSim& actor1, InteractionType::Enum interactionType, PxU8 flags);
|
||||
~Interaction() { PX_ASSERT(!readInteractionFlag(InteractionFlag::eIN_DIRTY_LIST)); }
|
||||
public:
|
||||
// Interactions automatically register themselves in the actors here
|
||||
PX_FORCE_INLINE void registerInActors();
|
||||
|
||||
// Interactions automatically unregister themselves from the actors here
|
||||
PX_FORCE_INLINE void unregisterFromActors();
|
||||
|
||||
PX_FORCE_INLINE ActorSim& getActorSim0() const { return mActor0; }
|
||||
PX_FORCE_INLINE ActorSim& getActorSim1() const { return mActor1; }
|
||||
|
||||
PX_FORCE_INLINE Scene& getScene() const { return mActor0.getScene(); }
|
||||
|
||||
PX_FORCE_INLINE InteractionType::Enum getType() const { return InteractionType::Enum(mInteractionType); }
|
||||
|
||||
PX_FORCE_INLINE PxU8 readInteractionFlag(PxU8 flag) const { return PxU8(mInteractionFlags & flag); }
|
||||
PX_FORCE_INLINE void raiseInteractionFlag(InteractionFlag::Enum flag) { mInteractionFlags |= flag; }
|
||||
PX_FORCE_INLINE void clearInteractionFlag(InteractionFlag::Enum flag) { mInteractionFlags &= ~flag; }
|
||||
|
||||
/**
|
||||
\brief Mark the interaction as dirty. This will put the interaction into a list that is processed once per simulation step.
|
||||
|
||||
\see InteractionDirtyFlag
|
||||
*/
|
||||
PX_FORCE_INLINE void setDirty(PxU32 dirtyFlags);
|
||||
|
||||
/**
|
||||
\brief Clear all flags that mark the interaction as dirty and optionally remove the interaction from the list of dirty interactions.
|
||||
|
||||
\see InteractionDirtyFlag
|
||||
*/
|
||||
/*PX_FORCE_INLINE*/ void setClean(bool removeFromList);
|
||||
|
||||
PX_FORCE_INLINE PxIntBool needsRefiltering() const { return (getDirtyFlags() & InteractionDirtyFlag::eFILTER_STATE); }
|
||||
|
||||
PX_FORCE_INLINE PxIntBool isElementInteraction() const;
|
||||
|
||||
PX_FORCE_INLINE void setInteractionId(PxU32 id) { mSceneId = id; }
|
||||
PX_FORCE_INLINE PxU32 getInteractionId() const { return mSceneId; }
|
||||
PX_FORCE_INLINE bool isRegistered() const { return mSceneId != PX_INVALID_INTERACTION_SCENE_ID; }
|
||||
|
||||
PX_FORCE_INLINE void setActorId(ActorSim* actor, PxU32 id);
|
||||
PX_FORCE_INLINE PxU32 getActorId(const ActorSim* actor) const;
|
||||
|
||||
PX_FORCE_INLINE PxU8 getDirtyFlags() const { return mDirtyFlags; }
|
||||
|
||||
private:
|
||||
void addToDirtyList();
|
||||
void removeFromDirtyList();
|
||||
|
||||
ActorSim& mActor0;
|
||||
ActorSim& mActor1;
|
||||
|
||||
// PT: TODO: merge the 6bits of the 3 PxU8s in the top bits of the 3 PxU32s
|
||||
PxU32 mSceneId; // PT: TODO: merge this with mInteractionType
|
||||
|
||||
// PT: TODO: are those IDs even worth caching? Since the number of interactions per actor is (or should be) small,
|
||||
// we could just do a linear search and save memory here...
|
||||
PxU32 mActorId0; // PT: id of this interaction within mActor0's mInteractions array
|
||||
PxU32 mActorId1; // PT: id of this interaction within mActor1's mInteractions array
|
||||
protected:
|
||||
const PxU8 mInteractionType; // PT: stored on a byte to save space, should be InteractionType enum, 5/6 bits needed here
|
||||
PxU8 mInteractionFlags; // PT: 6 bits needed here, see InteractionFlag enum
|
||||
PxU8 mDirtyFlags; // PT: 5 bits needed here, see InteractionDirtyFlag enum
|
||||
PxU8 mPadding8;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PX_FORCE_INLINE void Sc::Interaction::registerInActors()
|
||||
{
|
||||
mActor0.registerInteractionInActor(this);
|
||||
mActor1.registerInteractionInActor(this);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void Sc::Interaction::unregisterFromActors()
|
||||
{
|
||||
mActor0.unregisterInteractionFromActor(this);
|
||||
mActor1.unregisterInteractionFromActor(this);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void Sc::Interaction::setActorId(ActorSim* actor, PxU32 id)
|
||||
{
|
||||
PX_ASSERT(id != PX_INVALID_INTERACTION_ACTOR_ID);
|
||||
PX_ASSERT(&mActor0 == actor || &mActor1 == actor);
|
||||
if(&mActor0 == actor)
|
||||
mActorId0 = id;
|
||||
else
|
||||
mActorId1 = id;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxU32 Sc::Interaction::getActorId(const ActorSim* actor) const
|
||||
{
|
||||
PX_ASSERT(&mActor0 == actor || &mActor1 == actor);
|
||||
return &mActor0 == actor ? mActorId0 : mActorId1;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxIntBool Sc::Interaction::isElementInteraction() const
|
||||
{
|
||||
const PxIntBool res = readInteractionFlag(InteractionFlag::eRB_ELEMENT);
|
||||
PX_ASSERT( (res &&
|
||||
((getType() == InteractionType::eOVERLAP) ||
|
||||
(getType() == InteractionType::eTRIGGER) ||
|
||||
(getType() == InteractionType::eMARKER))) ||
|
||||
(!res &&
|
||||
((getType() == InteractionType::eCONSTRAINTSHADER) ||
|
||||
(getType() == InteractionType::eARTICULATION))));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void Sc::Interaction::setDirty(PxU32 dirtyFlags)
|
||||
{
|
||||
PX_ASSERT(getType() != InteractionType::eARTICULATION);
|
||||
|
||||
mDirtyFlags |= PxTo8(dirtyFlags);
|
||||
if(!readInteractionFlag(InteractionFlag::eIN_DIRTY_LIST))
|
||||
{
|
||||
addToDirtyList();
|
||||
raiseInteractionFlag(InteractionFlag::eIN_DIRTY_LIST);
|
||||
}
|
||||
}
|
||||
|
||||
//PX_FORCE_INLINE void Sc::Interaction::setClean(bool removeFromList)
|
||||
//{
|
||||
// if (readInteractionFlag(InteractionFlag::eIN_DIRTY_LIST))
|
||||
// {
|
||||
// if (removeFromList) // if we process all dirty interactions anyway, then we can just clear the list at the end and save the work here.
|
||||
// removeFromDirtyList();
|
||||
// clearInteractionFlag(InteractionFlag::eIN_DIRTY_LIST);
|
||||
// }
|
||||
//
|
||||
// mDirtyFlags = 0;
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
71
engine/third_party/physx/source/simulationcontroller/src/ScInteractionFlags.h
vendored
Normal file
71
engine/third_party/physx/source/simulationcontroller/src/ScInteractionFlags.h
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_INTERACTION_FLAGS_H
|
||||
#define SC_INTERACTION_FLAGS_H
|
||||
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
struct InteractionFlag // PT: TODO: use PxFlags
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eRB_ELEMENT = (1 << 0), // Interactions between rigid body shapes
|
||||
eCONSTRAINT = (1 << 1),
|
||||
eFILTERABLE = (1 << 2), // Interactions that go through the filter code
|
||||
eIN_DIRTY_LIST = (1 << 3), // The interaction is in the dirty list
|
||||
eIS_FILTER_PAIR = (1 << 4), // The interaction is tracked by the filter callback mechanism
|
||||
eIS_ACTIVE = (1 << 5)
|
||||
};
|
||||
};
|
||||
|
||||
struct InteractionDirtyFlag
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eFILTER_STATE = (1 << 0), // All changes filtering related
|
||||
eBODY_KINEMATIC = (1 << 1) | eFILTER_STATE, // A transition between dynamic and kinematic (and vice versa) require a refiltering
|
||||
eDOMINANCE = (1 << 2),
|
||||
eREST_OFFSET = (1 << 3),
|
||||
eVISUALIZATION = (1 << 4)
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
|
||||
} // namespace physx
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
129
engine/third_party/physx/source/simulationcontroller/src/ScIterators.cpp
vendored
Normal file
129
engine/third_party/physx/source/simulationcontroller/src/ScIterators.cpp
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#include "ScIterators.h"
|
||||
#include "ScBodySim.h"
|
||||
#include "ScShapeSim.h"
|
||||
#include "ScShapeInteraction.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Sc::ContactIterator::Pair::Pair(const void*& contactPatches, const void*& contactPoints, const void*& frictionPatches, PxU32 /*contactDataSize*/, const PxReal*& forces, PxU32 numContacts, PxU32 numPatches,
|
||||
ShapeSimBase& shape0, ShapeSimBase& shape1, ActorSim* actor0, ActorSim* actor1)
|
||||
: mIndex(0)
|
||||
, mNumContacts(numContacts)
|
||||
, mIter(reinterpret_cast<const PxU8*>(contactPatches), reinterpret_cast<const PxU8*>(contactPoints), reinterpret_cast<const PxU32*>(forces + numContacts), numPatches, numContacts)
|
||||
, mAnchorIter(reinterpret_cast<const PxU8*>(contactPatches), reinterpret_cast<const PxU8*>(frictionPatches), numPatches)
|
||||
, mForces(forces)
|
||||
, mActor0(actor0->getPxActor())
|
||||
, mActor1(actor1->getPxActor())
|
||||
{
|
||||
mCurrentContact.shape0 = shape0.getPxShape();
|
||||
mCurrentContact.shape1 = shape1.getPxShape();
|
||||
mCurrentContact.normalForceAvailable = (forces != NULL);
|
||||
}
|
||||
|
||||
Sc::ContactIterator::Pair* Sc::ContactIterator::getNextPair()
|
||||
{
|
||||
PX_ASSERT(mCurrent || (mCurrent == mLast));
|
||||
if(mCurrent < mLast)
|
||||
{
|
||||
ShapeInteraction* si = static_cast<ShapeInteraction*>(*mCurrent);
|
||||
|
||||
const void* contactPatches = NULL;
|
||||
const void* contactPoints = NULL;
|
||||
PxU32 contactDataSize = 0;
|
||||
const PxReal* forces = NULL;
|
||||
PxU32 numContacts = 0;
|
||||
PxU32 numPatches = 0;
|
||||
const void* frictionPatches = NULL;
|
||||
|
||||
PxU32 nextOffset = si->getContactPointData(contactPatches, contactPoints, contactDataSize, numContacts, numPatches, forces, mOffset, *mOutputs, frictionPatches);
|
||||
|
||||
if (nextOffset == mOffset)
|
||||
++mCurrent;
|
||||
else
|
||||
mOffset = nextOffset;
|
||||
|
||||
mCurrentPair = Pair(contactPatches, contactPoints, frictionPatches, contactDataSize, forces, numContacts, numPatches, si->getShape0(), si->getShape1(), &si->getActorSim0(), &si->getActorSim1());
|
||||
return &mCurrentPair;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Sc::Contact* Sc::ContactIterator::Pair::getNextContact()
|
||||
{
|
||||
if(mIndex < mNumContacts)
|
||||
{
|
||||
while (!mIter.hasNextContact())
|
||||
{
|
||||
if(!mIter.hasNextPatch())
|
||||
return NULL;
|
||||
mIter.nextPatch();
|
||||
}
|
||||
mIter.nextContact();
|
||||
|
||||
mCurrentContact.normal = mIter.getContactNormal();
|
||||
mCurrentContact.point = mIter.getContactPoint();
|
||||
mCurrentContact.separation = mIter.getSeparation();
|
||||
mCurrentContact.normalForce = mForces ? mForces[mIndex] : 0;
|
||||
mCurrentContact.faceIndex0 = mIter.getFaceIndex0();
|
||||
mCurrentContact.faceIndex1 = mIter.getFaceIndex1();
|
||||
|
||||
mIndex++;
|
||||
return &mCurrentContact;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Sc::FrictionAnchor* Sc::ContactIterator::Pair::getNextFrictionAnchor()
|
||||
{
|
||||
if(mAnchorIter.hasNextPatch())
|
||||
{
|
||||
while (!mAnchorIter.hasNextFrictionAnchor())
|
||||
{
|
||||
if(!mAnchorIter.hasNextPatch())
|
||||
return NULL;
|
||||
mAnchorIter.nextPatch();
|
||||
}
|
||||
mAnchorIter.nextFrictionAnchor();
|
||||
|
||||
mCurrentAnchor.normal = mAnchorIter.getNormal();
|
||||
mCurrentAnchor.point = mAnchorIter.getPosition();
|
||||
mCurrentAnchor.impulse = mAnchorIter.getImpulse();
|
||||
|
||||
return &mCurrentAnchor;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
470
engine/third_party/physx/source/simulationcontroller/src/ScKinematics.cpp
vendored
Normal file
470
engine/third_party/physx/source/simulationcontroller/src/ScKinematics.cpp
vendored
Normal file
@@ -0,0 +1,470 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "common/PxProfileZone.h"
|
||||
#include "ScScene.h"
|
||||
#include "ScBodySim.h"
|
||||
#include "ScShapeSim.h"
|
||||
#include "PxsSimulationController.h"
|
||||
#include "BpAABBManagerBase.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
//PX_IMPLEMENT_OUTPUT_ERROR
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PT: TODO: consider using a non-member function for this one
|
||||
void BodySim::calculateKinematicVelocity(PxReal oneOverDt)
|
||||
{
|
||||
PX_ASSERT(isKinematic());
|
||||
|
||||
/*------------------------------------------------\
|
||||
| kinematic bodies are moved directly by the user and are not influenced by external forces
|
||||
| we simply determine the distance moved since the last simulation frame and
|
||||
| assign the appropriate delta to the velocity. This vel will be used to shove dynamic
|
||||
| objects in the solver.
|
||||
| We have to do this like so in a delayed way, because when the user sets the target pos the dt is not
|
||||
| yet known.
|
||||
\------------------------------------------------*/
|
||||
PX_ASSERT(isActive());
|
||||
|
||||
BodyCore& core = getBodyCore();
|
||||
|
||||
if (readInternalFlag(BF_KINEMATIC_MOVED))
|
||||
{
|
||||
clearInternalFlag(InternalFlags(BF_KINEMATIC_SETTLING | BF_KINEMATIC_SETTLING_2));
|
||||
const SimStateData* kData = getSimStateData(true);
|
||||
PX_ASSERT(kData);
|
||||
PX_ASSERT(kData->isKine());
|
||||
PX_ASSERT(kData->getKinematicData()->targetValid);
|
||||
PxVec3 linVelLL, angVelLL;
|
||||
const PxTransform targetPose = kData->getKinematicData()->targetPose;
|
||||
const PxTransform& currBody2World = getBody2World();
|
||||
|
||||
//the kinematic target pose is now the target of the body (CoM) and not the actor.
|
||||
|
||||
PxVec3 deltaPos = targetPose.p;
|
||||
deltaPos -= currBody2World.p;
|
||||
linVelLL = deltaPos * oneOverDt;
|
||||
|
||||
PxQuat q = targetPose.q * currBody2World.q.getConjugate();
|
||||
|
||||
if (q.w < 0) //shortest angle.
|
||||
q = -q;
|
||||
|
||||
PxReal angle;
|
||||
PxVec3 axis;
|
||||
q.toRadiansAndUnitAxis(angle, axis);
|
||||
angVelLL = axis * angle * oneOverDt;
|
||||
|
||||
core.getCore().linearVelocity = linVelLL;
|
||||
core.getCore().angularVelocity = angVelLL;
|
||||
|
||||
// Moving a kinematic should trigger a wakeUp call on a higher level.
|
||||
PX_ASSERT(core.getWakeCounter()>0);
|
||||
PX_ASSERT(isActive());
|
||||
|
||||
}
|
||||
else if (!readInternalFlag(BF_KINEMATIC_SURFACE_VELOCITY))
|
||||
{
|
||||
core.setLinearVelocity(PxVec3(0.0f), true);
|
||||
core.setAngularVelocity(PxVec3(0.0f), true);
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class ScKinematicUpdateTask : public Cm::Task
|
||||
{
|
||||
Sc::BodyCore*const* mKinematics;
|
||||
const PxU32 mNbKinematics;
|
||||
const PxReal mOneOverDt;
|
||||
|
||||
PX_NOCOPY(ScKinematicUpdateTask)
|
||||
public:
|
||||
|
||||
static const PxU32 NbKinematicsPerTask = 1024;
|
||||
|
||||
ScKinematicUpdateTask(Sc::BodyCore*const* kinematics, PxU32 nbKinematics, PxReal oneOverDt, PxU64 contextID) :
|
||||
Cm::Task(contextID), mKinematics(kinematics), mNbKinematics(nbKinematics), mOneOverDt(oneOverDt)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void runInternal()
|
||||
{
|
||||
Sc::BodyCore*const* kinematics = mKinematics;
|
||||
PxU32 nb = mNbKinematics;
|
||||
const float oneOverDt = mOneOverDt;
|
||||
|
||||
while(nb--)
|
||||
{
|
||||
Sc::BodyCore* b = *kinematics++;
|
||||
PX_ASSERT(b->getSim()->isKinematic());
|
||||
PX_ASSERT(b->getSim()->isActive());
|
||||
|
||||
b->getSim()->calculateKinematicVelocity(oneOverDt);
|
||||
}
|
||||
}
|
||||
|
||||
virtual const char* getName() const
|
||||
{
|
||||
return "ScScene.KinematicUpdateTask";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void Sc::Scene::kinematicsSetup(PxBaseTask* continuation)
|
||||
{
|
||||
const PxU32 nbKinematics = getActiveKinematicBodiesCount();
|
||||
if(!nbKinematics)
|
||||
return;
|
||||
|
||||
BodyCore*const* kinematics = getActiveKinematicBodies();
|
||||
|
||||
// PT: create a copy of active bodies for the taks to operate on while the main array is
|
||||
// potentially resized by operations running in parallel.
|
||||
if(mActiveKinematicsCopyCapacity<nbKinematics)
|
||||
{
|
||||
PX_FREE(mActiveKinematicsCopy);
|
||||
mActiveKinematicsCopy = PX_ALLOCATE(BodyCore*, nbKinematics, "Sc::Scene::mActiveKinematicsCopy");
|
||||
mActiveKinematicsCopyCapacity = nbKinematics;
|
||||
}
|
||||
PxMemCopy(mActiveKinematicsCopy, kinematics, nbKinematics*sizeof(BodyCore*));
|
||||
kinematics = mActiveKinematicsCopy;
|
||||
|
||||
Cm::FlushPool& flushPool = mLLContext->getTaskPool();
|
||||
|
||||
// PT: TASK-CREATION TAG
|
||||
// PT: TODO: better load balancing? This will be single threaded for less than 1K kinematics
|
||||
for(PxU32 i = 0; i < nbKinematics; i += ScKinematicUpdateTask::NbKinematicsPerTask)
|
||||
{
|
||||
ScKinematicUpdateTask* task = PX_PLACEMENT_NEW(flushPool.allocate(sizeof(ScKinematicUpdateTask)), ScKinematicUpdateTask)
|
||||
(kinematics + i, PxMin(ScKinematicUpdateTask::NbKinematicsPerTask, nbKinematics - i), mOneOverDt, mContextId);
|
||||
|
||||
task->setContinuation(continuation);
|
||||
task->removeReference();
|
||||
}
|
||||
|
||||
if((mPublicFlags & PxSceneFlag::eENABLE_GPU_DYNAMICS))
|
||||
{
|
||||
// PT: running this serially for now because it's unsafe: mNPhaseCore->updateDirtyInteractions() (called after this)
|
||||
// can also call mSimulationController.updateDynamic() via BodySim::internalWakeUpBase
|
||||
PxU32 nb = nbKinematics;
|
||||
while(nb--)
|
||||
{
|
||||
Sc::BodyCore* b = *kinematics++;
|
||||
Sc::BodySim* bodySim = b->getSim();
|
||||
PX_ASSERT(!bodySim->getArticulation());
|
||||
mSimulationController->updateDynamic(NULL, bodySim->getNodeIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PT: TODO: consider using a non-member function for this one
|
||||
void BodySim::updateKinematicPose()
|
||||
{
|
||||
/*------------------------------------------------\
|
||||
| kinematic bodies are moved directly by the user and are not influenced by external forces
|
||||
| we simply determine the distance moved since the last simulation frame and
|
||||
| assign the appropriate delta to the velocity. This vel will be used to shove dynamic
|
||||
| objects in the solver.
|
||||
| We have to do this like so in a delayed way, because when the user sets the target pos the dt is not
|
||||
| yet known.
|
||||
\------------------------------------------------*/
|
||||
|
||||
PX_ASSERT(isKinematic());
|
||||
PX_ASSERT(isActive());
|
||||
|
||||
if(readInternalFlag(BF_KINEMATIC_MOVED))
|
||||
{
|
||||
clearInternalFlag(InternalFlags(BF_KINEMATIC_SETTLING | BF_KINEMATIC_SETTLING_2));
|
||||
const SimStateData* kData = getSimStateData(true);
|
||||
PX_ASSERT(kData);
|
||||
PX_ASSERT(kData->isKine());
|
||||
PX_ASSERT(kData->getKinematicData()->targetValid);
|
||||
|
||||
const PxTransform targetPose = kData->getKinematicData()->targetPose;
|
||||
getBodyCore().getCore().body2World = targetPose;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class ScKinematicPoseUpdateTask : public Cm::Task
|
||||
{
|
||||
Sc::BodyCore*const* mKinematics;
|
||||
const PxU32 mNbKinematics;
|
||||
|
||||
PX_NOCOPY(ScKinematicPoseUpdateTask)
|
||||
public:
|
||||
static const PxU32 NbKinematicsPerTask = 1024;
|
||||
|
||||
ScKinematicPoseUpdateTask(Sc::BodyCore*const* kinematics, PxU32 nbKinematics, PxU64 contextID) :
|
||||
Cm::Task(contextID), mKinematics(kinematics), mNbKinematics(nbKinematics)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void runInternal()
|
||||
{
|
||||
const PxU32 nb = mNbKinematics;
|
||||
|
||||
for(PxU32 a=0; a<nb; ++a)
|
||||
{
|
||||
if ((a + 16) < nb)
|
||||
{
|
||||
PxPrefetchLine(static_cast<Sc::BodyCore* const>(mKinematics[a + 16]));
|
||||
|
||||
if ((a + 4) < nb)
|
||||
{
|
||||
PxPrefetchLine(static_cast<Sc::BodyCore* const>(mKinematics[a + 4])->getSim());
|
||||
PxPrefetchLine(static_cast<Sc::BodyCore* const>(mKinematics[a + 4])->getSim()->getSimStateData_Unchecked());
|
||||
}
|
||||
}
|
||||
Sc::BodyCore* b = static_cast<Sc::BodyCore* const>(mKinematics[a]);
|
||||
PX_ASSERT(b->getSim()->isKinematic());
|
||||
PX_ASSERT(b->getSim()->isActive());
|
||||
b->getSim()->updateKinematicPose();
|
||||
}
|
||||
}
|
||||
|
||||
virtual const char* getName() const
|
||||
{
|
||||
return "ScScene.ScKinematicPoseUpdateTask";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void Sc::Scene::integrateKinematicPose()
|
||||
{
|
||||
PX_PROFILE_ZONE("Sim.integrateKinematicPose", mContextId);
|
||||
|
||||
const PxU32 nbKinematics = getActiveKinematicBodiesCount();
|
||||
BodyCore*const* kinematics = getActiveKinematicBodies();
|
||||
|
||||
Cm::FlushPool& flushPool = mLLContext->getTaskPool();
|
||||
|
||||
// PT: TASK-CREATION TAG
|
||||
for(PxU32 i=0; i<nbKinematics; i+= ScKinematicPoseUpdateTask::NbKinematicsPerTask)
|
||||
{
|
||||
ScKinematicPoseUpdateTask* task = PX_PLACEMENT_NEW(flushPool.allocate(sizeof(ScKinematicPoseUpdateTask)), ScKinematicPoseUpdateTask)
|
||||
(kinematics + i, PxMin(nbKinematics - i, ScKinematicPoseUpdateTask::NbKinematicsPerTask), mContextId);
|
||||
task->setContinuation(&mAfterIntegration);
|
||||
task->removeReference();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
class ScKinematicShapeUpdateTask : public Cm::Task
|
||||
{
|
||||
Sc::BodyCore*const* mKinematics;
|
||||
const PxU32 mNbKinematics;
|
||||
PxsTransformCache& mCache;
|
||||
Bp::BoundsArray& mBoundsArray;
|
||||
|
||||
PX_NOCOPY(ScKinematicShapeUpdateTask)
|
||||
public:
|
||||
static const PxU32 NbKinematicsShapesPerTask = 1024;
|
||||
|
||||
ScKinematicShapeUpdateTask(Sc::BodyCore*const* kinematics, PxU32 nbKinematics, PxsTransformCache& cache, Bp::BoundsArray& boundsArray, PxU64 contextID) :
|
||||
Cm::Task(contextID), mKinematics(kinematics), mNbKinematics(nbKinematics), mCache(cache), mBoundsArray(boundsArray)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void runInternal()
|
||||
{
|
||||
const PxU32 nb = mNbKinematics;
|
||||
for(PxU32 a=0; a<nb; ++a)
|
||||
{
|
||||
Sc::BodyCore* b = static_cast<Sc::BodyCore*>(mKinematics[a]);
|
||||
PX_ASSERT(b->getSim()->isKinematic());
|
||||
PX_ASSERT(b->getSim()->isActive());
|
||||
|
||||
b->getSim()->updateCached(mCache, mBoundsArray);
|
||||
}
|
||||
}
|
||||
|
||||
virtual const char* getName() const
|
||||
{
|
||||
return "ScScene.KinematicShapeUpdateTask";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void Sc::Scene::updateKinematicCached(PxBaseTask* continuation)
|
||||
{
|
||||
PX_PROFILE_ZONE("Sim.updateKinematicCached", mContextId);
|
||||
|
||||
const PxU32 nbKinematics = getActiveKinematicBodiesCount();
|
||||
if(!nbKinematics)
|
||||
return;
|
||||
|
||||
BodyCore*const* kinematics = getActiveKinematicBodies();
|
||||
|
||||
Cm::FlushPool& flushPool = mLLContext->getTaskPool();
|
||||
|
||||
PxU32 startIndex = 0;
|
||||
PxU32 nbShapes = 0;
|
||||
|
||||
{
|
||||
PX_PROFILE_ZONE("ShapeUpdate", mContextId);
|
||||
|
||||
// PT: TASK-CREATION TAG
|
||||
for(PxU32 i=0; i<nbKinematics; i++)
|
||||
{
|
||||
Sc::BodySim* sim = static_cast<Sc::BodyCore*>(kinematics[i])->getSim();
|
||||
PX_ASSERT(sim->isKinematic());
|
||||
PX_ASSERT(sim->isActive());
|
||||
|
||||
nbShapes += sim->getNbShapes();
|
||||
|
||||
if (nbShapes >= ScKinematicShapeUpdateTask::NbKinematicsShapesPerTask)
|
||||
{
|
||||
ScKinematicShapeUpdateTask* task = PX_PLACEMENT_NEW(flushPool.allocate(sizeof(ScKinematicShapeUpdateTask)), ScKinematicShapeUpdateTask)
|
||||
(kinematics + startIndex, (i + 1) - startIndex, mLLContext->getTransformCache(), *mBoundsArray, mContextId);
|
||||
|
||||
task->setContinuation(continuation);
|
||||
task->removeReference();
|
||||
startIndex = i + 1;
|
||||
nbShapes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(nbShapes)
|
||||
{
|
||||
ScKinematicShapeUpdateTask* task = PX_PLACEMENT_NEW(flushPool.allocate(sizeof(ScKinematicShapeUpdateTask)), ScKinematicShapeUpdateTask)
|
||||
(kinematics + startIndex, nbKinematics - startIndex, mLLContext->getTransformCache(), *mBoundsArray, mContextId);
|
||||
|
||||
task->setContinuation(continuation);
|
||||
task->removeReference();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
PxBitMapPinned& changedAABBMap = mAABBManager->getChangedAABBMgActorHandleMap();
|
||||
mLLContext->getTransformCache().setChangedState();
|
||||
mBoundsArray->setChangedState();
|
||||
for (PxU32 i = 0; i < nbKinematics; ++i)
|
||||
{
|
||||
Sc::BodySim* bodySim = static_cast<Sc::BodyCore*>(kinematics[i])->getSim();
|
||||
|
||||
if ((i+16) < nbKinematics)
|
||||
{
|
||||
PxPrefetchLine(kinematics[i + 16]);
|
||||
if ((i + 8) < nbKinematics)
|
||||
{
|
||||
PxPrefetchLine(kinematics[i + 8]->getSim());
|
||||
}
|
||||
}
|
||||
|
||||
// PT: ### changedMap pattern #1
|
||||
PxU32 nbElems = bodySim->getNbElements();
|
||||
Sc::ElementSim** elems = bodySim->getElements();
|
||||
while (nbElems--)
|
||||
{
|
||||
Sc::ShapeSim* sim = static_cast<Sc::ShapeSim*>(*elems++);
|
||||
//KS - TODO - can we parallelize this? The problem with parallelizing is that it's a bit operation,
|
||||
//so we would either need to use atomic operations or have some high-level concept that guarantees
|
||||
//that threads don't write to the same word in the map simultaneously
|
||||
if (sim->getFlags()&PxU32(PxShapeFlag::eSIMULATION_SHAPE | PxShapeFlag::eTRIGGER_SHAPE))
|
||||
changedAABBMap.set(sim->getElementID());
|
||||
}
|
||||
|
||||
mSimulationController->updateDynamic(NULL, bodySim->getNodeIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PT: TODO: consider using a non-member function for this one
|
||||
bool BodySim::deactivateKinematic()
|
||||
{
|
||||
BodyCore& core = getBodyCore();
|
||||
if(readInternalFlag(BF_KINEMATIC_SETTLING_2))
|
||||
{
|
||||
clearInternalFlag(BF_KINEMATIC_SETTLING_2);
|
||||
core.setWakeCounterFromSim(0); // For sleeping objects the wake counter must be 0. This needs to hold for kinematics too.
|
||||
notifyReadyForSleeping();
|
||||
notifyPutToSleep();
|
||||
setActive(false);
|
||||
return true;
|
||||
}
|
||||
else if (readInternalFlag(BF_KINEMATIC_SETTLING))
|
||||
{
|
||||
clearInternalFlag(BF_KINEMATIC_SETTLING);
|
||||
raiseInternalFlag(BF_KINEMATIC_SETTLING_2);
|
||||
}
|
||||
else if (!readInternalFlag(BF_KINEMATIC_SURFACE_VELOCITY))
|
||||
{
|
||||
clearInternalFlag(BF_KINEMATIC_MOVED);
|
||||
raiseInternalFlag(BF_KINEMATIC_SETTLING);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// PT: called during fetchResults()
|
||||
void Sc::Scene::postCallbacksPreSyncKinematics()
|
||||
{
|
||||
PX_PROFILE_ZONE("Sim.postCallbacksPreSyncKinematics", mContextId);
|
||||
|
||||
// Put/prepare kinematics to/for sleep and invalidate target pose
|
||||
// note: this needs to get done after the contact callbacks because
|
||||
// the target might get read there.
|
||||
//
|
||||
PxU32 nbKinematics = getActiveKinematicBodiesCount();
|
||||
BodyCore*const* kinematics = getActiveKinematicBodies();
|
||||
|
||||
//KS - this method must run over the kinematic actors in reverse.
|
||||
while(nbKinematics--)
|
||||
{
|
||||
if(nbKinematics > 16)
|
||||
{
|
||||
PxPrefetchLine(static_cast<BodyCore*>(kinematics[nbKinematics-16]));
|
||||
}
|
||||
if (nbKinematics > 4)
|
||||
{
|
||||
PxPrefetchLine((static_cast<BodyCore*>(kinematics[nbKinematics - 4]))->getSim());
|
||||
PxPrefetchLine((static_cast<BodyCore*>(kinematics[nbKinematics - 4]))->getSim()->getSimStateData_Unchecked());
|
||||
}
|
||||
|
||||
BodyCore* b = static_cast<BodyCore*>(kinematics[nbKinematics]);
|
||||
//kinematics++;
|
||||
PX_ASSERT(b->getSim()->isKinematic());
|
||||
PX_ASSERT(b->getSim()->isActive());
|
||||
|
||||
b->invalidateKinematicTarget();
|
||||
b->getSim()->deactivateKinematic();
|
||||
}
|
||||
}
|
||||
1269
engine/third_party/physx/source/simulationcontroller/src/ScNPhaseCore.cpp
vendored
Normal file
1269
engine/third_party/physx/source/simulationcontroller/src/ScNPhaseCore.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
409
engine/third_party/physx/source/simulationcontroller/src/ScNPhaseCore.h
vendored
Normal file
409
engine/third_party/physx/source/simulationcontroller/src/ScNPhaseCore.h
vendored
Normal file
@@ -0,0 +1,409 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_NPHASE_CORE_H
|
||||
#define SC_NPHASE_CORE_H
|
||||
|
||||
#include "PxSceneDesc.h"
|
||||
#include "foundation/PxHash.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "foundation/PxHashSet.h"
|
||||
#include "foundation/PxHashMap.h"
|
||||
#include "foundation/PxMutex.h"
|
||||
#include "foundation/PxAtomic.h"
|
||||
#include "PxPhysXConfig.h"
|
||||
|
||||
#include "foundation/PxPool.h"
|
||||
|
||||
#include "PxSimulationEventCallback.h"
|
||||
#include "ScTriggerPairs.h"
|
||||
#include "ScScene.h"
|
||||
#include "ScContactReportBuffer.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Bp
|
||||
{
|
||||
struct AABBOverlap;
|
||||
}
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
class ElementSim;
|
||||
class ShapeSimBase;
|
||||
|
||||
class Interaction;
|
||||
class ElementSimInteraction;
|
||||
class ElementInteractionMarker;
|
||||
class TriggerInteraction;
|
||||
|
||||
class ShapeInteraction;
|
||||
class ActorPair;
|
||||
class ActorPairReport;
|
||||
|
||||
class ActorPairContactReportData;
|
||||
|
||||
class ContactStreamManager;
|
||||
|
||||
class TriggerContactTask;
|
||||
|
||||
struct PairReleaseFlag
|
||||
{
|
||||
enum Enum
|
||||
{
|
||||
eRUN_LOST_TOUCH_LOGIC = (1 << 0), // run the lost-touch-logic for a pair that gets removed.
|
||||
eWAKE_ON_LOST_TOUCH = (1 << 1) // a pair that lost touch should check whether the actors should get woken up
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
NPhaseCore encapsulates the near phase processing to allow multiple implementations(eg threading and non threaded).
|
||||
|
||||
The broadphase inserts shape pairs into the NPhaseCore, which are then processed into contact point streams.
|
||||
Pairs can then be processed into AxisConstraints by the GroupSolveCore.
|
||||
*/
|
||||
|
||||
struct BodyPairKey
|
||||
{
|
||||
PX_FORCE_INLINE BodyPairKey(PxU32 sim0, PxU32 sim1) : mSim0(sim0), mSim1(sim1) {}
|
||||
|
||||
const PxU32 mSim0;
|
||||
const PxU32 mSim1;
|
||||
|
||||
PX_FORCE_INLINE bool operator == (const BodyPairKey& pair) const { return mSim0 == pair.mSim0 && mSim1 == pair.mSim1; }
|
||||
};
|
||||
|
||||
PX_INLINE PxU32 PxComputeHash(const BodyPairKey& key)
|
||||
{
|
||||
const PxU32 add0 = key.mSim0;
|
||||
const PxU32 add1 = key.mSim1;
|
||||
|
||||
const PxU32 base = PxU32((add0 & 0xFFFF) | (add1 << 16));
|
||||
|
||||
return physx::PxComputeHash(base);
|
||||
}
|
||||
|
||||
struct ElementSimKey
|
||||
{
|
||||
PxU32 mID0;
|
||||
PxU32 mID1;
|
||||
|
||||
ElementSimKey() : mID0(0xffffffff), mID1(0xffffffff)
|
||||
{}
|
||||
|
||||
ElementSimKey(PxU32 id0, PxU32 id1)
|
||||
{
|
||||
if(id0 > id1)
|
||||
PxSwap(id0, id1);
|
||||
mID0 = id0;
|
||||
mID1 = id1;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE bool operator == (const ElementSimKey& pair) const { return mID0 == pair.mID0 && mID1 == pair.mID1; }
|
||||
};
|
||||
|
||||
PX_INLINE PxU32 PxComputeHash(const ElementSimKey& key)
|
||||
{
|
||||
const PxU64 base = PxU64(key.mID0) | (PxU64(key.mID1) << 32);
|
||||
return physx::PxComputeHash(base);
|
||||
}
|
||||
|
||||
class ContactReportAllocationManager
|
||||
{
|
||||
PxU8* mBuffer;
|
||||
PxU32 mBufferSize;
|
||||
PxU32 mCurrentBufferIndex;
|
||||
PxU32 mCurrentOffset;
|
||||
ContactReportBuffer& mReportBuffer;
|
||||
PxMutex& mMutex;
|
||||
const PxU32 mBuferBlockSize;
|
||||
PX_NOCOPY(ContactReportAllocationManager)
|
||||
public:
|
||||
|
||||
ContactReportAllocationManager(ContactReportBuffer& buffer, PxMutex& mutex, const PxU32 bufferBlockSize = 16384) : mBuffer(NULL), mBufferSize(0), mCurrentBufferIndex(0),
|
||||
mCurrentOffset(0), mReportBuffer(buffer), mMutex(mutex), mBuferBlockSize(bufferBlockSize)
|
||||
{
|
||||
}
|
||||
|
||||
PxU8* allocate(PxU32 size, PxU32& index, PxU32 alignment = 16u)
|
||||
{
|
||||
//(1) fix up offsets...
|
||||
const PxU32 pad = ((mCurrentBufferIndex + alignment - 1)&~(alignment - 1)) - mCurrentBufferIndex;
|
||||
PxU32 currOffset = mCurrentOffset + pad;
|
||||
|
||||
if ((currOffset + size) > mBufferSize)
|
||||
{
|
||||
const PxU32 allocSize = PxMax(size, mBuferBlockSize);
|
||||
|
||||
mMutex.lock();
|
||||
mBuffer = mReportBuffer.allocateNotThreadSafe(allocSize, mCurrentBufferIndex, alignment);
|
||||
mCurrentOffset = currOffset = 0;
|
||||
mBufferSize = allocSize;
|
||||
mMutex.unlock();
|
||||
}
|
||||
|
||||
PxU8* ret = mBuffer + currOffset;
|
||||
index = mCurrentBufferIndex + currOffset;
|
||||
mCurrentOffset = currOffset + size;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
class TriggerProcessingContext
|
||||
{
|
||||
public:
|
||||
TriggerProcessingContext()
|
||||
: mTmpTriggerProcessingBlock(NULL)
|
||||
, mTmpTriggerPairCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool initialize(TriggerInteraction**, PxU32 pairCount, PxcScratchAllocator&);
|
||||
|
||||
void deinitialize(PxcScratchAllocator&);
|
||||
|
||||
PX_FORCE_INLINE TriggerInteraction* const* getTriggerInteractions() const
|
||||
{
|
||||
return reinterpret_cast<TriggerInteraction**>(mTmpTriggerProcessingBlock);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxU32 getTriggerInteractionCount() const
|
||||
{
|
||||
return mTmpTriggerPairCount;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE TriggerContactTask* getTriggerContactTasks()
|
||||
{
|
||||
const PxU32 offset = mTmpTriggerPairCount * sizeof(TriggerInteraction*);
|
||||
return reinterpret_cast<TriggerContactTask*>(mTmpTriggerProcessingBlock + offset);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxMutex& getTriggerWriteBackLock()
|
||||
{
|
||||
return mTriggerWriteBackLock;
|
||||
}
|
||||
|
||||
private:
|
||||
PxU8* mTmpTriggerProcessingBlock; // temporary memory block to process trigger pairs in parallel
|
||||
// (see comment in Sc::Scene::postIslandGen too)
|
||||
PxU32 mTmpTriggerPairCount;
|
||||
PxMutex mTriggerWriteBackLock;
|
||||
};
|
||||
|
||||
typedef PxPool2<ElementInteractionMarker, 4096> ElementInteractionMarkerPool;
|
||||
typedef PxPool2<ActorPairContactReportData, 4096> ActorPairContactReportDataPool;
|
||||
typedef PxPool2<TriggerInteraction, 4096> TriggerInteractionPool;
|
||||
typedef PxPool2<ActorPairReport, 4096> ActorPairReportPool;
|
||||
typedef PxPool2<ActorPair, 4096> ActorPairPool;
|
||||
|
||||
class NPhaseCore : public PxUserAllocated
|
||||
{
|
||||
PX_NOCOPY(NPhaseCore)
|
||||
|
||||
public:
|
||||
NPhaseCore(Scene& scene, const PxSceneDesc& desc);
|
||||
~NPhaseCore();
|
||||
|
||||
ElementSimInteraction* findInteraction(const ElementSim* element0, const ElementSim* element1) const;
|
||||
|
||||
void onTriggerOverlapCreated(const Bp::AABBOverlap* PX_RESTRICT pairs, PxU32 pairCount);
|
||||
|
||||
void runOverlapFilters( PxU32 nbToProcess, Bp::AABBOverlap* PX_RESTRICT pairs, FilterInfo* PX_RESTRICT filterInfo,
|
||||
PxU32& nbToKeep, PxU32& nbToSuppress) const;
|
||||
|
||||
void onOverlapRemoved(ElementSim* volume0, ElementSim* volume1, PxU32 ccdPass, void* elemSim, PxsContactManagerOutputIterator& outputs);
|
||||
void onVolumeRemoved(ElementSim* volume, PxU32 flags, PxsContactManagerOutputIterator& outputs);
|
||||
|
||||
void managerNewTouch(ShapeInteraction& interaction);
|
||||
|
||||
PxU32 getDefaultContactReportStreamBufferSize() const;
|
||||
|
||||
void fireCustomFilteringCallbacks(PxsContactManagerOutputIterator& outputs);
|
||||
|
||||
void addToDirtyInteractionList(Interaction* interaction);
|
||||
void removeFromDirtyInteractionList(Interaction* interaction);
|
||||
void updateDirtyInteractions(PxsContactManagerOutputIterator& outputs);
|
||||
|
||||
/**
|
||||
\brief Allocate buffers for trigger overlap test.
|
||||
|
||||
See comment in Sc::Scene::postIslandGen for why this is split up into multiple parts.
|
||||
|
||||
\param[in] continuation The task to run after trigger processing.
|
||||
\return The concluding trigger processing task if there is work to do, else NULL.
|
||||
*/
|
||||
PxBaseTask* prepareForTriggerInteractionProcessing(PxBaseTask* continuation);
|
||||
|
||||
// Perform trigger overlap tests.
|
||||
void processTriggerInteractions(PxBaseTask& continuation);
|
||||
|
||||
// Deactivate trigger interactions if possible, free buffers from overlap tests and clean up.
|
||||
// See comment in Sc::Scene::postIslandGen for why this is split up into multiple parts.
|
||||
void concludeTriggerInteractionProcessing(PxBaseTask* continuation);
|
||||
|
||||
// Check candidates for persistent touch contact events and create those events if necessary.
|
||||
void processPersistentContactEvents(PxsContactManagerOutputIterator& outputs);
|
||||
|
||||
PX_FORCE_INLINE void addToContactReportActorPairSet(ActorPairReport* pair) { mContactReportActorPairSet.pushBack(pair); }
|
||||
void clearContactReportActorPairs(bool shrinkToZero);
|
||||
PX_FORCE_INLINE PxU32 getNbContactReportActorPairs() const { return mContactReportActorPairSet.size(); }
|
||||
PX_FORCE_INLINE ActorPairReport* const* getContactReportActorPairs() const { return mContactReportActorPairSet.begin(); }
|
||||
|
||||
void addToPersistentContactEventPairs(ShapeInteraction*);
|
||||
void addToPersistentContactEventPairsDelayed(ShapeInteraction*);
|
||||
void removeFromPersistentContactEventPairs(ShapeInteraction*);
|
||||
|
||||
PX_FORCE_INLINE PxU32 getCurrentPersistentContactEventPairCount() const { return mNextFramePersistentContactEventPairIndex; }
|
||||
PX_FORCE_INLINE ShapeInteraction* const* getCurrentPersistentContactEventPairs() const { return mPersistentContactEventPairList.begin(); }
|
||||
PX_FORCE_INLINE PxU32 getAllPersistentContactEventPairCount() const { return mPersistentContactEventPairList.size(); }
|
||||
PX_FORCE_INLINE ShapeInteraction* const* getAllPersistentContactEventPairs() const { return mPersistentContactEventPairList.begin(); }
|
||||
PX_FORCE_INLINE void preparePersistentContactEventListForNextFrame()
|
||||
{
|
||||
// reports have been processed -> "activate" next frame candidates for persistent contact events
|
||||
mNextFramePersistentContactEventPairIndex = mPersistentContactEventPairList.size();
|
||||
}
|
||||
|
||||
void addToForceThresholdContactEventPairs(ShapeInteraction*);
|
||||
void removeFromForceThresholdContactEventPairs(ShapeInteraction*);
|
||||
|
||||
PX_FORCE_INLINE PxU32 getForceThresholdContactEventPairCount() const { return mForceThresholdContactEventPairList.size(); }
|
||||
PX_FORCE_INLINE ShapeInteraction* const* getForceThresholdContactEventPairs() const { return mForceThresholdContactEventPairList.begin(); }
|
||||
|
||||
PX_FORCE_INLINE PxU8* getContactReportPairData(const PxU32& bufferIndex) const { return mContactReportBuffer.getData(bufferIndex); }
|
||||
PxU8* reserveContactReportPairData(PxU32 pairCount, PxU32 extraDataSize, PxU32& bufferIndex, ContactReportAllocationManager* alloc = NULL);
|
||||
PxU8* resizeContactReportPairData(PxU32 pairCount, PxU32 extraDataSize, ContactStreamManager& csm);
|
||||
PX_FORCE_INLINE void clearContactReportStream() { mContactReportBuffer.reset(); } // Do not free memory at all
|
||||
PX_FORCE_INLINE void freeContactReportStreamMemory() { mContactReportBuffer.flush(); }
|
||||
|
||||
ActorPairContactReportData* createActorPairContactReportData();
|
||||
|
||||
void registerInteraction(ElementSimInteraction* interaction);
|
||||
void unregisterInteraction(ElementSimInteraction* interaction);
|
||||
|
||||
ElementSimInteraction* createRbElementInteraction(const FilterInfo& fInfo, ShapeSimBase& s0, ShapeSimBase& s1, PxsContactManager* contactManager, ShapeInteraction* shapeInteraction,
|
||||
ElementInteractionMarker* interactionMarker, bool isTriggerPair);
|
||||
|
||||
PX_FORCE_INLINE void lockReports() { mReportAllocLock.lock(); }
|
||||
PX_FORCE_INLINE void unlockReports() { mReportAllocLock.unlock(); }
|
||||
|
||||
private:
|
||||
void callPairLost(const ShapeSimBase& s0, const ShapeSimBase& s1, bool objVolumeRemoved);
|
||||
|
||||
ElementSimInteraction* createTriggerElementInteraction(ShapeSimBase& s0, ShapeSimBase& s1);
|
||||
|
||||
// removedElement: points to the removed element (that is, the BP volume wrapper), if a pair gets removed or loses touch due to a removed element.
|
||||
// NULL if not triggered by a removed element.
|
||||
//
|
||||
void releaseElementPair(ElementSimInteraction* pair, PxU32 flags, ElementSim* removedElement, PxU32 ccdPass, bool removeFromDirtyList, PxsContactManagerOutputIterator& outputs);
|
||||
void lostTouchReports(ShapeInteraction* pair, PxU32 flags, ElementSim* removedElement, PxU32 ccdPass, PxsContactManagerOutputIterator& outputs);
|
||||
|
||||
ShapeInteraction* createShapeInteraction(ShapeSimBase& s0, ShapeSimBase& s1, PxPairFlags pairFlags, PxsContactManager* contactManager, ShapeInteraction* shapeInteraction);
|
||||
TriggerInteraction* createTriggerInteraction(ShapeSimBase& s0, ShapeSimBase& s1, PxPairFlags triggerFlags);
|
||||
ElementInteractionMarker* createElementInteractionMarker(ElementSim& e0, ElementSim& e1, ElementInteractionMarker* marker);
|
||||
|
||||
//------------- Filtering -------------
|
||||
|
||||
ElementSimInteraction* refilterInteraction(ElementSimInteraction* pair, const FilterInfo* filterInfo, bool removeFromDirtyList, PxsContactManagerOutputIterator& outputs);
|
||||
//-------------------------------------
|
||||
|
||||
ElementSimInteraction* convert(ElementSimInteraction* pair, InteractionType::Enum type, FilterInfo& filterInfo, bool removeFromDirtyList, PxsContactManagerOutputIterator& outputs);
|
||||
|
||||
ActorPair* findActorPair(ShapeSimBase* s0, ShapeSimBase* s1, PxIntBool isReportPair);
|
||||
|
||||
// Pooling
|
||||
Scene& mOwnerScene;
|
||||
|
||||
PxArray<ActorPairReport*> mContactReportActorPairSet;
|
||||
PxArray<ShapeInteraction*> mPersistentContactEventPairList; // Pairs which request events which do not get triggered by the sdk and thus need to be tested actively every frame.
|
||||
// May also contain force threshold event pairs (see mForceThresholdContactEventPairList)
|
||||
// This list is split in two, the elements in front are for the current frame, the elements at the
|
||||
// back will get added next frame.
|
||||
|
||||
PxU32 mNextFramePersistentContactEventPairIndex; // start index of the pairs which need to get added to the persistent list for next frame
|
||||
|
||||
PxArray<ShapeInteraction*> mForceThresholdContactEventPairList; // Pairs which request force threshold contact events. A pair is only in this list if it does have contact.
|
||||
// Note: If a pair additionally requests PxPairFlag::eNOTIFY_TOUCH_PERSISTS events, then it
|
||||
// goes into mPersistentContactEventPairList instead. This allows to share the list index.
|
||||
|
||||
// data layout:
|
||||
// ContactActorPair0_ExtraData, ContactShapePair0_0, ContactShapePair0_1, ... ContactShapePair0_N,
|
||||
// ContactActorPair1_ExtraData, ContactShapePair1_0, ...
|
||||
//
|
||||
ContactReportBuffer mContactReportBuffer; // Shape pair information for contact reports
|
||||
|
||||
PxCoalescedHashSet<Interaction*> mDirtyInteractions;
|
||||
// Pools
|
||||
ActorPairPool mActorPairPool;
|
||||
ActorPairReportPool mActorPairReportPool;
|
||||
PxPool<ShapeInteraction> mShapeInteractionPool;
|
||||
TriggerInteractionPool mTriggerInteractionPool;
|
||||
ActorPairContactReportDataPool mActorPairContactReportDataPool;
|
||||
ElementInteractionMarkerPool mInteractionMarkerPool;
|
||||
|
||||
Cm::DelegateTask<NPhaseCore, &NPhaseCore::concludeTriggerInteractionProcessing> mConcludeTriggerInteractionProcessingTask;
|
||||
TriggerProcessingContext mTriggerProcessingContext;
|
||||
PxHashMap<BodyPairKey, ActorPair*> mActorPairMap;
|
||||
|
||||
PxHashMap<ElementSimKey, ElementSimInteraction*> mElementSimMap;
|
||||
|
||||
PxMutex mBufferAllocLock;
|
||||
PxMutex mReportAllocLock;
|
||||
|
||||
friend class Sc::Scene;
|
||||
friend class Sc::ShapeInteraction;
|
||||
};
|
||||
|
||||
struct FilteringContext
|
||||
{
|
||||
PX_NOCOPY(FilteringContext)
|
||||
public:
|
||||
FilteringContext(const Scene& scene) :
|
||||
mFilterShader (scene.getFilterShaderFast()),
|
||||
mFilterShaderData (scene.getFilterShaderDataFast()),
|
||||
mFilterShaderDataSize (scene.getFilterShaderDataSizeFast()),
|
||||
mFilterCallback (scene.getFilterCallbackFast()),
|
||||
mKineKineFilteringMode (scene.getKineKineFilteringMode()),
|
||||
mStaticKineFilteringMode(scene.getStaticKineFilteringMode()),
|
||||
mIsDirectGPU (scene.getFlags() & PxSceneFlag::eENABLE_DIRECT_GPU_API)
|
||||
{
|
||||
}
|
||||
|
||||
PxSimulationFilterShader mFilterShader;
|
||||
const void* mFilterShaderData;
|
||||
PxU32 mFilterShaderDataSize;
|
||||
PxSimulationFilterCallback* mFilterCallback;
|
||||
const PxPairFilteringMode::Enum mKineKineFilteringMode;
|
||||
const PxPairFilteringMode::Enum mStaticKineFilteringMode;
|
||||
const bool mIsDirectGPU;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
100
engine/third_party/physx/source/simulationcontroller/src/ScObjectIDTracker.h
vendored
Normal file
100
engine/third_party/physx/source/simulationcontroller/src/ScObjectIDTracker.h
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_OBJECT_ID_TRACKER_H
|
||||
#define SC_OBJECT_ID_TRACKER_H
|
||||
|
||||
#include "CmIDPool.h"
|
||||
#include "foundation/PxBitMap.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
// PT: TODO: this has no direct dependency on "Sc". It should really be a "Cm" class.
|
||||
class ObjectIDTracker : public PxUserAllocated
|
||||
{
|
||||
PX_NOCOPY(ObjectIDTracker)
|
||||
public:
|
||||
ObjectIDTracker() : mPendingReleasedIDs("objectIDTrackerIDs") {}
|
||||
|
||||
PX_INLINE PxU32 createID() { return mIDPool.getNewID(); }
|
||||
|
||||
PX_INLINE void releaseID(PxU32 id)
|
||||
{
|
||||
markIDAsDeleted(id);
|
||||
mPendingReleasedIDs.pushBack(id);
|
||||
}
|
||||
|
||||
PX_INLINE PxIntBool isDeletedID(PxU32 id) const { return mDeletedIDsMap.boundedTest(id); }
|
||||
PX_FORCE_INLINE PxU32 getDeletedIDCount() const { return mPendingReleasedIDs.size(); }
|
||||
PX_INLINE void clearDeletedIDMap() { mDeletedIDsMap.clear(); }
|
||||
|
||||
PX_INLINE void resizeDeletedIDMap(PxU32 id, PxU32 numIds)
|
||||
{
|
||||
mDeletedIDsMap.resize(id);
|
||||
mPendingReleasedIDs.reserve(numIds);
|
||||
}
|
||||
|
||||
PX_INLINE void processPendingReleases()
|
||||
{
|
||||
for(PxU32 i=0; i < mPendingReleasedIDs.size(); i++)
|
||||
mIDPool.freeID(mPendingReleasedIDs[i]);
|
||||
|
||||
mPendingReleasedIDs.clear();
|
||||
}
|
||||
|
||||
PX_INLINE void reset()
|
||||
{
|
||||
processPendingReleases();
|
||||
mPendingReleasedIDs.reset();
|
||||
|
||||
// Don't free stuff in IDPool, we still need the list of free IDs
|
||||
// And it does not seem worth freeing the memory of the bitmap
|
||||
}
|
||||
|
||||
PX_INLINE PxU32 getMaxID() const
|
||||
{
|
||||
return mIDPool.getMaxID();
|
||||
}
|
||||
private:
|
||||
PX_INLINE void markIDAsDeleted(PxU32 id)
|
||||
{
|
||||
PX_ASSERT(!isDeletedID(id));
|
||||
mDeletedIDsMap.growAndSet(id);
|
||||
}
|
||||
|
||||
Cm::IDPool mIDPool;
|
||||
PxBitMap mDeletedIDsMap;
|
||||
PxArray<PxU32> mPendingReleasedIDs; // Buffer for released IDs to make sure newly created objects do not re-use these IDs immediately
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
268
engine/third_party/physx/source/simulationcontroller/src/ScParticleSystemCore.cpp
vendored
Normal file
268
engine/third_party/physx/source/simulationcontroller/src/ScParticleSystemCore.cpp
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
|
||||
#include "ScParticleSystemCore.h"
|
||||
|
||||
#include "ScPhysics.h"
|
||||
#include "ScParticleSystemSim.h"
|
||||
#include "DyParticleSystem.h"
|
||||
#include "PxvGlobals.h"
|
||||
#include "PxPhysXGpu.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::ParticleSystemCore::ParticleSystemCore(PxActorType::Enum actorType) :
|
||||
ActorCore(actorType, PxActorFlag::eVISUALIZATION, PX_DEFAULT_CLIENT, 0)
|
||||
{
|
||||
}
|
||||
|
||||
Sc::ParticleSystemCore::~ParticleSystemCore()
|
||||
{
|
||||
}
|
||||
|
||||
Sc::ParticleSystemSim* Sc::ParticleSystemCore::getSim() const
|
||||
{
|
||||
return static_cast<ParticleSystemSim*>(ActorCore::getSim());
|
||||
}
|
||||
|
||||
PxReal Sc::ParticleSystemCore::getSleepThreshold() const
|
||||
{
|
||||
return mShapeCore.getLLCore().sleepThreshold;//mCore.sleepThreshold;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setSleepThreshold(const PxReal v)
|
||||
{
|
||||
mShapeCore.getLLCore().sleepThreshold = v;
|
||||
}
|
||||
|
||||
PxReal Sc::ParticleSystemCore::getRestOffset() const
|
||||
{
|
||||
return mShapeCore.getLLCore().restOffset;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setRestOffset(const PxReal v)
|
||||
{
|
||||
mShapeCore.getLLCore().restOffset = v;
|
||||
}
|
||||
|
||||
PxReal Sc::ParticleSystemCore::getContactOffset() const
|
||||
{
|
||||
return mShapeCore.getContactOffset();
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setContactOffset(const PxReal v)
|
||||
{
|
||||
mShapeCore.setContactOffset(v);
|
||||
|
||||
Sc::ParticleSystemSim* sim = getSim();
|
||||
if (sim)
|
||||
{
|
||||
sim->getScene().updateContactDistance(sim->getShapeSim().getElementID(), v);
|
||||
}
|
||||
}
|
||||
|
||||
PxReal Sc::ParticleSystemCore::getParticleContactOffset() const
|
||||
{
|
||||
return mShapeCore.getLLCore().particleContactOffset;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setParticleContactOffset(const PxReal v)
|
||||
{
|
||||
mShapeCore.getLLCore().particleContactOffset = v;
|
||||
}
|
||||
|
||||
PxReal Sc::ParticleSystemCore::getSolidRestOffset() const
|
||||
{
|
||||
return mShapeCore.getLLCore().solidRestOffset;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setSolidRestOffset(const PxReal v)
|
||||
{
|
||||
mShapeCore.getLLCore().solidRestOffset = v;
|
||||
}
|
||||
|
||||
PxReal Sc::ParticleSystemCore::getFluidRestOffset() const
|
||||
{
|
||||
return mShapeCore.getLLCore().fluidRestOffset;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setFluidRestOffset(const PxReal v)
|
||||
{
|
||||
mShapeCore.getLLCore().fluidRestOffset = v;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setMaxDepenetrationVelocity(const PxReal v)
|
||||
{
|
||||
mShapeCore.getLLCore().maxDepenetrationVelocity = v;
|
||||
}
|
||||
|
||||
PxReal Sc::ParticleSystemCore::getMaxDepenetrationVelocity() const
|
||||
{
|
||||
return mShapeCore.getLLCore().maxDepenetrationVelocity;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setMaxVelocity(const PxReal v)
|
||||
{
|
||||
mShapeCore.getLLCore().maxVelocity = v;
|
||||
}
|
||||
|
||||
PxReal Sc::ParticleSystemCore::getMaxVelocity() const
|
||||
{
|
||||
return mShapeCore.getLLCore().maxVelocity;
|
||||
}
|
||||
|
||||
PxParticleSystemCallback* Sc::ParticleSystemCore::getParticleSystemCallback() const
|
||||
{
|
||||
return mShapeCore.getLLCore().mCallback;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setParticleSystemCallback(PxParticleSystemCallback* callback)
|
||||
{
|
||||
mShapeCore.getLLCore().mCallback = callback;
|
||||
}
|
||||
|
||||
PxReal Sc::ParticleSystemCore::getFluidBoundaryDensityScale() const
|
||||
{
|
||||
return mShapeCore.getLLCore().fluidBoundaryDensityScale;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setFluidBoundaryDensityScale(const PxReal v)
|
||||
{
|
||||
mShapeCore.getLLCore().fluidBoundaryDensityScale = v;
|
||||
}
|
||||
|
||||
PxU32 Sc::ParticleSystemCore::getGridSizeX() const
|
||||
{
|
||||
return mShapeCore.getLLCore().gridSizeX;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setGridSizeX(const PxU32 v)
|
||||
{
|
||||
mShapeCore.getLLCore().gridSizeX = v;
|
||||
}
|
||||
|
||||
PxU32 Sc::ParticleSystemCore::getGridSizeY() const
|
||||
{
|
||||
return mShapeCore.getLLCore().gridSizeY;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setGridSizeY(const PxU32 v)
|
||||
{
|
||||
mShapeCore.getLLCore().gridSizeY = v;
|
||||
}
|
||||
|
||||
PxU32 Sc::ParticleSystemCore::getGridSizeZ() const
|
||||
{
|
||||
return mShapeCore.getLLCore().gridSizeZ;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setGridSizeZ(const PxU32 v)
|
||||
{
|
||||
mShapeCore.getLLCore().gridSizeZ = v;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setSolverIterationCounts(PxU16 c)
|
||||
{
|
||||
mShapeCore.getLLCore().solverIterationCounts = c;
|
||||
}
|
||||
|
||||
|
||||
PxReal Sc::ParticleSystemCore::getWakeCounter() const
|
||||
{
|
||||
return mShapeCore.getLLCore().wakeCounter;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setWakeCounter(const PxReal v)
|
||||
{
|
||||
mShapeCore.getLLCore().wakeCounter = v;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setWakeCounterInternal(const PxReal v)
|
||||
{
|
||||
mShapeCore.getLLCore().wakeCounter = v;
|
||||
}
|
||||
|
||||
bool Sc::ParticleSystemCore::isSleeping() const
|
||||
{
|
||||
Sc::ParticleSystemSim* sim = getSim();
|
||||
return sim ? sim->isSleeping() : (mShapeCore.getLLCore().wakeCounter == 0.0f);
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::wakeUp(PxReal wakeCounter)
|
||||
{
|
||||
mShapeCore.getLLCore().wakeCounter = wakeCounter;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::putToSleep()
|
||||
{
|
||||
mShapeCore.getLLCore().wakeCounter = 0.0f;
|
||||
}
|
||||
|
||||
PxActor* Sc::ParticleSystemCore::getPxActor() const
|
||||
{
|
||||
return PxPointerOffset<PxActor*>(const_cast<ParticleSystemCore*>(this), gOffsetTable.scCore2PxActor[getActorCoreType()]);
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::addRigidAttachment(Sc::BodyCore* core)
|
||||
{
|
||||
Sc::ParticleSystemSim* sim = getSim();
|
||||
if(sim)
|
||||
sim->getScene().addRigidAttachment(core, *sim);
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::removeRigidAttachment(Sc::BodyCore* core)
|
||||
{
|
||||
Sc::ParticleSystemSim* sim = getSim();
|
||||
if (sim)
|
||||
sim->getScene().removeRigidAttachment(core, *sim);
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemCore::setFlags(PxParticleFlags flags)
|
||||
{
|
||||
Sc::ParticleSystemSim* sim = getSim();
|
||||
PxParticleFlags oldFlags = mShapeCore.getLLCore().mFlags;
|
||||
mShapeCore.getLLCore().mFlags = flags;
|
||||
|
||||
if (sim)
|
||||
{
|
||||
bool wasRigidCollisionDisabled = oldFlags & PxParticleFlag::eDISABLE_RIGID_COLLISION;
|
||||
bool isRigidCollisionDisabled = flags & PxParticleFlag::eDISABLE_RIGID_COLLISION;
|
||||
|
||||
if (wasRigidCollisionDisabled ^ isRigidCollisionDisabled)
|
||||
{
|
||||
if (wasRigidCollisionDisabled)
|
||||
sim->createLowLevelVolume();
|
||||
else
|
||||
sim->destroyLowLevelVolume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //PX_SUPPORT_GPU_PHYSX
|
||||
118
engine/third_party/physx/source/simulationcontroller/src/ScParticleSystemShapeCore.cpp
vendored
Normal file
118
engine/third_party/physx/source/simulationcontroller/src/ScParticleSystemShapeCore.cpp
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
#include "foundation/PxErrorCallback.h"
|
||||
#include "ScParticleSystemShapeCore.h"
|
||||
#include "ScPhysics.h"
|
||||
#include "PxvGlobals.h"
|
||||
#include "PxPhysXGpu.h"
|
||||
#include "cudamanager/PxCudaContextManager.h"
|
||||
#include "CmVisualization.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
|
||||
ParticleSystemShapeCore::ParticleSystemShapeCore()
|
||||
: ShapeCore(PxEmpty)
|
||||
, mGpuMemStat(0)
|
||||
{
|
||||
mSimulationFilterData = PxFilterData();
|
||||
mCore = PxsShapeCore();
|
||||
|
||||
mCore.mShapeCoreFlags |= PxShapeCoreFlag::eOWNS_MATERIAL_IDX_MEMORY;
|
||||
|
||||
const PxTolerancesScale& scale = Physics::getInstance().getTolerancesScale();
|
||||
mCore.setTransform(PxTransform(PxIdentity));
|
||||
mCore.mContactOffset = 0.01f * scale.length;
|
||||
mCore.mShapeFlags = 0;
|
||||
mCore.mMaterialIndex = 0;
|
||||
|
||||
mCore.mMinTorsionalPatchRadius = 0.f;
|
||||
mCore.mTorsionalRadius = 0.f;
|
||||
|
||||
mLLCore.sleepThreshold = 5e-5f * scale.speed * scale.speed;
|
||||
mLLCore.wakeCounter = Physics::sWakeCounterOnCreation;
|
||||
mLLCore.freezeThreshold = 5e-6f * scale.speed * scale.speed;
|
||||
|
||||
//TODO, make this dependend on scale?
|
||||
//also set contact offset accordingly
|
||||
mLLCore.restOffset = 0.1f;
|
||||
const PxReal contactOffset = mLLCore.restOffset + 0.001f;
|
||||
setContactOffset(contactOffset);
|
||||
|
||||
mLLCore.particleContactOffset = contactOffset;
|
||||
mLLCore.solidRestOffset = mLLCore.restOffset;
|
||||
mLLCore.fluidRestOffset = mLLCore.restOffset * 0.6f;
|
||||
|
||||
mLLCore.particleContactOffset_prev = FLT_MIN;
|
||||
mLLCore.fluidRestOffset_prev = FLT_MIN;
|
||||
|
||||
mLLCore.fluidBoundaryDensityScale = 0.0f;
|
||||
|
||||
mLLCore.gridSizeX = 128;
|
||||
mLLCore.gridSizeY = 128;
|
||||
mLLCore.gridSizeZ = 128;
|
||||
|
||||
mLLCore.mFlags = PxParticleFlags(0);
|
||||
mLLCore.mLockFlags = PxParticleLockFlags(0);
|
||||
|
||||
mLLCore.solverIterationCounts = (1 << 8) | 4;
|
||||
|
||||
mLLCore.mWind = PxVec3(0.f);
|
||||
|
||||
// Sparse grid specific
|
||||
mLLCore.sparseGridParams.setToDefault();
|
||||
mLLCore.sparseGridParams.gridSpacing = 2.0f * mLLCore.particleContactOffset;
|
||||
}
|
||||
|
||||
|
||||
// PX_SERIALIZATION
|
||||
ParticleSystemShapeCore::ParticleSystemShapeCore(const PxEMPTY)
|
||||
: ShapeCore(PxEmpty)
|
||||
{
|
||||
}
|
||||
|
||||
ParticleSystemShapeCore::~ParticleSystemShapeCore()
|
||||
{
|
||||
}
|
||||
|
||||
void ParticleSystemShapeCore::initializeLLCoreData(PxU32 maxNeighborhood, PxReal neighborhoodScale)
|
||||
{
|
||||
const PxTolerancesScale& scale = Sc::Physics::getInstance().getTolerancesScale();
|
||||
|
||||
mLLCore.mMaxNeighborhood = maxNeighborhood;
|
||||
mLLCore.mNeighborhoodScale = neighborhoodScale;
|
||||
|
||||
mLLCore.maxDepenetrationVelocity = 50.f * scale.length;
|
||||
mLLCore.maxVelocity = 1e+6f;
|
||||
}
|
||||
|
||||
#endif // PX_SUPPORT_GPU_PHYSX
|
||||
|
||||
76
engine/third_party/physx/source/simulationcontroller/src/ScParticleSystemShapeCore.h
vendored
Normal file
76
engine/third_party/physx/source/simulationcontroller/src/ScParticleSystemShapeCore.h
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
|
||||
#ifndef SC_PARTICLESYSTEM_SHAPECORE_H
|
||||
#define SC_PARTICLESYSTEM_SHAPECORE_H
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "PxvGeometry.h"
|
||||
#include "foundation/PxUtilities.h"
|
||||
#include "PxFiltering.h"
|
||||
#include "PxShape.h"
|
||||
#include "ScShapeCore.h"
|
||||
#include "DyParticleSystemCore.h"
|
||||
#include "common/PxRenderOutput.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class Scene;
|
||||
class ParticleSystemCore;
|
||||
class ParticleSystemSim;
|
||||
|
||||
class ParticleSystemShapeCore : public Sc::ShapeCore
|
||||
{
|
||||
public:
|
||||
// PX_SERIALIZATION
|
||||
ParticleSystemShapeCore(const PxEMPTY);
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
ParticleSystemShapeCore();
|
||||
~ParticleSystemShapeCore();
|
||||
|
||||
PX_FORCE_INLINE const Dy::ParticleSystemCore& getLLCore() const { return mLLCore; }
|
||||
|
||||
PX_FORCE_INLINE Dy::ParticleSystemCore& getLLCore() { return mLLCore; }
|
||||
|
||||
void initializeLLCoreData(PxU32 maxNeighborhood, PxReal neighborhoodScale);
|
||||
|
||||
PxU64 getGpuMemStat() { return mGpuMemStat; }
|
||||
|
||||
protected:
|
||||
Dy::ParticleSystemCore mLLCore;
|
||||
PxU64 mGpuMemStat;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
109
engine/third_party/physx/source/simulationcontroller/src/ScParticleSystemSim.cpp
vendored
Normal file
109
engine/third_party/physx/source/simulationcontroller/src/ScParticleSystemSim.cpp
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
|
||||
#include "ScParticleSystemSim.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Dy;
|
||||
|
||||
Sc::ParticleSystemSim::ParticleSystemSim(ParticleSystemCore& core, Scene& scene) :
|
||||
GPUActorSim(scene, core, &core.getShapeCore())
|
||||
{
|
||||
createLowLevelVolume();
|
||||
|
||||
mLLParticleSystem = scene.createLLParticleSystem(this);
|
||||
|
||||
mNodeIndex = scene.getSimpleIslandManager()->addNode(false, false, IG::Node::ePARTICLESYSTEM_TYPE, mLLParticleSystem);
|
||||
|
||||
scene.getSimpleIslandManager()->activateNode(mNodeIndex);
|
||||
|
||||
//mCore.setSim(this);
|
||||
|
||||
mLLParticleSystem->setElementId(mShapeSim.getElementID());
|
||||
|
||||
PxParticleSystemGeometry geometry;
|
||||
geometry.mSolverType = PxParticleSolverType::ePBD;
|
||||
|
||||
core.getShapeCore().setGeometry(geometry);
|
||||
|
||||
PxsShapeCore* shapeCore = const_cast<PxsShapeCore*>(&core.getShapeCore().getCore());
|
||||
mLLParticleSystem->setShapeCore(shapeCore);
|
||||
}
|
||||
|
||||
Sc::ParticleSystemSim::~ParticleSystemSim()
|
||||
{
|
||||
if (!mLLParticleSystem)
|
||||
return;
|
||||
|
||||
mScene.destroyLLParticleSystem(*mLLParticleSystem);
|
||||
|
||||
mScene.getSimpleIslandManager()->removeNode(mNodeIndex);
|
||||
|
||||
mCore.setSim(NULL);
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemSim::createLowLevelVolume()
|
||||
{
|
||||
//PX_ASSERT(getWorldBounds().isFinite());
|
||||
|
||||
const PxU32 index = mShapeSim.getElementID();
|
||||
|
||||
if (!(static_cast<Sc::ParticleSystemSim&>(mShapeSim.getActor()).getCore().getFlags() & PxParticleFlag::eDISABLE_RIGID_COLLISION))
|
||||
{
|
||||
mScene.getBoundsArray().setBounds(PxBounds3(PxVec3(PX_MAX_BOUNDS_EXTENTS), PxVec3(-PX_MAX_BOUNDS_EXTENTS)), index);
|
||||
mShapeSim.setInBroadPhase();
|
||||
}
|
||||
else
|
||||
mScene.getAABBManager()->reserveSpaceForBounds(index);
|
||||
|
||||
addToAABBMgr(Bp::FilterType::PARTICLESYSTEM);
|
||||
}
|
||||
|
||||
bool Sc::ParticleSystemSim::isSleeping() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemSim::sleepCheck(PxReal dt)
|
||||
{
|
||||
PX_UNUSED(dt);
|
||||
}
|
||||
|
||||
/*void Sc::ParticleSystemSim::activate()
|
||||
{
|
||||
activateInteractions(*this);
|
||||
}
|
||||
|
||||
void Sc::ParticleSystemSim::deactivate()
|
||||
{
|
||||
deactivateInteractions(*this);
|
||||
}*/
|
||||
|
||||
#endif //PX_SUPPORT_GPU_PHYSX
|
||||
74
engine/third_party/physx/source/simulationcontroller/src/ScParticleSystemSim.h
vendored
Normal file
74
engine/third_party/physx/source/simulationcontroller/src/ScParticleSystemSim.h
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
|
||||
#ifndef SC_PARTICLESYSTEM_SIM_H
|
||||
#define SC_PARTICLESYSTEM_SIM_H
|
||||
|
||||
#include "foundation/PxPreprocessor.h"
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "ScGpuActorSim.h"
|
||||
#include "ScParticleSystemCore.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class Scene;
|
||||
|
||||
class ParticleSystemSim : public GPUActorSim
|
||||
{
|
||||
PX_NOCOPY(ParticleSystemSim)
|
||||
public:
|
||||
ParticleSystemSim(ParticleSystemCore& core, Scene& scene);
|
||||
~ParticleSystemSim();
|
||||
|
||||
PX_INLINE Dy::ParticleSystem* getLowLevelParticleSystem() const { return mLLParticleSystem; }
|
||||
PX_INLINE ParticleSystemCore& getCore() const { return static_cast<ParticleSystemCore&>(mCore); }
|
||||
|
||||
virtual PxActor* getPxActor() const { return getCore().getPxActor(); }
|
||||
|
||||
bool isSleeping() const;
|
||||
bool isActive() const { return true; }
|
||||
void sleepCheck(PxReal dt);
|
||||
|
||||
void setActive(bool active, bool asPartOfCreation=false);
|
||||
|
||||
void createLowLevelVolume();
|
||||
|
||||
private:
|
||||
Dy::ParticleSystem* mLLParticleSystem;
|
||||
|
||||
// PT: as far as I can tell these are never actually called
|
||||
// void activate();
|
||||
// void deactivate();
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
59
engine/third_party/physx/source/simulationcontroller/src/ScPhysics.cpp
vendored
Normal file
59
engine/third_party/physx/source/simulationcontroller/src/ScPhysics.cpp
vendored
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-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#include "common/PxTolerancesScale.h"
|
||||
|
||||
#include "ScPhysics.h"
|
||||
#include "ScScene.h"
|
||||
#include "PxvGlobals.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::Physics* Sc::Physics::mInstance = NULL;
|
||||
const PxReal Sc::Physics::sWakeCounterOnCreation = 20.0f*0.02f;
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
OffsetTable gOffsetTable;
|
||||
}
|
||||
}
|
||||
|
||||
Sc::Physics::Physics(const PxTolerancesScale& scale, const PxvOffsetTable& pxvOffsetTable) : mScale(scale)
|
||||
{
|
||||
mInstance = this;
|
||||
PxvInit(pxvOffsetTable);
|
||||
}
|
||||
|
||||
Sc::Physics::~Physics()
|
||||
{
|
||||
PxvTerm();
|
||||
mInstance = NULL;
|
||||
}
|
||||
2910
engine/third_party/physx/source/simulationcontroller/src/ScPipeline.cpp
vendored
Normal file
2910
engine/third_party/physx/source/simulationcontroller/src/ScPipeline.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
167
engine/third_party/physx/source/simulationcontroller/src/ScRigidCore.cpp
vendored
Normal file
167
engine/third_party/physx/source/simulationcontroller/src/ScRigidCore.cpp
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScRigidCore.h"
|
||||
#include "ScRigidSim.h"
|
||||
#include "ScShapeSim.h"
|
||||
#include "ScScene.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
PX_IMPLEMENT_OUTPUT_ERROR
|
||||
|
||||
static ShapeSim* getSimForShape(const ShapeCore& core, const ActorSim& actorSim)
|
||||
{
|
||||
if(core.getExclusiveSim())
|
||||
{
|
||||
return core.getExclusiveSim();
|
||||
}
|
||||
|
||||
//Must be a shared shape.
|
||||
//Search backwards to emulate the behaviour of the previous linked list.
|
||||
PxU32 nbElems = actorSim.getNbElements();
|
||||
ElementSim*const* elems = actorSim.getElements() + (nbElems - 1);
|
||||
while (nbElems--)
|
||||
{
|
||||
ShapeSim* sim = static_cast<ShapeSim*>(*elems--);
|
||||
if (&sim->getCore() == &core)
|
||||
return sim;
|
||||
}
|
||||
|
||||
// Defensive coding added for OM-118444.
|
||||
// Switched this function to return a pointer rather than a reference.
|
||||
// This allows callers to avoid a crash in case the ShapeSim is not found.
|
||||
// The original use of a reference implies that this should never happen yet the crash in this ticket suggests that it's possible.
|
||||
// We could/should revert this eventually and remove the checks for NULL pointers in all callers in this file.
|
||||
// ### DEFENSIVE
|
||||
outputError<PxErrorCode::eINTERNAL_ERROR>(__LINE__, "ScRigidCore::getSimForShape: ShapeSim not found!");
|
||||
|
||||
PX_ASSERT(0); // should never fail
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RigidCore::RigidCore(const PxActorType::Enum type) : ActorCore(type, PxActorFlag::eVISUALIZATION, PX_DEFAULT_CLIENT, 0)
|
||||
{
|
||||
}
|
||||
|
||||
RigidCore::~RigidCore()
|
||||
{
|
||||
}
|
||||
|
||||
void RigidCore::addShapeToScene(ShapeCore& shapeCore)
|
||||
{
|
||||
RigidSim* sim = getSim();
|
||||
PX_ASSERT(sim);
|
||||
if(!sim)
|
||||
return;
|
||||
sim->getScene().addShape_(*sim, shapeCore);
|
||||
}
|
||||
|
||||
void RigidCore::removeShapeFromScene(ShapeCore& shapeCore, bool wakeOnLostTouch)
|
||||
{
|
||||
RigidSim* sim = getSim();
|
||||
if(!sim)
|
||||
return;
|
||||
|
||||
ShapeSim* s = getSimForShape(shapeCore, *sim);
|
||||
if(s)
|
||||
sim->getScene().removeShape_(*s, wakeOnLostTouch);
|
||||
}
|
||||
|
||||
void RigidCore::unregisterShapeFromNphase(Sc::ShapeCore& shapeCore)
|
||||
{
|
||||
RigidSim* sim = getSim();
|
||||
if (!sim)
|
||||
return;
|
||||
|
||||
ShapeSim* s = getSimForShape(shapeCore, *sim);
|
||||
if(s)
|
||||
s->getScene().unregisterShapeFromNphase(shapeCore, s->getElementID());
|
||||
}
|
||||
|
||||
void RigidCore::registerShapeInNphase(Sc::ShapeCore& shapeCore)
|
||||
{
|
||||
RigidSim* sim = getSim();
|
||||
if (!sim)
|
||||
return;
|
||||
|
||||
ShapeSim* s = getSimForShape(shapeCore, *sim);
|
||||
if(s)
|
||||
s->getScene().registerShapeInNphase(this, shapeCore, s->getElementID());
|
||||
}
|
||||
|
||||
void RigidCore::onShapeChange(ShapeCore& shape, ShapeChangeNotifyFlags notifyFlags)
|
||||
{
|
||||
RigidSim* sim = getSim();
|
||||
if(!sim)
|
||||
return;
|
||||
|
||||
ShapeSim* s = getSimForShape(shape, *sim);
|
||||
if(!s)
|
||||
return;
|
||||
|
||||
if(notifyFlags & ShapeChangeNotifyFlag::eGEOMETRY)
|
||||
s->onVolumeOrTransformChange();
|
||||
if(notifyFlags & ShapeChangeNotifyFlag::eRESET_FILTERING)
|
||||
s->onResetFiltering();
|
||||
if(notifyFlags & ShapeChangeNotifyFlag::eSHAPE2BODY)
|
||||
s->onVolumeOrTransformChange();
|
||||
if(notifyFlags & ShapeChangeNotifyFlag::eFILTERDATA)
|
||||
s->onFilterDataChange();
|
||||
if(notifyFlags & ShapeChangeNotifyFlag::eCONTACTOFFSET)
|
||||
s->onContactOffsetChange();
|
||||
if(notifyFlags & ShapeChangeNotifyFlag::eRESTOFFSET)
|
||||
s->onRestOffsetChange();
|
||||
}
|
||||
|
||||
void RigidCore::onShapeFlagsChange(ShapeCore& shape, PxShapeFlags oldShapeFlags)
|
||||
{
|
||||
// DS: We pass flags to avoid searching multiple times or exposing RigidSim outside SC.
|
||||
//If we start hitting this a lot we should do it
|
||||
// a different way, but shape modification after insertion is rare.
|
||||
|
||||
RigidSim* sim = getSim();
|
||||
if(!sim)
|
||||
return;
|
||||
|
||||
ShapeSim* s = getSimForShape(shape, *sim);
|
||||
if(s)
|
||||
s->onFlagChange(oldShapeFlags);
|
||||
}
|
||||
|
||||
RigidSim* RigidCore::getSim() const
|
||||
{
|
||||
return static_cast<RigidSim*>(ActorCore::getSim());
|
||||
}
|
||||
|
||||
PxU32 RigidCore::getRigidID() const
|
||||
{
|
||||
return static_cast<RigidSim*>(ActorCore::getSim())->getActorID();
|
||||
}
|
||||
|
||||
71
engine/third_party/physx/source/simulationcontroller/src/ScRigidSim.cpp
vendored
Normal file
71
engine/third_party/physx/source/simulationcontroller/src/ScRigidSim.cpp
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScScene.h"
|
||||
#include "ScRigidSim.h"
|
||||
#include "ScShapeSim.h"
|
||||
#include "PxsSimulationController.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
/*
|
||||
PT:
|
||||
|
||||
The BP group ID comes from a Cm::IDPool, and ActorSim is the only class releasing the ID.
|
||||
|
||||
The rigid tracker ID comes from a Cm::IDPool internal to an ObjectIDTracker, and ActorSim
|
||||
is the only class using it.
|
||||
|
||||
Thus we should:
|
||||
- promote the BP group ID stuff to a "tracker" object
|
||||
- use the BP group ID as a rigid ID
|
||||
*/
|
||||
|
||||
RigidSim::RigidSim(Scene& scene, RigidCore& core) : ActorSim(scene, core)
|
||||
{
|
||||
}
|
||||
|
||||
RigidSim::~RigidSim()
|
||||
{
|
||||
}
|
||||
|
||||
void notifyActorInteractionsOfTransformChange(ActorSim& actor);
|
||||
void RigidSim::notifyShapesOfTransformChange()
|
||||
{
|
||||
PxU32 nbElems = getNbElements();
|
||||
ElementSim** elems = getElements();
|
||||
while (nbElems--)
|
||||
{
|
||||
ShapeSim* sim = static_cast<ShapeSim*>(*elems++);
|
||||
sim->markBoundsForUpdate();
|
||||
}
|
||||
|
||||
notifyActorInteractionsOfTransformChange(*this);
|
||||
}
|
||||
|
||||
58
engine/third_party/physx/source/simulationcontroller/src/ScRigidSim.h
vendored
Normal file
58
engine/third_party/physx/source/simulationcontroller/src/ScRigidSim.h
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_RIGID_SIM_H
|
||||
#define SC_RIGID_SIM_H
|
||||
|
||||
#include "ScActorSim.h"
|
||||
#include "ScRigidCore.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class Scene;
|
||||
|
||||
class RigidSim : public ActorSim
|
||||
{
|
||||
public:
|
||||
RigidSim(Scene&, RigidCore&);
|
||||
virtual ~RigidSim();
|
||||
|
||||
PX_FORCE_INLINE RigidCore& getRigidCore() const { return static_cast<RigidCore&>(mCore); }
|
||||
|
||||
void notifyShapesOfTransformChange();
|
||||
|
||||
virtual PxActor* getPxActor() const { return getRigidCore().getPxActor(); }
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
3959
engine/third_party/physx/source/simulationcontroller/src/ScScene.cpp
vendored
Normal file
3959
engine/third_party/physx/source/simulationcontroller/src/ScScene.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
400
engine/third_party/physx/source/simulationcontroller/src/ScShapeCore.cpp
vendored
Normal file
400
engine/third_party/physx/source/simulationcontroller/src/ScShapeCore.cpp
vendored
Normal file
@@ -0,0 +1,400 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "foundation/PxErrorCallback.h"
|
||||
#include "ScShapeSim.h"
|
||||
#include "ScPhysics.h"
|
||||
#include "GuConvexMesh.h"
|
||||
#include "GuTriangleMesh.h"
|
||||
#include "GuHeightField.h"
|
||||
#include "GuTetrahedronMesh.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Gu;
|
||||
using namespace Cm;
|
||||
using namespace Sc;
|
||||
|
||||
static PX_FORCE_INLINE Gu::ConvexMesh& getConvexMesh(PxConvexMesh* pxcm)
|
||||
{
|
||||
return *static_cast<Gu::ConvexMesh*>(pxcm);
|
||||
}
|
||||
|
||||
// PT: TODO: optimize all these data copies
|
||||
void GeometryUnion::set(const PxGeometry& g)
|
||||
{
|
||||
// PT: preserve this field that can be used by higher-level code to store useful data
|
||||
const float saved = reinterpret_cast<const PxGeometry&>(mGeometry).mTypePadding;
|
||||
|
||||
switch(g.getType())
|
||||
{
|
||||
case PxGeometryType::eBOX:
|
||||
{
|
||||
reinterpret_cast<PxBoxGeometry&>(mGeometry) = static_cast<const PxBoxGeometry&>(g);
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eCAPSULE:
|
||||
{
|
||||
reinterpret_cast<PxCapsuleGeometry&>(mGeometry) = static_cast<const PxCapsuleGeometry&>(g);
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eSPHERE:
|
||||
{
|
||||
reinterpret_cast<PxSphereGeometry&>(mGeometry) = static_cast<const PxSphereGeometry&>(g);
|
||||
reinterpret_cast<PxCapsuleGeometry&>(mGeometry).halfHeight = 0.0f; //AM: make sphere geometry also castable as a zero height capsule.
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::ePLANE:
|
||||
{
|
||||
reinterpret_cast<PxPlaneGeometry&>(mGeometry) = static_cast<const PxPlaneGeometry&>(g);
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eCONVEXCORE:
|
||||
{
|
||||
reinterpret_cast<PxConvexCoreGeometry&>(mGeometry) = static_cast<const PxConvexCoreGeometry&>(g);
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eCONVEXMESH:
|
||||
{
|
||||
reinterpret_cast<PxConvexMeshGeometry&>(mGeometry) = static_cast<const PxConvexMeshGeometry&>(g);
|
||||
reinterpret_cast<PxConvexMeshGeometryLL&>(mGeometry).gpuCompatible = ::getConvexMesh(get<PxConvexMeshGeometryLL>().convexMesh).isGpuCompatible();
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::ePARTICLESYSTEM:
|
||||
{
|
||||
reinterpret_cast<PxParticleSystemGeometry&>(mGeometry) = static_cast<const PxParticleSystemGeometry&>(g);
|
||||
reinterpret_cast<PxParticleSystemGeometryLL&>(mGeometry).materialsLL = MaterialIndicesStruct();
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eTRIANGLEMESH:
|
||||
{
|
||||
reinterpret_cast<PxTriangleMeshGeometry&>(mGeometry) = static_cast<const PxTriangleMeshGeometry&>(g);
|
||||
reinterpret_cast<PxTriangleMeshGeometryLL&>(mGeometry).materialsLL = MaterialIndicesStruct();
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eTETRAHEDRONMESH:
|
||||
{
|
||||
reinterpret_cast<PxTetrahedronMeshGeometry&>(mGeometry) = static_cast<const PxTetrahedronMeshGeometry&>(g);
|
||||
reinterpret_cast<PxTetrahedronMeshGeometryLL&>(mGeometry).materialsLL = MaterialIndicesStruct();
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eHEIGHTFIELD:
|
||||
{
|
||||
reinterpret_cast<PxHeightFieldGeometry&>(mGeometry) = static_cast<const PxHeightFieldGeometry&>(g);
|
||||
reinterpret_cast<PxHeightFieldGeometryLL&>(mGeometry).materialsLL = MaterialIndicesStruct();
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eCUSTOM:
|
||||
{
|
||||
reinterpret_cast<PxCustomGeometry&>(mGeometry) = static_cast<const PxCustomGeometry&>(g);
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eGEOMETRY_COUNT:
|
||||
case PxGeometryType::eINVALID:
|
||||
PX_ALWAYS_ASSERT_MESSAGE("geometry type not handled");
|
||||
break;
|
||||
}
|
||||
|
||||
reinterpret_cast<PxGeometry&>(mGeometry).mTypePadding = saved;
|
||||
}
|
||||
|
||||
static PxConvexMeshGeometryLL extendForLL(const PxConvexMeshGeometry& hlGeom)
|
||||
{
|
||||
PxConvexMeshGeometryLL llGeom;
|
||||
static_cast<PxConvexMeshGeometry&>(llGeom) = hlGeom;
|
||||
|
||||
llGeom.gpuCompatible = hlGeom.convexMesh->isGpuCompatible();
|
||||
|
||||
return llGeom;
|
||||
}
|
||||
|
||||
static PxTriangleMeshGeometryLL extendForLL(const PxTriangleMeshGeometry& hlGeom)
|
||||
{
|
||||
PxTriangleMeshGeometryLL llGeom;
|
||||
static_cast<PxTriangleMeshGeometry&>(llGeom) = hlGeom;
|
||||
|
||||
llGeom.materialsLL = static_cast<const PxTriangleMeshGeometryLL&>(hlGeom).materialsLL;
|
||||
|
||||
return llGeom;
|
||||
}
|
||||
|
||||
static PxHeightFieldGeometryLL extendForLL(const PxHeightFieldGeometry& hlGeom)
|
||||
{
|
||||
PxHeightFieldGeometryLL llGeom;
|
||||
static_cast<PxHeightFieldGeometry&>(llGeom) = hlGeom;
|
||||
|
||||
llGeom.materialsLL = static_cast<const PxHeightFieldGeometryLL&>(hlGeom).materialsLL;
|
||||
|
||||
return llGeom;
|
||||
}
|
||||
|
||||
ShapeCore::ShapeCore(const PxGeometry& geometry, PxShapeFlags shapeFlags, const PxU16* materialIndices, PxU16 materialCount, bool isExclusive, PxShapeCoreFlag::Enum coreFlags) :
|
||||
mExclusiveSim(NULL)
|
||||
{
|
||||
mCore.mShapeCoreFlags |= PxShapeCoreFlag::eOWNS_MATERIAL_IDX_MEMORY;
|
||||
if(isExclusive)
|
||||
mCore.mShapeCoreFlags |= PxShapeCoreFlag::eIS_EXCLUSIVE;
|
||||
|
||||
mCore.mShapeCoreFlags |= coreFlags;
|
||||
|
||||
PX_ASSERT(materialCount > 0);
|
||||
|
||||
const PxTolerancesScale& scale = Physics::getInstance().getTolerancesScale();
|
||||
mCore.mGeometry.set(geometry);
|
||||
mCore.setTransform(PxTransform(PxIdentity));
|
||||
mCore.mContactOffset = 0.02f * scale.length;
|
||||
mCore.mRestOffset = 0.0f;
|
||||
mCore.mTorsionalRadius = 0.0f;
|
||||
mCore.mMinTorsionalPatchRadius = 0.0f;
|
||||
mCore.mShapeFlags = shapeFlags;
|
||||
|
||||
setMaterialIndices(materialIndices, materialCount);
|
||||
}
|
||||
|
||||
// PX_SERIALIZATION
|
||||
ShapeCore::ShapeCore(const PxEMPTY) :
|
||||
mSimulationFilterData (PxEmpty),
|
||||
mCore (PxEmpty),
|
||||
mExclusiveSim (NULL)
|
||||
{
|
||||
mCore.mShapeCoreFlags.clear(PxShapeCoreFlag::eOWNS_MATERIAL_IDX_MEMORY);
|
||||
}
|
||||
//~PX_SERIALIZATION
|
||||
|
||||
static PX_FORCE_INLINE const MaterialIndicesStruct* getMaterials(const GeometryUnion& gu)
|
||||
{
|
||||
const PxGeometryType::Enum type = gu.getType();
|
||||
if(type == PxGeometryType::eTRIANGLEMESH)
|
||||
return &gu.get<PxTriangleMeshGeometryLL>().materialsLL;
|
||||
else if(type == PxGeometryType::eHEIGHTFIELD)
|
||||
return &gu.get<PxHeightFieldGeometryLL>().materialsLL;
|
||||
else if(type == PxGeometryType::eTETRAHEDRONMESH)
|
||||
return &gu.get<PxTetrahedronMeshGeometryLL>().materialsLL;
|
||||
else if(type == PxGeometryType::ePARTICLESYSTEM)
|
||||
return &gu.get<PxParticleSystemGeometryLL>().materialsLL;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ShapeCore::~ShapeCore()
|
||||
{
|
||||
if(mCore.mShapeCoreFlags.isSet(PxShapeCoreFlag::eOWNS_MATERIAL_IDX_MEMORY))
|
||||
{
|
||||
MaterialIndicesStruct* materialsLL = const_cast<MaterialIndicesStruct*>(getMaterials(mCore.mGeometry));
|
||||
if(materialsLL)
|
||||
materialsLL->deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
PxU16 Sc::ShapeCore::getNbMaterialIndices() const
|
||||
{
|
||||
const MaterialIndicesStruct* materialsLL = getMaterials(mCore.mGeometry);
|
||||
return materialsLL ? materialsLL->numIndices : 1;
|
||||
}
|
||||
|
||||
const PxU16* Sc::ShapeCore::getMaterialIndices() const
|
||||
{
|
||||
const MaterialIndicesStruct* materialsLL = getMaterials(mCore.mGeometry);
|
||||
return materialsLL ? materialsLL->indices : &mCore.mMaterialIndex;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void setMaterialsHelper(MaterialIndicesStruct& materials, const PxU16* materialIndices, PxU16 materialIndexCount, PxShapeCoreFlags& shapeCoreFlags)
|
||||
{
|
||||
if(materials.numIndices < materialIndexCount)
|
||||
{
|
||||
if(materials.indices && shapeCoreFlags.isSet(PxShapeCoreFlag::eOWNS_MATERIAL_IDX_MEMORY))
|
||||
materials.deallocate();
|
||||
materials.allocate(materialIndexCount);
|
||||
shapeCoreFlags |= PxShapeCoreFlag::eOWNS_MATERIAL_IDX_MEMORY;
|
||||
}
|
||||
PxMemCopy(materials.indices, materialIndices, sizeof(PxU16)*materialIndexCount);
|
||||
materials.numIndices = materialIndexCount;
|
||||
}
|
||||
|
||||
void ShapeCore::setMaterialIndices(const PxU16* materialIndices, PxU16 materialIndexCount)
|
||||
{
|
||||
mCore.mMaterialIndex = materialIndices[0];
|
||||
|
||||
MaterialIndicesStruct* materialsLL = const_cast<MaterialIndicesStruct*>(getMaterials(mCore.mGeometry));
|
||||
if(materialsLL)
|
||||
setMaterialsHelper(*materialsLL, materialIndices, materialIndexCount, mCore.mShapeCoreFlags);
|
||||
}
|
||||
|
||||
void ShapeCore::setGeometry(const PxGeometry& geom)
|
||||
{
|
||||
const PxGeometryType::Enum newGeomType = geom.getType();
|
||||
|
||||
// copy material related data to restore it after the new geometry has been set
|
||||
MaterialIndicesStruct materials;
|
||||
PX_ASSERT(materials.numIndices == 0);
|
||||
|
||||
const MaterialIndicesStruct* materialsLL = getMaterials(mCore.mGeometry);
|
||||
if(materialsLL)
|
||||
materials = *materialsLL;
|
||||
|
||||
mCore.mGeometry.set(geom);
|
||||
|
||||
if((newGeomType == PxGeometryType::eTRIANGLEMESH) || (newGeomType == PxGeometryType::eHEIGHTFIELD)
|
||||
|| (newGeomType == PxGeometryType::eTETRAHEDRONMESH)|| (newGeomType == PxGeometryType::ePARTICLESYSTEM))
|
||||
{
|
||||
MaterialIndicesStruct* newMaterials = const_cast<MaterialIndicesStruct*>(getMaterials(mCore.mGeometry));
|
||||
PX_ASSERT(newMaterials);
|
||||
|
||||
if(materials.numIndices != 0) // old type was mesh type
|
||||
*newMaterials = materials;
|
||||
else
|
||||
{ // old type was non-mesh type
|
||||
newMaterials->allocate(1);
|
||||
*newMaterials->indices = mCore.mMaterialIndex;
|
||||
mCore.mShapeCoreFlags |= PxShapeCoreFlag::eOWNS_MATERIAL_IDX_MEMORY;
|
||||
}
|
||||
}
|
||||
else if((materials.numIndices != 0) && mCore.mShapeCoreFlags.isSet(PxShapeCoreFlag::eOWNS_MATERIAL_IDX_MEMORY))
|
||||
{
|
||||
// geometry changed to non-mesh type
|
||||
materials.deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
PxShape* ShapeCore::getPxShape()
|
||||
{
|
||||
return Sc::gOffsetTable.convertScShape2Px(this);
|
||||
}
|
||||
|
||||
const PxShape* ShapeCore::getPxShape() const
|
||||
{
|
||||
return Sc::gOffsetTable.convertScShape2Px(this);
|
||||
}
|
||||
|
||||
void ShapeCore::setContactOffset(const PxReal offset)
|
||||
{
|
||||
mCore.mContactOffset = offset;
|
||||
|
||||
ShapeSim* exclusiveSim = getExclusiveSim();
|
||||
if(exclusiveSim)
|
||||
exclusiveSim->getScene().updateContactDistance(exclusiveSim->getElementID(), offset);
|
||||
}
|
||||
|
||||
// PX_SERIALIZATION
|
||||
|
||||
PX_FORCE_INLINE void exportExtraDataMaterials(PxSerializationContext& stream, const MaterialIndicesStruct& materials)
|
||||
{
|
||||
stream.alignData(PX_SERIAL_ALIGN);
|
||||
stream.writeData(materials.indices, sizeof(PxU16)*materials.numIndices);
|
||||
}
|
||||
|
||||
void ShapeCore::exportExtraData(PxSerializationContext& stream)
|
||||
{
|
||||
const MaterialIndicesStruct* materialsLL = getMaterials(mCore.mGeometry);
|
||||
if(materialsLL)
|
||||
exportExtraDataMaterials(stream, *materialsLL);
|
||||
}
|
||||
|
||||
void ShapeCore::importExtraData(PxDeserializationContext& context)
|
||||
{
|
||||
MaterialIndicesStruct* materialsLL = const_cast<MaterialIndicesStruct*>(getMaterials(mCore.mGeometry));
|
||||
if(materialsLL)
|
||||
materialsLL->indices = context.readExtraData<PxU16, PX_SERIAL_ALIGN>(materialsLL->numIndices);
|
||||
}
|
||||
|
||||
void ShapeCore::resolveMaterialReference(PxU32 materialTableIndex, PxU16 materialIndex)
|
||||
{
|
||||
if(materialTableIndex == 0)
|
||||
mCore.mMaterialIndex = materialIndex;
|
||||
|
||||
MaterialIndicesStruct* materialsLL = const_cast<MaterialIndicesStruct*>(getMaterials(mCore.mGeometry));
|
||||
if(materialsLL)
|
||||
materialsLL->indices[materialTableIndex] = materialIndex;
|
||||
}
|
||||
|
||||
void ShapeCore::resolveReferences(PxDeserializationContext& context)
|
||||
{
|
||||
// Resolve geometry pointers if needed
|
||||
PxGeometry& geom = const_cast<PxGeometry&>(mCore.mGeometry.getGeometry());
|
||||
|
||||
switch(geom.getType())
|
||||
{
|
||||
case PxGeometryType::eCONVEXMESH:
|
||||
{
|
||||
PxConvexMeshGeometryLL& convexGeom = static_cast<PxConvexMeshGeometryLL&>(geom);
|
||||
context.translatePxBase(convexGeom.convexMesh);
|
||||
|
||||
// update the hullData pointer
|
||||
static_cast<PxConvexMeshGeometryLL&>(geom) = extendForLL(convexGeom);
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eHEIGHTFIELD:
|
||||
{
|
||||
PxHeightFieldGeometryLL& hfGeom = static_cast<PxHeightFieldGeometryLL&>(geom);
|
||||
context.translatePxBase(hfGeom.heightField);
|
||||
|
||||
// update hf pointers
|
||||
static_cast<PxHeightFieldGeometryLL&>(geom) = extendForLL(hfGeom);
|
||||
}
|
||||
break;
|
||||
|
||||
case PxGeometryType::eTRIANGLEMESH:
|
||||
{
|
||||
PxTriangleMeshGeometryLL& meshGeom = static_cast<PxTriangleMeshGeometryLL&>(geom);
|
||||
context.translatePxBase(meshGeom.triangleMesh);
|
||||
|
||||
// update mesh pointers
|
||||
static_cast<PxTriangleMeshGeometryLL&>(geom) = extendForLL(meshGeom);
|
||||
}
|
||||
break;
|
||||
case PxGeometryType::eTETRAHEDRONMESH:
|
||||
case PxGeometryType::ePARTICLESYSTEM:
|
||||
case PxGeometryType::eCUSTOM:
|
||||
{
|
||||
// implement
|
||||
PX_ASSERT(0);
|
||||
}
|
||||
break;
|
||||
case PxGeometryType::eSPHERE:
|
||||
case PxGeometryType::ePLANE:
|
||||
case PxGeometryType::eCAPSULE:
|
||||
case PxGeometryType::eBOX:
|
||||
case PxGeometryType::eCONVEXCORE:
|
||||
case PxGeometryType::eGEOMETRY_COUNT:
|
||||
case PxGeometryType::eINVALID:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//~PX_SERIALIZATION
|
||||
1169
engine/third_party/physx/source/simulationcontroller/src/ScShapeInteraction.cpp
vendored
Normal file
1169
engine/third_party/physx/source/simulationcontroller/src/ScShapeInteraction.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
343
engine/third_party/physx/source/simulationcontroller/src/ScShapeInteraction.h
vendored
Normal file
343
engine/third_party/physx/source/simulationcontroller/src/ScShapeInteraction.h
vendored
Normal file
@@ -0,0 +1,343 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_SHAPE_INTERACTION_H
|
||||
#define SC_SHAPE_INTERACTION_H
|
||||
|
||||
#include "ScElementSimInteraction.h"
|
||||
#include "ScShapeSim.h"
|
||||
#include "ScActorPair.h"
|
||||
#include "ScScene.h"
|
||||
#include "ScBodySim.h"
|
||||
#include "PxsContactManager.h"
|
||||
#include "PxsContext.h"
|
||||
#include "PxsSimpleIslandManager.h"
|
||||
|
||||
#define INVALID_REPORT_PAIR_ID 0xffffffff
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
class PxsContactManagerOutputIterator;
|
||||
namespace Sc
|
||||
{
|
||||
class ContactReportAllocationManager;
|
||||
|
||||
PX_FORCE_INLINE IG::Edge::EdgeType getInteractionEdgeType(PxActorType::Enum actorTypeLargest)
|
||||
{
|
||||
IG::Edge::EdgeType type = IG::Edge::eCONTACT_MANAGER;
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
if(actorTypeLargest == PxActorType::eDEFORMABLE_VOLUME)
|
||||
type = IG::Edge::eSOFT_BODY_CONTACT;
|
||||
else if(actorTypeLargest == PxActorType::eDEFORMABLE_SURFACE)
|
||||
type = IG::Edge::eFEM_CLOTH_CONTACT;
|
||||
else if(actorTypeLargest == PxActorType::ePBD_PARTICLESYSTEM)
|
||||
type = IG::Edge::ePARTICLE_SYSTEM_CONTACT;
|
||||
#else
|
||||
PX_UNUSED(actorTypeLargest);
|
||||
#endif
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
Description: A ShapeInteraction represents a pair of objects which _may_ have contacts. Created by the broadphase
|
||||
and processed by the NPhaseCore.
|
||||
*/
|
||||
class ShapeInteraction : public ElementSimInteraction
|
||||
{
|
||||
friend class NPhaseCore;
|
||||
ShapeInteraction& operator=(const ShapeInteraction&);
|
||||
public:
|
||||
enum SiFlag
|
||||
{
|
||||
PAIR_FLAGS_MASK = (PxPairFlag::eNEXT_FREE - 1), // Bits where the PxPairFlags get stored
|
||||
NEXT_FREE = ((PAIR_FLAGS_MASK << 1) & ~PAIR_FLAGS_MASK),
|
||||
|
||||
HAS_TOUCH = (NEXT_FREE << 0), // Tracks the last know touch state
|
||||
HAS_NO_TOUCH = (NEXT_FREE << 1), // Tracks the last know touch state
|
||||
TOUCH_KNOWN = (HAS_TOUCH | HAS_NO_TOUCH), // If none of these flags is set, the touch state is not known (for example, this is true for pairs that never ran narrowphase
|
||||
|
||||
CONTACTS_COLLECT_POINTS = (NEXT_FREE << 2), // The user wants to get the contact points (includes debug rendering)
|
||||
CONTACTS_RESPONSE_DISABLED = (NEXT_FREE << 3), // Collision response disabled (either by the user through PxPairFlag::eSOLVE_CONTACT or because the pair has two kinematics)
|
||||
|
||||
CONTACT_FORCE_THRESHOLD_PAIRS = PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_FOUND) | PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_PERSISTS) | PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_LOST),
|
||||
CONTACT_REPORT_EVENTS = PxU32(PxPairFlag::eNOTIFY_TOUCH_FOUND) | PxU32(PxPairFlag::eNOTIFY_TOUCH_PERSISTS) | PxU32(PxPairFlag::eNOTIFY_TOUCH_LOST) |
|
||||
PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_FOUND) | PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_PERSISTS) | PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_LOST),
|
||||
CONTACT_REPORT_EXTRA_DATA = PxU32(PxPairFlag::ePRE_SOLVER_VELOCITY) | PxU32(PxPairFlag::ePOST_SOLVER_VELOCITY) | PxU32(PxPairFlag::eCONTACT_EVENT_POSE),
|
||||
|
||||
FORCE_THRESHOLD_EXCEEDED_NOW = (NEXT_FREE << 4),
|
||||
FORCE_THRESHOLD_EXCEEDED_BEFORE = (NEXT_FREE << 5),
|
||||
FORCE_THRESHOLD_EXCEEDED_FLAGS = FORCE_THRESHOLD_EXCEEDED_NOW | FORCE_THRESHOLD_EXCEEDED_BEFORE,
|
||||
|
||||
IS_IN_PERSISTENT_EVENT_LIST = (NEXT_FREE << 6), // The pair is in the list of persistent contact events
|
||||
WAS_IN_PERSISTENT_EVENT_LIST = (NEXT_FREE << 7), // The pair is inactive but used to be in the list of persistent contact events
|
||||
IN_PERSISTENT_EVENT_LIST = IS_IN_PERSISTENT_EVENT_LIST | WAS_IN_PERSISTENT_EVENT_LIST,
|
||||
IS_IN_FORCE_THRESHOLD_EVENT_LIST= (NEXT_FREE << 8), // The pair is in the list of force threshold contact events
|
||||
IS_IN_CONTACT_EVENT_LIST = IS_IN_PERSISTENT_EVENT_LIST | IS_IN_FORCE_THRESHOLD_EVENT_LIST,
|
||||
|
||||
LL_MANAGER_RECREATE_EVENT = CONTACT_REPORT_EVENTS | CONTACTS_COLLECT_POINTS |
|
||||
CONTACTS_RESPONSE_DISABLED | PxU32(PxPairFlag::eMODIFY_CONTACTS)
|
||||
};
|
||||
ShapeInteraction(ShapeSimBase& s1, ShapeSimBase& s2, PxPairFlags pairFlags, PxsContactManager* contactManager);
|
||||
~ShapeInteraction();
|
||||
|
||||
// Submits to contact stream
|
||||
void processUserNotification(PxU32 contactEvent, PxU16 infoFlags, bool touchLost, PxU32 ccdPass, bool useCurrentTransform,
|
||||
PxsContactManagerOutputIterator& outputs); // ccdPass is 0 for discrete collision and then 1,2,... for the CCD passes
|
||||
void processUserNotificationSync();
|
||||
void processUserNotificationAsync(PxU32 contactEvent, PxU16 infoFlags, bool touchLost, PxU32 ccdPass, bool useCurrentTransform,
|
||||
PxsContactManagerOutputIterator& outputs, ContactReportAllocationManager* alloc = NULL); // ccdPass is 0 for discrete collision and then 1,2,... for the CCD passes
|
||||
|
||||
void visualize( PxRenderOutput&, PxsContactManagerOutputIterator&,
|
||||
float scale, float contactImpulse, float contactNormal, float contactError, float contactPoint,
|
||||
float frictionImpulse, float frictionNormal, float frictionPoint);
|
||||
|
||||
PxU32 getContactPointData(const void*& contactPatches, const void*& contactPoints, PxU32& contactDataSize, PxU32& contactPointCount, PxU32& patchCount, const PxReal*& impulses, PxU32 startOffset, PxsContactManagerOutputIterator& outputs);
|
||||
PxU32 getContactPointData(const void*& contactPatches, const void*& contactPoints, PxU32& contactDataSize, PxU32& contactPointCount, PxU32& patchCount, const PxReal*& impulses, PxU32 startOffset, PxsContactManagerOutputIterator& outputs, const void*& frictionPatches);
|
||||
|
||||
bool managerLostTouch(PxU32 ccdPass, PxsContactManagerOutputIterator& outputs);
|
||||
void managerNewTouch(PxU32 ccdPass, PxsContactManagerOutputIterator& outputs);
|
||||
|
||||
PX_FORCE_INLINE void adjustCountersOnLostTouch();
|
||||
PX_FORCE_INLINE void adjustCountersOnNewTouch();
|
||||
|
||||
PX_FORCE_INLINE void sendCCDRetouch(PxU32 ccdPass, PxsContactManagerOutputIterator& outputs);
|
||||
void setContactReportPostSolverVelocity(ContactStreamManager& cs);
|
||||
void sendLostTouchReport(bool shapeVolumeRemoved, PxU32 ccdPass, PxsContactManagerOutputIterator& ouptuts);
|
||||
void resetManagerCachedState() const;
|
||||
|
||||
PX_FORCE_INLINE ActorPair* getActorPair() const { return mActorPair; }
|
||||
PX_FORCE_INLINE void setActorPair(ActorPair& aPair) { mActorPair = &aPair; }
|
||||
PX_FORCE_INLINE void clearActorPair() { mActorPair = NULL; }
|
||||
PX_FORCE_INLINE ActorPairReport& getActorPairReport() const { return ActorPairReport::cast(*mActorPair); }
|
||||
PX_INLINE PxIntBool isReportPair() const { /*PX_ASSERT(!(PxIntBool(getPairFlags() & CONTACT_REPORT_EVENTS)) || mActorPair->isReportPair());*/ return PxIntBool(getPairFlags() & CONTACT_REPORT_EVENTS); }
|
||||
PX_INLINE PxIntBool hasTouch() const { return readFlag(HAS_TOUCH); }
|
||||
PX_INLINE PxIntBool hasCCDTouch() const { PX_ASSERT(mManager); return mManager->getHadCCDContact(); }
|
||||
PX_INLINE void swapAndClearForceThresholdExceeded();
|
||||
|
||||
PX_FORCE_INLINE void raiseFlag(SiFlag flag) { mFlags |= flag; }
|
||||
PX_FORCE_INLINE PxIntBool readFlag(SiFlag flag) const { return PxIntBool(mFlags & flag); }
|
||||
PX_FORCE_INLINE PxU32 getPairFlags() const;
|
||||
|
||||
PX_FORCE_INLINE void removeFromReportPairList();
|
||||
|
||||
void onShapeChangeWhileSleeping(bool shapeOfDynamicChanged);
|
||||
|
||||
PX_FORCE_INLINE PxIntBool hasKnownTouchState() const;
|
||||
|
||||
bool onActivate(PxsContactManager* contactManager);
|
||||
bool onDeactivate();
|
||||
|
||||
void updateState(const PxU8 externalDirtyFlags);
|
||||
|
||||
const PxsContactManager* getContactManager() const { return mManager; }
|
||||
|
||||
void clearIslandGenData(IG::SimpleIslandManager& islandManager);
|
||||
|
||||
PX_FORCE_INLINE IG::EdgeIndex getEdgeIndex() const { return mEdgeIndex; }
|
||||
|
||||
PX_FORCE_INLINE Sc::ShapeSimBase& getShape0() const { return static_cast<ShapeSimBase&>(getElement0()); }
|
||||
PX_FORCE_INLINE Sc::ShapeSimBase& getShape1() const { return static_cast<ShapeSimBase&>(getElement1()); }
|
||||
|
||||
PX_FORCE_INLINE Sc::ActorSim& getActor0() { return getActorSim0(); }
|
||||
PX_FORCE_INLINE Sc::ActorSim& getActor1() { return getActorSim1(); }
|
||||
|
||||
private:
|
||||
ActorPair* mActorPair;
|
||||
PxsContactManager* mManager;
|
||||
PxU32 mContactReportStamp;
|
||||
PxU32 mReportPairIndex; // Owned by NPhaseCore for its report pair list
|
||||
PxU32 mReportStreamIndex; // position of this pair in the contact report stream
|
||||
|
||||
void createManager(PxsContactManager* contactManager);
|
||||
PX_INLINE bool updateManager(PxsContactManager* contactManager);
|
||||
PX_INLINE void destroyManager();
|
||||
PX_FORCE_INLINE bool activeManagerAllowed() const;
|
||||
PX_FORCE_INLINE PxU32 getManagerContactState() const { return mFlags & LL_MANAGER_RECREATE_EVENT; }
|
||||
|
||||
PX_FORCE_INLINE void clearFlag(SiFlag flag) { mFlags &= ~flag; }
|
||||
PX_INLINE void setFlag(SiFlag flag, bool value)
|
||||
{
|
||||
if (value)
|
||||
raiseFlag(flag);
|
||||
else
|
||||
clearFlag(flag);
|
||||
}
|
||||
PX_FORCE_INLINE void setHasTouch() { clearFlag(HAS_NO_TOUCH); raiseFlag(HAS_TOUCH); }
|
||||
PX_FORCE_INLINE void setHasNoTouch() { clearFlag(HAS_TOUCH); raiseFlag(HAS_NO_TOUCH); }
|
||||
|
||||
PX_FORCE_INLINE void setPairFlags(PxPairFlags flags);
|
||||
|
||||
PX_FORCE_INLINE void processReportPairOnActivate();
|
||||
PX_FORCE_INLINE void processReportPairOnDeactivate();
|
||||
|
||||
// Certain SiFlag cache properties of the pair. If these properties change then the flags have to be updated.
|
||||
// For example: is collision enabled for this pair? are contact points requested for this pair?
|
||||
PX_FORCE_INLINE void updateFlags(const Sc::Scene&, const Sc::ActorSim&, const Sc::ActorSim&, const PxU32 pairFlags);
|
||||
|
||||
friend class Sc::Scene;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
PX_FORCE_INLINE void Sc::ShapeInteraction::setPairFlags(PxPairFlags flags)
|
||||
{
|
||||
PX_ASSERT(PxU32(flags) < PxPairFlag::eNEXT_FREE); // to find out if a new PxPairFlag has been added after eLAST instead of in front
|
||||
|
||||
PxU32 newFlags = mFlags;
|
||||
PxU32 fl = PxU32(flags) & PAIR_FLAGS_MASK;
|
||||
newFlags &= (~PAIR_FLAGS_MASK); // clear old flags
|
||||
newFlags |= fl;
|
||||
|
||||
mFlags = newFlags;
|
||||
}
|
||||
|
||||
// PT: returning PxU32 instead of PxPairFlags to remove LHS. Please do not undo this.
|
||||
PX_FORCE_INLINE PxU32 Sc::ShapeInteraction::getPairFlags() const
|
||||
{
|
||||
return (mFlags & PAIR_FLAGS_MASK);
|
||||
}
|
||||
|
||||
PX_INLINE void Sc::ShapeInteraction::swapAndClearForceThresholdExceeded()
|
||||
{
|
||||
PxU32 flags = mFlags;
|
||||
|
||||
PX_COMPILE_TIME_ASSERT(FORCE_THRESHOLD_EXCEEDED_NOW == (FORCE_THRESHOLD_EXCEEDED_BEFORE >> 1));
|
||||
|
||||
PxU32 nowToBefore = (flags & FORCE_THRESHOLD_EXCEEDED_NOW) << 1;
|
||||
flags &= ~(FORCE_THRESHOLD_EXCEEDED_NOW | FORCE_THRESHOLD_EXCEEDED_BEFORE);
|
||||
flags |= nowToBefore;
|
||||
|
||||
mFlags = flags;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void Sc::ShapeInteraction::removeFromReportPairList()
|
||||
{
|
||||
// this method should only get called if the pair is in the list for
|
||||
// persistent or force based contact reports
|
||||
PX_ASSERT(mReportPairIndex != INVALID_REPORT_PAIR_ID);
|
||||
PX_ASSERT(readFlag(IS_IN_CONTACT_EVENT_LIST));
|
||||
|
||||
Scene& scene = getScene();
|
||||
|
||||
if (readFlag(IS_IN_FORCE_THRESHOLD_EVENT_LIST))
|
||||
scene.getNPhaseCore()->removeFromForceThresholdContactEventPairs(this);
|
||||
else
|
||||
{
|
||||
PX_ASSERT(readFlag(IS_IN_PERSISTENT_EVENT_LIST));
|
||||
scene.getNPhaseCore()->removeFromPersistentContactEventPairs(this);
|
||||
}
|
||||
}
|
||||
|
||||
PX_INLINE bool Sc::ShapeInteraction::updateManager(PxsContactManager* contactManager)
|
||||
{
|
||||
if (activeManagerAllowed())
|
||||
{
|
||||
if (mManager == 0)
|
||||
createManager(contactManager);
|
||||
|
||||
return (mManager != NULL); // creation might fail (pool reached limit, mem allocation failed etc.)
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
PX_INLINE void Sc::ShapeInteraction::destroyManager()
|
||||
{
|
||||
PX_ASSERT(mManager);
|
||||
|
||||
Scene& scene = getScene();
|
||||
|
||||
PxvNphaseImplementationContext* nphaseImplementationContext = scene.getLowLevelContext()->getNphaseImplementationContext();
|
||||
PX_ASSERT(nphaseImplementationContext);
|
||||
nphaseImplementationContext->unregisterContactManager(mManager);
|
||||
|
||||
/*if (mEdgeIndex != IG_INVALID_EDGE)
|
||||
scene.getSimpleIslandManager()->clearEdgeRigidCM(mEdgeIndex);*/
|
||||
scene.getLowLevelContext()->destroyContactManager(mManager);
|
||||
mManager = 0;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE bool Sc::ShapeInteraction::activeManagerAllowed() const
|
||||
{
|
||||
ActorSim& bodySim0 = getActorSim0();
|
||||
ActorSim& bodySim1 = getActorSim1();
|
||||
|
||||
// the first shape always belongs to a dynamic body or deformable volume
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
PX_ASSERT(bodySim0.isDynamicRigid() || bodySim0.isDeformableSurface() || bodySim0.isDeformableVolume() || bodySim0.isParticleSystem());
|
||||
#else
|
||||
PX_ASSERT(bodySim0.isDynamicRigid());
|
||||
#endif
|
||||
|
||||
// PT: try to prevent OM-103695 / PX-4509
|
||||
// ### DEFENSIVE
|
||||
if(!bodySim0.getNodeIndex().isValid())
|
||||
return PxGetFoundation().error(PxErrorCode::eINTERNAL_ERROR, PX_FL, "ShapeInteraction::activeManagerAllowed: found invalid node!");
|
||||
|
||||
const IG::IslandSim& islandSim = getScene().getSimpleIslandManager()->getSpeculativeIslandSim();
|
||||
|
||||
//check whether active in the speculative sim!
|
||||
return (islandSim.getNode(bodySim0.getNodeIndex()).isActive() ||
|
||||
(!bodySim1.isStaticRigid() && islandSim.getNode(bodySim1.getNodeIndex()).isActive()));
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void Sc::ShapeInteraction::sendCCDRetouch(PxU32 ccdPass, PxsContactManagerOutputIterator& outputs)
|
||||
{
|
||||
const PxU32 pairFlags = getPairFlags();
|
||||
if (pairFlags & PxPairFlag::eNOTIFY_TOUCH_CCD)
|
||||
processUserNotification(PxPairFlag::eNOTIFY_TOUCH_CCD, 0, false, ccdPass, false, outputs);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void Sc::ShapeInteraction::adjustCountersOnLostTouch()
|
||||
{
|
||||
PX_ASSERT(mActorPair->getTouchCount());
|
||||
|
||||
mActorPair->decTouchCount();
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void Sc::ShapeInteraction::adjustCountersOnNewTouch()
|
||||
{
|
||||
mActorPair->incTouchCount();
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxIntBool Sc::ShapeInteraction::hasKnownTouchState() const
|
||||
{
|
||||
// For a pair where the bodies were added asleep, the touch state is not known until narrowphase runs on the pair for the first time.
|
||||
// If such a pair looses AABB overlap before, the conservative approach is to wake the bodies up. This method provides an indicator that
|
||||
// this is such a pair. Note: this might also wake up objects that do not touch but that's the price to pay (unless we want to run
|
||||
// overlap tests on such pairs).
|
||||
if (mManager)
|
||||
return mManager->touchStatusKnown();
|
||||
else
|
||||
return readFlag(TOUCH_KNOWN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
49
engine/third_party/physx/source/simulationcontroller/src/ScShapeSim.cpp
vendored
Normal file
49
engine/third_party/physx/source/simulationcontroller/src/ScShapeSim.cpp
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScShapeSim.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
void resetElementID(Scene& scene, ShapeSimBase& shapeSim);
|
||||
|
||||
ShapeSim::ShapeSim(ActorSim& owner, ShapeCore& core) : ShapeSimBase(owner, &core)
|
||||
{
|
||||
const PxU32 index = getElementID();
|
||||
initSubsystemsDependingOnElementID(index);
|
||||
core.setExclusiveSim(this);
|
||||
}
|
||||
|
||||
ShapeSim::~ShapeSim()
|
||||
{
|
||||
Sc::ShapeCore::getCore(*mShapeCore).setExclusiveSim(NULL);
|
||||
Scene& scScene = getScene();
|
||||
resetElementID(scScene, *this);
|
||||
}
|
||||
|
||||
58
engine/third_party/physx/source/simulationcontroller/src/ScShapeSim.h
vendored
Normal file
58
engine/third_party/physx/source/simulationcontroller/src/ScShapeSim.h
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_SHAPE_SIM_H
|
||||
#define SC_SHAPE_SIM_H
|
||||
|
||||
#include "ScShapeSimBase.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
/** Simulation object corresponding to a shape core object. This object is created when
|
||||
a ShapeCore object is added to the simulation, and destroyed when it is removed
|
||||
*/
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
class ActorSim;
|
||||
class ShapeCore;
|
||||
|
||||
class ShapeSim : public ShapeSimBase
|
||||
{
|
||||
PX_NOCOPY(ShapeSim)
|
||||
public:
|
||||
ShapeSim(ActorSim&, ShapeCore& core);
|
||||
~ShapeSim();
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
432
engine/third_party/physx/source/simulationcontroller/src/ScShapeSimBase.cpp
vendored
Normal file
432
engine/third_party/physx/source/simulationcontroller/src/ScShapeSimBase.cpp
vendored
Normal file
@@ -0,0 +1,432 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
|
||||
#include "ScShapeSimBase.h"
|
||||
#include "ScSqBoundsManager.h"
|
||||
#include "ScTriggerInteraction.h"
|
||||
#include "ScSimulationController.h"
|
||||
#include "CmTransformUtils.h"
|
||||
#include "ScShapeInteraction.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
// PT: keep local functions in cpp, no need to pollute the header. Don't force conversions to bool if not necessary.
|
||||
static PX_FORCE_INLINE PxU32 hasTriggerFlags(PxShapeFlags flags) { return PxU32(flags) & PxU32(PxShapeFlag::eTRIGGER_SHAPE); }
|
||||
|
||||
void resetElementID(Scene& scene, ShapeSimBase& shapeSim)
|
||||
{
|
||||
PX_ASSERT(!shapeSim.isInBroadPhase());
|
||||
|
||||
// scene.getDirtyShapeSimMap().reset(shapeSim.getElementID());
|
||||
scene.getDirtyShapeSimMap().boundedReset(shapeSim.getElementID());
|
||||
|
||||
if (shapeSim.getSqBoundsId() != PX_INVALID_U32)
|
||||
shapeSim.destroySqBounds();
|
||||
}
|
||||
|
||||
static PX_INLINE Bp::FilterGroup::Enum getBPGroup(const ShapeSimBase& shapeSim)
|
||||
{
|
||||
const BodySim* bs = shapeSim.getBodySim();
|
||||
|
||||
const RigidSim& rbSim = shapeSim.getRbSim();
|
||||
|
||||
bool isKinematic = bs ? bs->isKinematic() : false;
|
||||
|
||||
if (isKinematic && bs->hasForcedKinematicNotif())
|
||||
isKinematic = false;
|
||||
|
||||
return Bp::getFilterGroup(rbSim.getActorType() == PxActorType::eRIGID_STATIC, rbSim.getActorID(), isKinematic);
|
||||
}
|
||||
|
||||
static void setElementInteractionsDirty(Sc::ElementSim& elementSim, InteractionDirtyFlag::Enum flag, PxU8 interactionFlag)
|
||||
{
|
||||
ElementSim::ElementInteractionIterator iter = elementSim.getElemInteractions();
|
||||
ElementSimInteraction* interaction = iter.getNext();
|
||||
while(interaction)
|
||||
{
|
||||
if(interaction->readInteractionFlag(interactionFlag))
|
||||
interaction->setDirty(flag);
|
||||
|
||||
interaction = iter.getNext();
|
||||
}
|
||||
}
|
||||
|
||||
void ShapeSimBase::onFilterDataChange()
|
||||
{
|
||||
setElementInteractionsDirty(*this, InteractionDirtyFlag::eFILTER_STATE, InteractionFlag::eFILTERABLE);
|
||||
}
|
||||
|
||||
void ShapeSimBase::onResetFiltering()
|
||||
{
|
||||
if (isInBroadPhase())
|
||||
reinsertBroadPhase();
|
||||
}
|
||||
|
||||
void ShapeSimBase::onRestOffsetChange()
|
||||
{
|
||||
setElementInteractionsDirty(*this, InteractionDirtyFlag::eREST_OFFSET, InteractionFlag::eRB_ELEMENT);
|
||||
}
|
||||
|
||||
void ShapeSimBase::onContactOffsetChange()
|
||||
{
|
||||
if (isInBroadPhase())
|
||||
getScene().getAABBManager()->setContactDistance(getElementID(), getCore().getContactOffset());
|
||||
}
|
||||
|
||||
void ShapeSimBase::removeFromBroadPhase(bool wakeOnLostTouch)
|
||||
{
|
||||
if (isInBroadPhase())
|
||||
internalRemoveFromBroadPhase(wakeOnLostTouch);
|
||||
}
|
||||
|
||||
void ShapeSimBase::reinsertBroadPhase()
|
||||
{
|
||||
bool wasPendingInsert = false;
|
||||
if (isInBroadPhase())
|
||||
{
|
||||
wasPendingInsert = internalRemoveFromBroadPhase();
|
||||
}
|
||||
// internalAddToBroadPhase();
|
||||
|
||||
Scene& scene = getScene();
|
||||
|
||||
// Scene::removeShape
|
||||
{
|
||||
//unregisterShapeFromNphase(shape.getCore());
|
||||
|
||||
scene.getSimulationController()->removePxgShape(getElementID());
|
||||
|
||||
scene.unregisterShapeFromNphase(getCore(), getElementID());
|
||||
}
|
||||
PxU32 indexFrom = getElementID();
|
||||
|
||||
// Call ShapeSim dtor
|
||||
{
|
||||
resetElementID(scene, *this);
|
||||
}
|
||||
|
||||
// Call ElementSim dtor - only required if this shape was not pending insert (otherwise the elementID is fine to keep)
|
||||
if (!wasPendingInsert)
|
||||
{
|
||||
{
|
||||
releaseID();
|
||||
}
|
||||
|
||||
// Call ElementSim ctor
|
||||
{
|
||||
initID();
|
||||
}
|
||||
}
|
||||
|
||||
// Call ShapeSim ctor
|
||||
{
|
||||
initSubsystemsDependingOnElementID(indexFrom);
|
||||
}
|
||||
|
||||
// Scene::addShape
|
||||
{
|
||||
scene.getSimulationController()->addPxgShape(this, getPxsShapeCore(), getActorNodeIndex(), getElementID());
|
||||
|
||||
// PT: TODO: anything else needed here?
|
||||
scene.registerShapeInNphase(&getRbSim().getRigidCore(), getCore(), getElementID()); // register in narrowphase getElementID() - transformcacheID. so I guess we must know at this point the definite index
|
||||
}
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void ShapeSimBase::internalAddToBroadPhase()
|
||||
{
|
||||
PX_ASSERT(!isInBroadPhase());
|
||||
|
||||
addToAABBMgr(getCore().getContactOffset(), getBPGroup(*this), (getCore().getCore().mShapeFlags & PxShapeFlag::eTRIGGER_SHAPE) ? Bp::ElementType::eTRIGGER : Bp::ElementType::eSHAPE);
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE bool ShapeSimBase::internalRemoveFromBroadPhase(bool wakeOnLostTouch)
|
||||
{
|
||||
PX_ASSERT(isInBroadPhase());
|
||||
bool res = removeFromAABBMgr();
|
||||
|
||||
Scene& scene = getScene();
|
||||
PxsContactManagerOutputIterator outputs = scene.getLowLevelContext()->getNphaseImplementationContext()->getContactManagerOutputs();
|
||||
scene.getNPhaseCore()->onVolumeRemoved(this, wakeOnLostTouch ? PxU32(PairReleaseFlag::eWAKE_ON_LOST_TOUCH) : 0, outputs);
|
||||
return res;
|
||||
}
|
||||
|
||||
void ShapeSimBase::initSubsystemsDependingOnElementID(PxU32 indexFrom)
|
||||
{
|
||||
Scene& scScene = getScene();
|
||||
|
||||
Bp::BoundsArray& boundsArray = scScene.getBoundsArray();
|
||||
const PxU32 index = getElementID();
|
||||
|
||||
PX_ALIGN(16, PxTransform absPos);
|
||||
getAbsPoseAligned(&absPos);
|
||||
|
||||
PxsTransformCache& cache = scScene.getLowLevelContext()->getTransformCache();
|
||||
cache.initEntry(index);
|
||||
cache.setTransformCache(absPos, 0, index, indexFrom);
|
||||
|
||||
boundsArray.updateBounds(absPos, getCore().getGeometryUnion().getGeometry(), index, indexFrom);
|
||||
|
||||
{
|
||||
PX_PROFILE_ZONE("API.simAddShapeToBroadPhase", scScene.getContextId());
|
||||
if (isBroadPhase(getCore().getFlags()))
|
||||
internalAddToBroadPhase();
|
||||
else
|
||||
scScene.getAABBManager()->reserveSpaceForBounds(index);
|
||||
scScene.updateContactDistance(index, getContactOffset());
|
||||
}
|
||||
|
||||
// if(scScene.getDirtyShapeSimMap().size() <= index)
|
||||
// scScene.getDirtyShapeSimMap().resize(PxMax(index+1, (scScene.getDirtyShapeSimMap().size()+1) * 2u));
|
||||
|
||||
ActorSim& owner = mActor;
|
||||
|
||||
if (owner.isDynamicRigid() && static_cast<BodySim&>(owner).isActive())
|
||||
createSqBounds();
|
||||
}
|
||||
|
||||
PxNodeIndex ShapeSimBase::getActorNodeIndex() const
|
||||
{
|
||||
ActorSim& owner = mActor;
|
||||
return owner.getActorType() == PxActorType::eRIGID_STATIC ? PxNodeIndex(PX_INVALID_NODE) : static_cast<BodySim&>(owner).getNodeIndex();
|
||||
}
|
||||
|
||||
void ShapeSimBase::getAbsPoseAligned(PxTransform* PX_RESTRICT globalPose) const
|
||||
{
|
||||
// PT: TODO: simplify dynamic case when shape2Actor = idt
|
||||
|
||||
const PxsShapeCore& shapeCore = getCore().getCore();
|
||||
|
||||
const PxTransform& shape2Actor = shapeCore.getTransform();
|
||||
const PxTransform* actor2World = NULL;
|
||||
if (getActor().getActorType() == PxActorType::eRIGID_STATIC)
|
||||
{
|
||||
PxsRigidCore& core = static_cast<StaticSim&>(getActor()).getStaticCore().getCore();
|
||||
|
||||
if (shapeCore.mShapeCoreFlags.isSet(PxShapeCoreFlag::eIDT_TRANSFORM))
|
||||
{
|
||||
PX_ASSERT(shape2Actor.p.isZero() && shape2Actor.q.isIdentity());
|
||||
*globalPose = core.body2World;
|
||||
return;
|
||||
}
|
||||
|
||||
actor2World = &core.body2World;
|
||||
}
|
||||
else
|
||||
{
|
||||
PxsBodyCore& core = static_cast<BodySim&>(getActor()).getBodyCore().getCore();
|
||||
if (!core.hasIdtBody2Actor())
|
||||
{
|
||||
Cm::getDynamicGlobalPoseAligned(core.body2World, shape2Actor, core.getBody2Actor(), *globalPose);
|
||||
return;
|
||||
}
|
||||
actor2World = &core.body2World;
|
||||
}
|
||||
Cm::getStaticGlobalPoseAligned(*actor2World, shape2Actor, *globalPose);
|
||||
}
|
||||
|
||||
void ShapeSimBase::onFlagChange(PxShapeFlags oldFlags)
|
||||
{
|
||||
const PxShapeFlags newFlags = getCore().getFlags();
|
||||
|
||||
const bool oldBp = isBroadPhase(oldFlags) != 0;
|
||||
const bool newBp = isBroadPhase(newFlags) != 0;
|
||||
|
||||
// Change of collision shape flags requires removal/add to broadphase
|
||||
if (oldBp != newBp)
|
||||
{
|
||||
if (!oldBp && newBp)
|
||||
{
|
||||
// A.B. if a trigger was removed and inserted within the same frame we need to reinsert
|
||||
if (hasTriggerFlags(newFlags) && getScene().getAABBManager()->isMarkedForRemove(getElementID()))
|
||||
reinsertBroadPhase();
|
||||
else
|
||||
internalAddToBroadPhase();
|
||||
}
|
||||
else
|
||||
internalRemoveFromBroadPhase();
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool wasTrigger = hasTriggerFlags(oldFlags) != 0;
|
||||
const bool isTrigger = hasTriggerFlags(newFlags) != 0;
|
||||
if (wasTrigger != isTrigger)
|
||||
reinsertBroadPhase(); // re-insertion is necessary because trigger pairs get killed
|
||||
}
|
||||
|
||||
const PxShapeFlags hadSq = oldFlags & PxShapeFlag::eSCENE_QUERY_SHAPE;
|
||||
const PxShapeFlags hasSq = newFlags & PxShapeFlag::eSCENE_QUERY_SHAPE;
|
||||
if (hasSq && !hadSq)
|
||||
{
|
||||
BodySim* body = getBodySim();
|
||||
if (body && body->isActive())
|
||||
createSqBounds();
|
||||
}
|
||||
else if (hadSq && !hasSq)
|
||||
destroySqBounds();
|
||||
|
||||
getScene().getSimulationController()->addPxgShape(this, getPxsShapeCore(), getActorNodeIndex(), getElementID());
|
||||
}
|
||||
|
||||
BodySim* ShapeSimBase::getBodySim() const
|
||||
{
|
||||
ActorSim& a = getActor();
|
||||
return a.isDynamicRigid() ? static_cast<BodySim*>(&a) : NULL;
|
||||
}
|
||||
|
||||
PxsRigidCore& ShapeSimBase::getPxsRigidCore() const
|
||||
{
|
||||
ActorSim& a = getActor();
|
||||
return a.isDynamicRigid() ? static_cast<BodySim&>(a).getBodyCore().getCore()
|
||||
: static_cast<StaticSim&>(a).getStaticCore().getCore();
|
||||
}
|
||||
|
||||
void ShapeSimBase::updateCached(PxU32 transformCacheFlags, PxBitMapPinned* shapeChangedMap)
|
||||
{
|
||||
PX_ALIGN(16, PxTransform absPose);
|
||||
getAbsPoseAligned(&absPose);
|
||||
|
||||
Scene& scene = getScene();
|
||||
const PxU32 index = getElementID();
|
||||
|
||||
scene.getLowLevelContext()->getTransformCache().setTransformCache(absPose, transformCacheFlags, index, index);
|
||||
scene.getBoundsArray().updateBounds(absPose, getCore().getGeometryUnion().getGeometry(), index, index);
|
||||
if (shapeChangedMap && isInBroadPhase())
|
||||
shapeChangedMap->growAndSet(index);
|
||||
}
|
||||
|
||||
void ShapeSimBase::updateCached(PxsTransformCache& transformCache, Bp::BoundsArray& boundsArray)
|
||||
{
|
||||
const PxU32 index = getElementID();
|
||||
|
||||
PxsCachedTransform& ct = transformCache.getTransformCache(index);
|
||||
PxPrefetchLine(&ct);
|
||||
|
||||
getAbsPoseAligned(&ct.transform);
|
||||
|
||||
ct.flags = 0;
|
||||
|
||||
PxBounds3& b = boundsArray.begin()[index];
|
||||
Gu::computeBounds(b, getCore().getGeometryUnion().getGeometry(), ct.transform, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void ShapeSimBase::updateBPGroup()
|
||||
{
|
||||
if (isInBroadPhase())
|
||||
{
|
||||
Sc::Scene& scene = getScene();
|
||||
scene.getAABBManager()->setBPGroup(getElementID(), getBPGroup(*this));
|
||||
|
||||
reinsertBroadPhase();
|
||||
// internalRemoveFromBroadPhase();
|
||||
// internalAddToBroadPhase();
|
||||
}
|
||||
}
|
||||
|
||||
void ShapeSimBase::markBoundsForUpdate()
|
||||
{
|
||||
Scene& scene = getScene();
|
||||
if (isInBroadPhase())
|
||||
scene.getDirtyShapeSimMap().growAndSet(getElementID());
|
||||
}
|
||||
|
||||
static PX_FORCE_INLINE void updateInteraction(Scene& scene, Interaction* i, const bool isDynamic, const bool isAsleep)
|
||||
{
|
||||
if (i->getType() == InteractionType::eOVERLAP)
|
||||
{
|
||||
ShapeInteraction* si = static_cast<ShapeInteraction*>(i);
|
||||
si->resetManagerCachedState();
|
||||
|
||||
if (isAsleep)
|
||||
si->onShapeChangeWhileSleeping(isDynamic);
|
||||
}
|
||||
else if (i->getType() == InteractionType::eTRIGGER)
|
||||
(static_cast<TriggerInteraction*>(i))->forceProcessingThisFrame(scene); // trigger pairs need to be checked next frame
|
||||
}
|
||||
|
||||
void ShapeSimBase::onVolumeOrTransformChange()
|
||||
{
|
||||
Scene& scene = getScene();
|
||||
BodySim* body = getBodySim();
|
||||
const bool isDynamic = (body != NULL);
|
||||
const bool isAsleep = body ? !body->isActive() : true;
|
||||
|
||||
ElementSim::ElementInteractionIterator iter = getElemInteractions();
|
||||
ElementSimInteraction* i = iter.getNext();
|
||||
while (i)
|
||||
{
|
||||
updateInteraction(scene, i, isDynamic, isAsleep);
|
||||
i = iter.getNext();
|
||||
}
|
||||
|
||||
markBoundsForUpdate();
|
||||
getScene().getSimulationController()->addPxgShape(this, getPxsShapeCore(), getActorNodeIndex(), getElementID());
|
||||
}
|
||||
|
||||
void notifyActorInteractionsOfTransformChange(ActorSim& actor)
|
||||
{
|
||||
bool isDynamic;
|
||||
bool isAsleep;
|
||||
if (actor.isDynamicRigid())
|
||||
{
|
||||
isDynamic = true;
|
||||
isAsleep = !static_cast<BodySim&>(actor).isActive();
|
||||
}
|
||||
else
|
||||
{
|
||||
isDynamic = false;
|
||||
isAsleep = true;
|
||||
}
|
||||
|
||||
Scene& scene = actor.getScene();
|
||||
|
||||
PxU32 nbInteractions = actor.getActorInteractionCount();
|
||||
Interaction** interactions = actor.getActorInteractions();
|
||||
while (nbInteractions--)
|
||||
updateInteraction(scene, *interactions++, isDynamic, isAsleep);
|
||||
}
|
||||
|
||||
void ShapeSimBase::createSqBounds()
|
||||
{
|
||||
if (mSqBoundsId != PX_INVALID_U32)
|
||||
return;
|
||||
|
||||
BodySim* bodySim = getBodySim();
|
||||
PX_ASSERT(bodySim);
|
||||
|
||||
if (bodySim->usingSqKinematicTarget() || bodySim->isFrozen() || !bodySim->isActive() || bodySim->readInternalFlag(BodySim::BF_IS_COMPOUND_RIGID))
|
||||
return;
|
||||
|
||||
if (getCore().getFlags() & PxShapeFlag::eSCENE_QUERY_SHAPE)
|
||||
getScene().getSqBoundsManager().addSyncShape(*this);
|
||||
}
|
||||
|
||||
void ShapeSimBase::destroySqBounds()
|
||||
{
|
||||
if (mSqBoundsId != PX_INVALID_U32)
|
||||
getScene().getSqBoundsManager().removeSyncShape(*this);
|
||||
}
|
||||
|
||||
126
engine/third_party/physx/source/simulationcontroller/src/ScShapeSimBase.h
vendored
Normal file
126
engine/third_party/physx/source/simulationcontroller/src/ScShapeSimBase.h
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
|
||||
#ifndef SC_SHAPESIM_BASE_H
|
||||
#define SC_SHAPESIM_BASE_H
|
||||
|
||||
#include "ScElementSim.h"
|
||||
#include "ScShapeCore.h"
|
||||
#include "ScRigidSim.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
PX_FORCE_INLINE PxU32 isBroadPhase(PxShapeFlags flags) { return PxU32(flags) & PxU32(PxShapeFlag::eTRIGGER_SHAPE | PxShapeFlag::eSIMULATION_SHAPE); }
|
||||
|
||||
class ShapeCore;
|
||||
|
||||
class ShapeSimBase : public ElementSim
|
||||
{
|
||||
PX_NOCOPY(ShapeSimBase)
|
||||
public:
|
||||
ShapeSimBase(ActorSim& owner, const ShapeCore* core) :
|
||||
ElementSim (owner),
|
||||
mSqBoundsId (PX_INVALID_U32),
|
||||
mPrunerIndex(PX_INVALID_U32)
|
||||
{ setCore(core); }
|
||||
~ShapeSimBase() { }
|
||||
|
||||
PX_FORCE_INLINE void setCore(const ShapeCore* core);
|
||||
PX_FORCE_INLINE const ShapeCore& getCore() const;
|
||||
PX_FORCE_INLINE bool isPxsCoreValid() const { return mShapeCore != NULL; }
|
||||
|
||||
PX_INLINE PxGeometryType::Enum getGeometryType() const { return getCore().getGeometryType(); }
|
||||
|
||||
// This is just for getting a reference for the user, so we cast away const-ness
|
||||
|
||||
PX_INLINE PxShape* getPxShape() const { return const_cast<PxShape*>(getCore().getPxShape()); }
|
||||
|
||||
PX_FORCE_INLINE PxReal getRestOffset() const { return getCore().getRestOffset(); }
|
||||
PX_FORCE_INLINE PxReal getTorsionalPatchRadius() const { return getCore().getTorsionalPatchRadius(); }
|
||||
PX_FORCE_INLINE PxReal getMinTorsionalPatchRadius() const { return getCore().getMinTorsionalPatchRadius(); }
|
||||
PX_FORCE_INLINE PxU32 getFlags() const { return getCore().getFlags(); }
|
||||
PX_FORCE_INLINE PxReal getContactOffset() const { return getCore().getContactOffset(); }
|
||||
|
||||
PX_FORCE_INLINE PxU32 getTransformCacheID() const { return getElementID(); }
|
||||
|
||||
PX_FORCE_INLINE PxU32 getSqBoundsId() const { return mSqBoundsId; }
|
||||
PX_FORCE_INLINE void setSqBoundsId(PxU32 id) { mSqBoundsId = id; }
|
||||
|
||||
PX_FORCE_INLINE PxU32 getSqPrunerIndex() const { return mPrunerIndex; }
|
||||
PX_FORCE_INLINE void setSqPrunerIndex(PxU32 index) { mPrunerIndex = index; }
|
||||
|
||||
PX_FORCE_INLINE PxsShapeCore* getPxsShapeCore() { return mShapeCore; }
|
||||
|
||||
void onFilterDataChange();
|
||||
void onRestOffsetChange();
|
||||
void onFlagChange(PxShapeFlags oldFlags);
|
||||
void onResetFiltering();
|
||||
void onVolumeOrTransformChange();
|
||||
void onContactOffsetChange();
|
||||
void markBoundsForUpdate();
|
||||
void reinsertBroadPhase();
|
||||
void removeFromBroadPhase(bool wakeOnLostTouch);
|
||||
void getAbsPoseAligned(PxTransform* PX_RESTRICT globalPose) const;
|
||||
PxNodeIndex getActorNodeIndex() const;
|
||||
|
||||
PX_FORCE_INLINE RigidSim& getRbSim() const { return static_cast<RigidSim&>(getActor()); }
|
||||
BodySim* getBodySim() const;
|
||||
|
||||
PxsRigidCore& getPxsRigidCore() const;
|
||||
|
||||
void createSqBounds();
|
||||
void destroySqBounds();
|
||||
|
||||
void updateCached(PxU32 transformCacheFlags, PxBitMapPinned* shapeChangedMap);
|
||||
void updateCached(PxsTransformCache& transformCache, Bp::BoundsArray& boundsArray);
|
||||
void updateBPGroup();
|
||||
protected:
|
||||
|
||||
PX_FORCE_INLINE void internalAddToBroadPhase();
|
||||
PX_FORCE_INLINE bool internalRemoveFromBroadPhase(bool wakeOnLostTouch = true);
|
||||
void initSubsystemsDependingOnElementID(PxU32 indexFrom);
|
||||
|
||||
PxsShapeCore* mShapeCore;
|
||||
PxU32 mSqBoundsId;
|
||||
PxU32 mPrunerIndex;
|
||||
};
|
||||
|
||||
PX_FORCE_INLINE void ShapeSimBase::setCore(const ShapeCore* core)
|
||||
{
|
||||
mShapeCore = core ? const_cast<PxsShapeCore*>(&core->getCore()) : NULL;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE const ShapeCore& ShapeSimBase::getCore() const
|
||||
{
|
||||
return Sc::ShapeCore::getCore(*mShapeCore);
|
||||
}
|
||||
|
||||
} // namespace Sc
|
||||
}
|
||||
|
||||
#endif
|
||||
213
engine/third_party/physx/source/simulationcontroller/src/ScSimStateData.h
vendored
Normal file
213
engine/third_party/physx/source/simulationcontroller/src/ScSimStateData.h
vendored
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-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_SIM_STATE_DATA_H
|
||||
#define SC_SIM_STATE_DATA_H
|
||||
|
||||
#include "foundation/PxMemory.h"
|
||||
#include "ScBodyCore.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
struct KinematicTransform
|
||||
{
|
||||
PxTransform targetPose; // The body will move to this pose over the superstep following this getting set.
|
||||
PxU8 targetValid; // User set a kinematic target.
|
||||
PxU8 pad[2];
|
||||
PxU8 type;
|
||||
};
|
||||
|
||||
struct Kinematic : public KinematicTransform
|
||||
{
|
||||
// The following members buffer the original body data to restore them when switching back to dynamic body
|
||||
// (for kinematics the corresponding LowLevel properties are set to predefined values)
|
||||
PxVec3 backupInverseInertia; // The inverse of the body space inertia tensor
|
||||
PxReal backupInvMass; // The inverse of the body mass
|
||||
PxReal backupLinearDamping; // The velocity is scaled by (1.0f - this * dt) inside integrateVelocity() every substep.
|
||||
PxReal backupAngularDamping;
|
||||
PxReal backupMaxAngVelSq; // The angular velocity's magnitude is clamped to this maximum value.
|
||||
PxReal backupMaxLinVelSq; // The angular velocity's magnitude is clamped to this maximum value
|
||||
};
|
||||
PX_COMPILE_TIME_ASSERT(0 == (sizeof(Kinematic) & 0x0f));
|
||||
|
||||
enum VelocityModFlags
|
||||
{
|
||||
VMF_GRAVITY_DIRTY = (1 << 0),
|
||||
VMF_ACC_DIRTY = (1 << 1),
|
||||
VMF_VEL_DIRTY = (1 << 2)
|
||||
};
|
||||
|
||||
// Important: Struct is reset in setForcesToDefaults.
|
||||
struct VelocityMod
|
||||
{
|
||||
PxVec3 linearPerSec; // A request to change the linear velocity by this much each second. The velocity is changed by this * dt inside integrateVelocity().
|
||||
PxU8 pad0[4];
|
||||
PxVec3 angularPerSec;
|
||||
PxU8 pad1[3];
|
||||
PxU8 type;
|
||||
PxVec3 linearPerStep; // A request to change the linear velocity by this much the next step. The velocity is changed inside updateForces().
|
||||
PxU32 pad2;
|
||||
PxVec3 angularPerStep;
|
||||
PxU32 pad3;
|
||||
|
||||
PX_FORCE_INLINE void clear() { linearPerSec = angularPerSec = linearPerStep = angularPerStep = PxVec3(0.0f); }
|
||||
|
||||
PX_FORCE_INLINE void clearPerStep() { linearPerStep = angularPerStep = PxVec3(0.0f); }
|
||||
|
||||
PX_FORCE_INLINE const PxVec3& getLinearVelModPerSec() const { return linearPerSec; }
|
||||
PX_FORCE_INLINE void accumulateLinearVelModPerSec(const PxVec3& v) { linearPerSec += v; }
|
||||
PX_FORCE_INLINE void setLinearVelModPerSec(const PxVec3& v) { linearPerSec = v; }
|
||||
PX_FORCE_INLINE void clearLinearVelModPerSec() { linearPerSec = PxVec3(0.0f); }
|
||||
|
||||
PX_FORCE_INLINE const PxVec3& getLinearVelModPerStep() const { return linearPerStep; }
|
||||
PX_FORCE_INLINE void accumulateLinearVelModPerStep(const PxVec3& v) { linearPerStep += v; }
|
||||
PX_FORCE_INLINE void clearLinearVelModPerStep() { linearPerStep = PxVec3(0.0f); }
|
||||
|
||||
PX_FORCE_INLINE const PxVec3& getAngularVelModPerSec() const { return angularPerSec; }
|
||||
PX_FORCE_INLINE void accumulateAngularVelModPerSec(const PxVec3& v) { angularPerSec += v; }
|
||||
PX_FORCE_INLINE void setAngularVelModPerSec(const PxVec3& v) { angularPerSec = v; }
|
||||
PX_FORCE_INLINE void clearAngularVelModPerSec() { angularPerSec = PxVec3(0.0f); }
|
||||
|
||||
PX_FORCE_INLINE const PxVec3& getAngularVelModPerStep() const { return angularPerStep; }
|
||||
PX_FORCE_INLINE void accumulateAngularVelModPerStep(const PxVec3& v) { angularPerStep += v; }
|
||||
PX_FORCE_INLINE void clearAngularVelModPerStep() { angularPerStep = PxVec3(0.0f); }
|
||||
};
|
||||
PX_COMPILE_TIME_ASSERT(sizeof(VelocityMod) == sizeof(Kinematic));
|
||||
|
||||
|
||||
// Structure to store data either for kinematics (target pose etc.) or for dynamics (vel and accel changes).
|
||||
// note: we do not delete this object for kinematics even if no target is set.
|
||||
struct SimStateData : public PxUserAllocated // TODO: may want to optimize the allocation of this further.
|
||||
{
|
||||
PxU8 data[sizeof(Kinematic)];
|
||||
|
||||
enum Enum
|
||||
{
|
||||
eVelMod=0,
|
||||
eKine
|
||||
};
|
||||
|
||||
SimStateData(){}
|
||||
SimStateData(const PxU8 type)
|
||||
{
|
||||
PxMemZero(data, sizeof(Kinematic));
|
||||
Kinematic* kine = reinterpret_cast<Kinematic*>(data);
|
||||
kine->type = type;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE PxU32 getType() const { const Kinematic* kine = reinterpret_cast<const Kinematic*>(data); return kine->type;}
|
||||
PX_FORCE_INLINE bool isKine() const {return eKine == getType();}
|
||||
PX_FORCE_INLINE bool isVelMod() const {return eVelMod == getType();}
|
||||
|
||||
PX_FORCE_INLINE Kinematic* getKinematicData() { Kinematic* kine = reinterpret_cast<Kinematic*>(data); PX_ASSERT(eKine == kine->type); return kine;}
|
||||
PX_FORCE_INLINE VelocityMod* getVelocityModData() { VelocityMod* velmod = reinterpret_cast<VelocityMod*>(data); PX_ASSERT(eVelMod == velmod->type); return velmod;}
|
||||
PX_FORCE_INLINE const Kinematic* getKinematicData() const { const Kinematic* kine = reinterpret_cast<const Kinematic*>(data); PX_ASSERT(eKine == kine->type); return kine;}
|
||||
PX_FORCE_INLINE const VelocityMod* getVelocityModData() const { const VelocityMod* velmod = reinterpret_cast<const VelocityMod*>(data); PX_ASSERT(eVelMod == velmod->type); return velmod;}
|
||||
};
|
||||
|
||||
PX_FORCE_INLINE void simStateBackupAndClearBodyProperties(SimStateData* simStateData, PxsBodyCore& core)
|
||||
{
|
||||
PX_ASSERT(simStateData && simStateData->isKine());
|
||||
Kinematic* kine = simStateData->getKinematicData();
|
||||
|
||||
kine->backupLinearDamping = core.linearDamping;
|
||||
kine->backupAngularDamping = core.angularDamping;
|
||||
kine->backupInverseInertia = core.inverseInertia;
|
||||
kine->backupInvMass = core.inverseMass;
|
||||
kine->backupMaxAngVelSq = core.maxAngularVelocitySq;
|
||||
kine->backupMaxLinVelSq = core.maxLinearVelocitySq;
|
||||
|
||||
core.inverseMass = 0.0f;
|
||||
core.inverseInertia = PxVec3(0.0f);
|
||||
core.linearDamping = 0.0f;
|
||||
core.angularDamping = 0.0f;
|
||||
core.maxAngularVelocitySq = PX_MAX_REAL;
|
||||
core.maxLinearVelocitySq = PX_MAX_REAL;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void simStateRestoreBodyProperties(const SimStateData* simStateData, PxsBodyCore& core)
|
||||
{
|
||||
PX_ASSERT(simStateData && simStateData->isKine());
|
||||
const Kinematic* kine = simStateData->getKinematicData();
|
||||
core.inverseMass = kine->backupInvMass;
|
||||
core.inverseInertia = kine->backupInverseInertia;
|
||||
core.linearDamping = kine->backupLinearDamping;
|
||||
core.angularDamping = kine->backupAngularDamping;
|
||||
core.maxAngularVelocitySq = kine->backupMaxAngVelSq;
|
||||
core.maxLinearVelocitySq = kine->backupMaxLinVelSq;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void simStateClearVelMod(SimStateData* simStateData)
|
||||
{
|
||||
if (simStateData && simStateData->isVelMod())
|
||||
{
|
||||
VelocityMod* velmod = simStateData->getVelocityModData();
|
||||
velmod->clear();
|
||||
}
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE bool simStateGetKinematicTarget(const SimStateData* simStateData, PxTransform& p)
|
||||
{
|
||||
if (simStateData && simStateData->isKine() && simStateData->getKinematicData()->targetValid)
|
||||
{
|
||||
p = simStateData->getKinematicData()->targetPose;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE bool simStateGetHasValidKinematicTarget(const SimStateData* simStateData)
|
||||
{
|
||||
PX_ASSERT(!simStateData || simStateData->isKine());
|
||||
return simStateData && simStateData->isKine() && simStateData->getKinematicData()->targetValid;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void simStateSetKinematicTarget(SimStateData* simStateData, const PxTransform& p)
|
||||
{
|
||||
PX_ASSERT(simStateData && simStateData->isKine());
|
||||
// setting the kinematic target is only allowed if the body is part of a scene, at which point the
|
||||
// mSimStateData buffer must exist
|
||||
Kinematic* kine = simStateData->getKinematicData();
|
||||
kine->targetPose = p;
|
||||
kine->targetValid = 1;
|
||||
}
|
||||
|
||||
PX_FORCE_INLINE void simStateInvalidateKinematicTarget(SimStateData* simStateData)
|
||||
{
|
||||
PX_ASSERT(simStateData && simStateData->isKine());
|
||||
simStateData->getKinematicData()->targetValid = 0;
|
||||
}
|
||||
} // namespace Sc
|
||||
|
||||
} // namespace physx
|
||||
|
||||
#endif
|
||||
|
||||
153
engine/third_party/physx/source/simulationcontroller/src/ScSimStats.cpp
vendored
Normal file
153
engine/third_party/physx/source/simulationcontroller/src/ScSimStats.cpp
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "foundation/PxMemory.h"
|
||||
#include "ScSimStats.h"
|
||||
#include "PxvSimStats.h"
|
||||
#include "PxsHeapMemoryAllocator.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::SimStats::SimStats()
|
||||
{
|
||||
numBroadPhaseAdds = numBroadPhaseRemoves = 0;
|
||||
|
||||
gpuMemSizeParticles = 0;
|
||||
gpuMemSizeDeformableSurfaces = 0;
|
||||
gpuMemSizeDeformableVolumes = 0;
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
void Sc::SimStats::clear()
|
||||
{
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
PxMemZero(const_cast<void*>(reinterpret_cast<volatile void*>(&numTriggerPairs)), sizeof(TriggerPairCounts));
|
||||
numBroadPhaseAddsPending = numBroadPhaseRemovesPending = 0;
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
}
|
||||
|
||||
void Sc::SimStats::simStart()
|
||||
{
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
// pending broadphase adds/removes are now the current ones
|
||||
numBroadPhaseAdds = numBroadPhaseAddsPending;
|
||||
numBroadPhaseRemoves = numBroadPhaseRemovesPending;
|
||||
clear();
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
#endif
|
||||
}
|
||||
|
||||
void Sc::SimStats::readOut(PxSimulationStatistics& s, const PxvSimStats& simStats) const
|
||||
{
|
||||
#if PX_ENABLE_SIM_STATS
|
||||
s = PxSimulationStatistics(); // clear stats
|
||||
|
||||
for(PxU32 i=0; i < PxGeometryType::eCONVEXMESH+1; i++)
|
||||
{
|
||||
for(PxU32 j=0; j < PxGeometryType::eGEOMETRY_COUNT; j++)
|
||||
{
|
||||
s.nbTriggerPairs[i][j] += PxU32(numTriggerPairs[i][j]);
|
||||
if (i != j)
|
||||
s.nbTriggerPairs[j][i] += PxU32(numTriggerPairs[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
s.nbBroadPhaseAdds = numBroadPhaseAdds;
|
||||
s.nbBroadPhaseRemoves = numBroadPhaseRemoves;
|
||||
|
||||
for(PxU32 i=0; i < PxGeometryType::eGEOMETRY_COUNT; i++)
|
||||
{
|
||||
s.nbDiscreteContactPairs[i][i] = simStats.mNbDiscreteContactPairs[i][i];
|
||||
s.nbModifiedContactPairs[i][i] = simStats.mNbModifiedContactPairs[i][i];
|
||||
s.nbCCDPairs[i][i] = simStats.mNbCCDPairs[i][i];
|
||||
|
||||
for(PxU32 j=i+1; j < PxGeometryType::eGEOMETRY_COUNT; j++)
|
||||
{
|
||||
PxU32 c = simStats.mNbDiscreteContactPairs[i][j];
|
||||
s.nbDiscreteContactPairs[i][j] = c;
|
||||
s.nbDiscreteContactPairs[j][i] = c;
|
||||
|
||||
c = simStats.mNbModifiedContactPairs[i][j];
|
||||
s.nbModifiedContactPairs[i][j] = c;
|
||||
s.nbModifiedContactPairs[j][i] = c;
|
||||
|
||||
c = simStats.mNbCCDPairs[i][j];
|
||||
s.nbCCDPairs[i][j] = c;
|
||||
s.nbCCDPairs[j][i] = c;
|
||||
}
|
||||
#if PX_DEBUG
|
||||
for(PxU32 j=0; j < i; j++)
|
||||
{
|
||||
// PxvSimStats should only use one half of the matrix
|
||||
PX_ASSERT(simStats.mNbDiscreteContactPairs[i][j] == 0);
|
||||
PX_ASSERT(simStats.mNbModifiedContactPairs[i][j] == 0);
|
||||
PX_ASSERT(simStats.mNbCCDPairs[i][j] == 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
s.nbDiscreteContactPairsTotal = simStats.mNbDiscreteContactPairsTotal;
|
||||
s.nbDiscreteContactPairsWithCacheHits = simStats.mNbDiscreteContactPairsWithCacheHits;
|
||||
s.nbDiscreteContactPairsWithContacts = simStats.mNbDiscreteContactPairsWithContacts;
|
||||
s.nbActiveConstraints = simStats.mNbActiveConstraints;
|
||||
s.nbActiveDynamicBodies = simStats.mNbActiveDynamicBodies;
|
||||
s.nbActiveKinematicBodies = simStats.mNbActiveKinematicBodies;
|
||||
|
||||
s.nbAxisSolverConstraints = simStats.mNbAxisSolverConstraints;
|
||||
|
||||
s.peakConstraintMemory = simStats.mPeakConstraintBlockAllocations * 16 * 1024;
|
||||
s.compressedContactSize = simStats.mTotalCompressedContactSize;
|
||||
s.requiredContactConstraintMemory = simStats.mTotalConstraintSize;
|
||||
s.nbNewPairs = simStats.mNbNewPairs;
|
||||
s.nbLostPairs = simStats.mNbLostPairs;
|
||||
s.nbNewTouches = simStats.mNbNewTouches;
|
||||
s.nbLostTouches = simStats.mNbLostTouches;
|
||||
s.nbPartitions = simStats.mNbPartitions;
|
||||
|
||||
s.gpuDynamicsMemoryConfigStatistics.tempBufferCapacity = simStats.mGpuDynamicsTempBufferCapacity;
|
||||
s.gpuDynamicsMemoryConfigStatistics.rigidContactCount = simStats.mGpuDynamicsRigidContactCount;
|
||||
s.gpuDynamicsMemoryConfigStatistics.rigidPatchCount = simStats.mGpuDynamicsRigidPatchCount;
|
||||
s.gpuDynamicsMemoryConfigStatistics.foundLostPairs = simStats.mGpuDynamicsFoundLostPairs;
|
||||
s.gpuDynamicsMemoryConfigStatistics.foundLostAggregatePairs = simStats.mGpuDynamicsFoundLostAggregatePairs;
|
||||
s.gpuDynamicsMemoryConfigStatistics.totalAggregatePairs = simStats.mGpuDynamicsTotalAggregatePairs;
|
||||
s.gpuDynamicsMemoryConfigStatistics.deformableSurfaceContacts = simStats.mGpuDynamicsDeformableSurfaceContacts;
|
||||
s.gpuDynamicsMemoryConfigStatistics.deformableVolumeContacts = simStats.mGpuDynamicsDeformableVolumeContacts;
|
||||
s.gpuDynamicsMemoryConfigStatistics.softbodyContacts = simStats.mGpuDynamicsDeformableVolumeContacts; //deprecated
|
||||
s.gpuDynamicsMemoryConfigStatistics.particleContacts = simStats.mGpuDynamicsParticleContacts;
|
||||
s.gpuDynamicsMemoryConfigStatistics.collisionStackSize = simStats.mGpuDynamicsCollisionStackSize;
|
||||
|
||||
#else
|
||||
PX_CATCH_UNDEFINED_ENABLE_SIM_STATS
|
||||
PX_UNUSED(s);
|
||||
PX_UNUSED(simStats);
|
||||
#endif
|
||||
}
|
||||
90
engine/third_party/physx/source/simulationcontroller/src/ScSimStats.h
vendored
Normal file
90
engine/third_party/physx/source/simulationcontroller/src/ScSimStats.h
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_SIM_STATS_H
|
||||
#define SC_SIM_STATS_H
|
||||
|
||||
#include "geometry/PxGeometry.h"
|
||||
#include "PxSimulationStatistics.h"
|
||||
#include "foundation/PxAtomic.h"
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
|
||||
struct PxvSimStats;
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
|
||||
/*
|
||||
Description: contains statistics for the scene.
|
||||
*/
|
||||
class SimStats : public PxUserAllocated
|
||||
{
|
||||
public:
|
||||
SimStats();
|
||||
|
||||
void clear(); //set counters to zero
|
||||
void simStart();
|
||||
void readOut(PxSimulationStatistics& dest, const PxvSimStats& simStats) const;
|
||||
|
||||
PX_INLINE void incBroadphaseAdds()
|
||||
{
|
||||
numBroadPhaseAddsPending++;
|
||||
}
|
||||
|
||||
PX_INLINE void incBroadphaseRemoves()
|
||||
{
|
||||
numBroadPhaseRemovesPending++;
|
||||
}
|
||||
|
||||
private:
|
||||
// Broadphase adds/removes for the current simulation step
|
||||
PxU32 numBroadPhaseAdds;
|
||||
PxU32 numBroadPhaseRemoves;
|
||||
|
||||
// Broadphase adds/removes for the next simulation step
|
||||
PxU32 numBroadPhaseAddsPending;
|
||||
PxU32 numBroadPhaseRemovesPending;
|
||||
|
||||
public:
|
||||
typedef PxI32 TriggerPairCountsNonVolatile[PxGeometryType::eCONVEXMESH+1][PxGeometryType::eGEOMETRY_COUNT];
|
||||
typedef volatile TriggerPairCountsNonVolatile TriggerPairCounts;
|
||||
TriggerPairCounts numTriggerPairs;
|
||||
|
||||
PxU64 gpuMemSizeParticles;
|
||||
PxU64 gpuMemSizeDeformableSurfaces;
|
||||
PxU64 gpuMemSizeDeformableVolumes;
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
127
engine/third_party/physx/source/simulationcontroller/src/ScSimulationController.cpp
vendored
Normal file
127
engine/third_party/physx/source/simulationcontroller/src/ScSimulationController.cpp
vendored
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-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScSimulationController.h"
|
||||
#include "foundation/PxAllocator.h"
|
||||
#include "CmTask.h"
|
||||
#include "CmFlushPool.h"
|
||||
#include "PxNodeIndex.h"
|
||||
#include "ScArticulationSim.h"
|
||||
#include "PxsContext.h"
|
||||
#include "foundation/PxAllocator.h"
|
||||
#include "BpAABBManager.h"
|
||||
#include "DyVArticulation.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace IG;
|
||||
using namespace Sc;
|
||||
|
||||
void SimulationController::updateScBodyAndShapeSim(PxsTransformCache& /*cache*/, Bp::BoundsArray& /*boundArray*/, PxBaseTask* continuation)
|
||||
{
|
||||
mCallback->updateScBodyAndShapeSim(continuation);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class UpdateArticulationAfterIntegrationTask : public Cm::Task
|
||||
{
|
||||
IslandSim& mIslandSim;
|
||||
const PxNodeIndex* const PX_RESTRICT mNodeIndices;
|
||||
const PxU32 mNbArticulations;
|
||||
const PxReal mDt;
|
||||
|
||||
PX_NOCOPY(UpdateArticulationAfterIntegrationTask)
|
||||
public:
|
||||
static const PxU32 NbArticulationsPerTask = 64;
|
||||
|
||||
UpdateArticulationAfterIntegrationTask(PxU64 contextId, PxU32 nbArticulations, PxReal dt, const PxNodeIndex* nodeIndices, IslandSim& islandSim) :
|
||||
Cm::Task(contextId),
|
||||
mIslandSim(islandSim),
|
||||
mNodeIndices(nodeIndices),
|
||||
mNbArticulations(nbArticulations),
|
||||
mDt(dt)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void runInternal()
|
||||
{
|
||||
for (PxU32 i = 0; i < mNbArticulations; ++i)
|
||||
{
|
||||
PxNodeIndex nodeIndex = mNodeIndices[i];
|
||||
ArticulationSim* articSim = getArticulationSim(mIslandSim, nodeIndex);
|
||||
articSim->sleepCheck(mDt);
|
||||
articSim->updateCached(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
virtual const char* getName() const { return "UpdateArticulationAfterIntegrationTask"; }
|
||||
};
|
||||
}
|
||||
|
||||
//KS - TODO - parallelize this bit!!!!!
|
||||
void SimulationController::updateArticulationAfterIntegration(
|
||||
PxsContext* llContext,
|
||||
Bp::AABBManagerBase* aabbManager,
|
||||
PxArray<BodySim*>& ccdBodies,
|
||||
PxBaseTask* continuation,
|
||||
IslandSim& islandSim,
|
||||
float dt
|
||||
)
|
||||
{
|
||||
const PxU32 nbActiveArticulations = islandSim.getNbActiveNodes(Node::eARTICULATION_TYPE);
|
||||
|
||||
Cm::FlushPool& flushPool = llContext->getTaskPool();
|
||||
|
||||
const PxNodeIndex* activeArticulations = islandSim.getActiveNodes(Node::eARTICULATION_TYPE);
|
||||
|
||||
for (PxU32 i = 0; i < nbActiveArticulations; i += UpdateArticulationAfterIntegrationTask::NbArticulationsPerTask)
|
||||
{
|
||||
UpdateArticulationAfterIntegrationTask* task =
|
||||
PX_PLACEMENT_NEW(flushPool.allocate(sizeof(UpdateArticulationAfterIntegrationTask)), UpdateArticulationAfterIntegrationTask)(islandSim.getContextId(), PxMin(UpdateArticulationAfterIntegrationTask::NbArticulationsPerTask, PxU32(nbActiveArticulations - i)), dt,
|
||||
activeArticulations + i, islandSim);
|
||||
|
||||
startTask(task, continuation);
|
||||
}
|
||||
|
||||
llContext->getLock().lock();
|
||||
|
||||
//const NodeIndex* activeArticulations = islandSim.getActiveNodes(Node::eARTICULATION_TYPE);
|
||||
|
||||
PxBitMapPinned& changedAABBMgrActorHandles = aabbManager->getChangedAABBMgActorHandleMap();
|
||||
|
||||
for (PxU32 i = 0; i < nbActiveArticulations; i++)
|
||||
{
|
||||
ArticulationSim* articSim = getArticulationSim(islandSim, activeArticulations[i]);
|
||||
|
||||
//KS - check links for CCD flags and add to mCcdBodies list if required....
|
||||
articSim->updateCCDLinks(ccdBodies);
|
||||
|
||||
articSim->markShapesUpdated(&changedAABBMgrActorHandles);
|
||||
}
|
||||
llContext->getLock().unlock();
|
||||
}
|
||||
54
engine/third_party/physx/source/simulationcontroller/src/ScSimulationController.h
vendored
Normal file
54
engine/third_party/physx/source/simulationcontroller/src/ScSimulationController.h
vendored
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-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_SIMULATION_CONTROLLER_H
|
||||
#define SC_SIMULATION_CONTROLLER_H
|
||||
|
||||
#include "PxsSimulationController.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class SimulationController : public PxsSimulationController
|
||||
{
|
||||
PX_NOCOPY(SimulationController)
|
||||
public:
|
||||
SimulationController(PxsSimulationControllerCallback* callback) : PxsSimulationController(callback, PxIntFalse) {}
|
||||
virtual ~SimulationController() {}
|
||||
|
||||
virtual void updateScBodyAndShapeSim(PxsTransformCache& cache, Bp::BoundsArray& boundArray, PxBaseTask* continuation) PX_OVERRIDE;
|
||||
|
||||
virtual void updateArticulationAfterIntegration(PxsContext* llContext, Bp::AABBManagerBase* aabbManager,
|
||||
PxArray<Sc::BodySim*>& ccdBodies, PxBaseTask* continuation, IG::IslandSim& islandSim, float dt) PX_OVERRIDE;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
304
engine/third_party/physx/source/simulationcontroller/src/ScSleep.cpp
vendored
Normal file
304
engine/third_party/physx/source/simulationcontroller/src/ScSleep.cpp
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "ScScene.h"
|
||||
#include "ScArticulationSim.h"
|
||||
#include "ScBodySim.h"
|
||||
#include "ScActorSim.h"
|
||||
#include "DyIslandManager.h"
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
#include "ScDeformableSurfaceSim.h"
|
||||
#include "ScDeformableVolumeSim.h"
|
||||
#include "ScParticleSystemSim.h"
|
||||
#endif
|
||||
|
||||
#include "common/PxProfileZone.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Cm;
|
||||
using namespace Dy;
|
||||
using namespace Sc;
|
||||
|
||||
// PT: "setActive()" moved from ActorSim to BodySim because GPU classes silently re-implement this in a very different way (see below),
|
||||
// i.e. it defeats the purpose of the virtual activate()/deactivate() functions.
|
||||
void Sc::BodySim::setActive(bool active, bool asPartOfCreation)
|
||||
{
|
||||
PX_ASSERT(!active || isDynamicRigid()); // Currently there should be no need to activate an actor that does not take part in island generation
|
||||
|
||||
if(asPartOfCreation || isActive() != active)
|
||||
{
|
||||
PX_ASSERT(!asPartOfCreation || (getActorInteractionCount() == 0)); // On creation or destruction there should be no interactions
|
||||
|
||||
if(active)
|
||||
{
|
||||
if(!asPartOfCreation)
|
||||
getScene().addToActiveList(*this); // Inactive => Active
|
||||
|
||||
activate();
|
||||
|
||||
PX_ASSERT(asPartOfCreation || isActive());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!asPartOfCreation)
|
||||
getScene().removeFromActiveList(*this); // Active => Inactive
|
||||
|
||||
deactivate();
|
||||
|
||||
PX_ASSERT(asPartOfCreation || (!isActive()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Sc::ArticulationSim::setActive(bool b, bool asPartOfCreation)
|
||||
{
|
||||
const PxReal wakeCounter = mCore.getWakeCounter();
|
||||
const PxU32 nbBodies = mBodies.size();
|
||||
for(PxU32 i=0;i<nbBodies;i++)
|
||||
{
|
||||
if(i+1 < nbBodies)
|
||||
{
|
||||
PxPrefetchLine(mBodies[i+1],0);
|
||||
PxPrefetchLine(mBodies[i+1],128);
|
||||
}
|
||||
//KS - force in the wake counter from the articulation to its links. This is required because
|
||||
//GPU articulation simulation does not DMA back wake counters for each link - it just brings back a global wake counter
|
||||
mBodies[i]->getBodyCore().setWakeCounterFromSim(wakeCounter);
|
||||
mBodies[i]->setActive(b, asPartOfCreation);
|
||||
}
|
||||
}
|
||||
|
||||
// PT: moving all the sleeping-related implementations to the same file clearly exposes the inconsistencies between them
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
void Sc::ParticleSystemSim::setActive(bool /*active*/, bool /*asPartOfCreation*/)
|
||||
{
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceSim::activate()
|
||||
{
|
||||
mScene.getSimulationController()->activateCloth(mLLDeformableSurface);
|
||||
|
||||
activateInteractions(*this);
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceSim::deactivate()
|
||||
{
|
||||
mScene.getSimulationController()->deactivateCloth(mLLDeformableSurface);
|
||||
|
||||
deactivateInteractions(*this);
|
||||
}
|
||||
|
||||
void Sc::DeformableSurfaceSim::setActive(bool active, bool /*asPartOfCreation*/)
|
||||
{
|
||||
if(active)
|
||||
activate();
|
||||
else
|
||||
deactivate();
|
||||
}
|
||||
|
||||
void Sc::DeformableVolumeSim::setActive(bool active, bool /*asPartOfCreation*/)
|
||||
{
|
||||
if(active)
|
||||
getScene().getSimulationController()->activateSoftbody(mLLDeformableVolume);
|
||||
else
|
||||
getScene().getSimulationController()->deactivateSoftbody(mLLDeformableVolume);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
struct GetRigidSim { static PX_FORCE_INLINE BodySim* getSim(const IG::Node& node) { return reinterpret_cast<BodySim*>(reinterpret_cast<PxU8*>(node.mObject) - BodySim::getRigidBodyOffset()); } };
|
||||
struct GetArticSim { static PX_FORCE_INLINE ArticulationSim* getSim(const IG::Node& node) { return reinterpret_cast<ArticulationSim*>(getObjectFromIG<FeatherstoneArticulation>(node)->getUserData()); } };
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
struct GetDeformableSurfaceSim { static PX_FORCE_INLINE DeformableSurfaceSim* getSim(const IG::Node& node) { return getObjectFromIG<DeformableSurface>(node)->getSim(); } };
|
||||
struct GetDeformableVolumeSim { static PX_FORCE_INLINE DeformableVolumeSim* getSim(const IG::Node& node) { return getObjectFromIG<DeformableVolume>(node)->getSim(); } };
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class SimT, class SimAccessT, const bool active>
|
||||
static void setActive(PxU32& nbModified, const IG::IslandSim& islandSim, IG::Node::NodeType type)
|
||||
{
|
||||
PxU32 nbToProcess = active ? islandSim.getNbNodesToActivate(type) : islandSim.getNbNodesToDeactivate(type);
|
||||
const PxNodeIndex* indices = active ? islandSim.getNodesToActivate(type) : islandSim.getNodesToDeactivate(type);
|
||||
|
||||
while(nbToProcess--)
|
||||
{
|
||||
const IG::Node& node = islandSim.getNode(*indices++);
|
||||
PX_ASSERT(node.mType == type);
|
||||
if((!!node.isActive())==active)
|
||||
{
|
||||
SimT* sim = SimAccessT::getSim(node);
|
||||
if(sim)
|
||||
{
|
||||
sim->setActive(active);
|
||||
nbModified++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BATCHED
|
||||
namespace
|
||||
{
|
||||
struct SetActiveRigidSim
|
||||
{
|
||||
template<const bool active>
|
||||
static void setActive(Scene& /*scene*/, PxU32 nbObjects, BodySim** objects)
|
||||
{
|
||||
if(1)
|
||||
{
|
||||
while(nbObjects--)
|
||||
{
|
||||
(*objects)->setActive(active);
|
||||
objects++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(active)
|
||||
{
|
||||
// scene.addToActiveList(*this);
|
||||
// activate();
|
||||
// PX_ASSERT(isActive());
|
||||
}
|
||||
else
|
||||
{
|
||||
// scene.removeFromActiveList(*this);
|
||||
// deactivate();
|
||||
// PX_ASSERT(!isActive());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<class SimT, class SimAccessT, class SetActiveBatchedT, const bool active>
|
||||
static void setActiveBatched(Scene& scene, PxU32& nbModified, const IG::IslandSim& islandSim, IG::Node::NodeType type)
|
||||
{
|
||||
PxU32 nbToProcess = active ? islandSim.getNbNodesToActivate(type) : islandSim.getNbNodesToDeactivate(type);
|
||||
const PxNodeIndex* indices = active ? islandSim.getNodesToActivate(type) : islandSim.getNodesToDeactivate(type);
|
||||
|
||||
PX_ALLOCA(batch, SimT*, nbToProcess);
|
||||
|
||||
PxU32 nb = 0;
|
||||
while(nbToProcess--)
|
||||
{
|
||||
const IG::Node& node = islandSim.getNode(*indices++);
|
||||
PX_ASSERT(node.mType == type);
|
||||
if(node.isActive()==active)
|
||||
{
|
||||
SimT* sim = SimAccessT::getSim(node);
|
||||
if(sim && sim->isActive()!=active)
|
||||
batch.mPointer[nb++] = sim;
|
||||
}
|
||||
}
|
||||
|
||||
SetActiveBatchedT::setActive<active>(scene, nb, batch.mPointer);
|
||||
|
||||
nbModified = nb;
|
||||
}
|
||||
|
||||
/*
|
||||
Batched version would be just:
|
||||
a) addToActiveList(batched objects)
|
||||
b) activate(batched objects)
|
||||
|
||||
void Sc::ActorSim::setActive(bool active)
|
||||
{
|
||||
PX_ASSERT(!active || isDynamicRigid()); // Currently there should be no need to activate an actor that does not take part in island generation
|
||||
|
||||
if(isActive() != active)
|
||||
{
|
||||
if(active)
|
||||
{
|
||||
// Inactive => Active
|
||||
getScene().addToActiveList(*this);
|
||||
|
||||
activate();
|
||||
|
||||
PX_ASSERT(isActive());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Active => Inactive
|
||||
getScene().removeFromActiveList(*this);
|
||||
|
||||
deactivate();
|
||||
|
||||
PX_ASSERT(!isActive());
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
void Sc::Scene::putObjectsToSleep()
|
||||
{
|
||||
PX_PROFILE_ZONE("Sc::Scene::putObjectsToSleep", mContextId);
|
||||
|
||||
//Set to sleep all bodies that were in awake islands that have just been put to sleep.
|
||||
|
||||
const IG::IslandSim& islandSim = mSimpleIslandManager->getAccurateIslandSim();
|
||||
|
||||
PxU32 nbBodiesDeactivated = 0;
|
||||
//setActiveBatched<BodySim, GetRigidSim, SetActiveRigidSim, false>(*this, nbBodiesDeactivated, islandSim, IG::Node::eRIGID_BODY_TYPE);
|
||||
setActive<BodySim, GetRigidSim, false>(nbBodiesDeactivated, islandSim, IG::Node::eRIGID_BODY_TYPE);
|
||||
setActive<ArticulationSim, GetArticSim, false>(nbBodiesDeactivated, islandSim, IG::Node::eARTICULATION_TYPE);
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
setActive<DeformableSurfaceSim, GetDeformableSurfaceSim, false>(nbBodiesDeactivated, islandSim, IG::Node::eDEFORMABLE_SURFACE_TYPE);
|
||||
setActive<DeformableVolumeSim, GetDeformableVolumeSim, false>(nbBodiesDeactivated, islandSim, IG::Node::eDEFORMABLE_VOLUME_TYPE);
|
||||
#endif
|
||||
|
||||
if(nbBodiesDeactivated)
|
||||
mDynamicsContext->setStateDirty(true);
|
||||
}
|
||||
|
||||
void Sc::Scene::wakeObjectsUp()
|
||||
{
|
||||
PX_PROFILE_ZONE("Sc::Scene::wakeObjectsUp", mContextId);
|
||||
|
||||
//Wake up all bodies that were in sleeping islands that have just been hit by a moving object.
|
||||
|
||||
const IG::IslandSim& islandSim = mSimpleIslandManager->getAccurateIslandSim();
|
||||
|
||||
PxU32 nbBodiesWoken = 0;
|
||||
setActive<BodySim, GetRigidSim, true>(nbBodiesWoken, islandSim, IG::Node::eRIGID_BODY_TYPE);
|
||||
setActive<ArticulationSim, GetArticSim, true>(nbBodiesWoken, islandSim, IG::Node::eARTICULATION_TYPE);
|
||||
|
||||
#if PX_SUPPORT_GPU_PHYSX
|
||||
setActive<DeformableSurfaceSim, GetDeformableSurfaceSim, true>(nbBodiesWoken, islandSim, IG::Node::eDEFORMABLE_SURFACE_TYPE);
|
||||
setActive<DeformableVolumeSim, GetDeformableVolumeSim, true>(nbBodiesWoken, islandSim, IG::Node::eDEFORMABLE_VOLUME_TYPE);
|
||||
#endif
|
||||
|
||||
if(nbBodiesWoken)
|
||||
mDynamicsContext->setStateDirty(true);
|
||||
}
|
||||
|
||||
329
engine/third_party/physx/source/simulationcontroller/src/ScSqBoundsManager.cpp
vendored
Normal file
329
engine/third_party/physx/source/simulationcontroller/src/ScSqBoundsManager.cpp
vendored
Normal file
@@ -0,0 +1,329 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#include "GuPrunerTypedef.h"
|
||||
#include "ScSqBoundsManager.h"
|
||||
#include "ScBodySim.h"
|
||||
#include "ScShapeSim.h"
|
||||
#include "ScSqBoundsSync.h"
|
||||
#include "common/PxProfileZone.h"
|
||||
|
||||
using namespace physx;
|
||||
using namespace Sc;
|
||||
|
||||
#define INVALID_REF ScPrunerHandle(Gu::INVALID_PRUNERHANDLE)
|
||||
|
||||
SqBoundsManager0::SqBoundsManager0() :
|
||||
mShapes ("SqBoundsManager::mShapes"),
|
||||
mRefs ("SqBoundsManager::mRefs"),
|
||||
mBoundsIndices ("SqBoundsManager::mBoundsIndices"),
|
||||
mRefless ("SqBoundsManager::mRefless")
|
||||
{
|
||||
}
|
||||
|
||||
void SqBoundsManager0::addSyncShape(ShapeSimBase& shape)
|
||||
{
|
||||
PX_ASSERT(shape.getFlags() & PxShapeFlag::eSCENE_QUERY_SHAPE);
|
||||
PX_ASSERT(!shape.getBodySim()->usingSqKinematicTarget());
|
||||
PX_ASSERT(!shape.getBodySim()->isFrozen());
|
||||
|
||||
const PxU32 id = mShapes.size();
|
||||
PX_ASSERT(id == mRefs.size());
|
||||
PX_ASSERT(id == mBoundsIndices.size());
|
||||
|
||||
shape.setSqBoundsId(id);
|
||||
|
||||
// PT: mShapes / mRefs / mBoundsIndices are "parallel arrays". These arrays are persistent.
|
||||
// mRefless is temporary/transient data to help populate mRefs each frame.
|
||||
// mRefs / mBoundsIndices will be ultimately passed to updateObjects, whose API dictates the layout here.
|
||||
// mShapes is not actually used for the sync, it's only here to be able to call setSqBoundsId in removeShape.
|
||||
|
||||
mShapes.pushBack(static_cast<Sc::ShapeSim*>(&shape));
|
||||
mRefs.pushBack(INVALID_REF);
|
||||
mBoundsIndices.pushBack(shape.getElementID());
|
||||
mRefless.pushBack(static_cast<Sc::ShapeSim*>(&shape));
|
||||
}
|
||||
|
||||
void SqBoundsManager0::removeSyncShape(ShapeSimBase& shape)
|
||||
{
|
||||
const PxU32 id = shape.getSqBoundsId();
|
||||
PX_ASSERT(id!=PX_INVALID_U32);
|
||||
|
||||
shape.setSqBoundsId(PX_INVALID_U32);
|
||||
mShapes[id] = mShapes.back();
|
||||
mBoundsIndices[id] = mBoundsIndices.back();
|
||||
mRefs[id] = mRefs.back();
|
||||
|
||||
if(id+1 != mShapes.size())
|
||||
mShapes[id]->setSqBoundsId(id);
|
||||
|
||||
mShapes.popBack();
|
||||
mRefs.popBack();
|
||||
mBoundsIndices.popBack();
|
||||
}
|
||||
|
||||
void SqBoundsManager0::syncBounds(SqBoundsSync& sync, SqRefFinder& finder, const PxBounds3* bounds, const PxTransform32* transforms, PxU64 contextID, const PxBitMap& ignoredIndices)
|
||||
{
|
||||
PX_PROFILE_ZONE("Sim.sceneQuerySyncBounds", contextID);
|
||||
PX_UNUSED(contextID);
|
||||
|
||||
#if PX_DEBUG
|
||||
for(PxU32 i=0;i<mShapes.size();i++)
|
||||
{
|
||||
const ShapeSimBase& shape = *mShapes[i];
|
||||
PX_UNUSED(shape);
|
||||
PX_ASSERT(shape.getFlags() & PxShapeFlag::eSCENE_QUERY_SHAPE);
|
||||
PX_ASSERT(!shape.getBodySim()->usingSqKinematicTarget());
|
||||
PX_ASSERT(!shape.getBodySim()->isFrozen());
|
||||
}
|
||||
#endif
|
||||
|
||||
ShapeSimBase*const * shapes = mRefless.begin();
|
||||
for(PxU32 i=0, size = mRefless.size();i<size;i++)
|
||||
{
|
||||
const PxU32 id = shapes[i]->getSqBoundsId();
|
||||
// PT:
|
||||
//
|
||||
// If id == PX_INVALID_U32, the shape has been removed and not re-added. Nothing to do in this case, we just ignore it.
|
||||
// This case didn't previously exist since mRefless only contained valid (added) shapes. But now we left removed shapes in the
|
||||
// structure, and these have an id == PX_INVALID_U32.
|
||||
//
|
||||
// Now if the id is valid but mRefs[id] == PX_INVALID_U32, this is a regular shape that has been added and not processed yet.
|
||||
// So we process it.
|
||||
//
|
||||
// Finally, if both id and mRefs[id] are not PX_INVALID_U32, this is a shape that has been added, removed, and re-added. The
|
||||
// array contains the same shape twice and we only need to process it once.
|
||||
if(id!=PX_INVALID_U32)
|
||||
{
|
||||
if(mRefs[id] == INVALID_REF)
|
||||
{
|
||||
PxU32 prunerIndex = 0xffffffff;
|
||||
mRefs[id] = finder.find(static_cast<PxRigidBody*>(shapes[i]->getBodySim()->getPxActor()), shapes[i]->getPxShape(), prunerIndex);
|
||||
PX_ASSERT(prunerIndex==1);
|
||||
}
|
||||
}
|
||||
}
|
||||
mRefless.clear();
|
||||
|
||||
sync.sync(1, mRefs.begin(), mBoundsIndices.begin(), bounds, transforms, mShapes.size(), ignoredIndices);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// PT: we need to change the code so that the shape is added to the proper array during syncBounds, not during addSyncShape,
|
||||
// because the pruner index is not known in addSyncShape. We could perhaps call the ref-finder directly in addSyncShape, but
|
||||
// it would impose an order on the calls (the shape would need to be added to the pruners before addSyncShape is called. There's
|
||||
// no such requirement with the initial code).
|
||||
//
|
||||
// Instead we do this:
|
||||
// - in addSyncShape we just add the shape to a "waiting room", that's all.
|
||||
// - adding the shape to the proper array is delayed until syncBounds. That way the prunerIndex will be available. Also we could
|
||||
// then take advantage of batching, since all shapes are processed/added at the same time.
|
||||
// - the only catch is that we need to ensure the previous edge-cases are still properly handled, i.e. when a shape is added then
|
||||
// removed before sync is called, etc.
|
||||
//
|
||||
|
||||
SqBoundsManagerEx::SqBoundsManagerEx() :
|
||||
mWaitingRoom ("SqBoundsManagerEx::mWaitingRoom"),
|
||||
mPrunerSyncData (NULL),
|
||||
mPrunerSyncDataSize (0)
|
||||
{
|
||||
}
|
||||
|
||||
SqBoundsManagerEx::~SqBoundsManagerEx()
|
||||
{
|
||||
const PxU32 nbToGo = mPrunerSyncDataSize;
|
||||
for(PxU32 i=0;i<nbToGo;i++)
|
||||
{
|
||||
PrunerSyncData* psd = mPrunerSyncData[i];
|
||||
PX_DELETE(psd);
|
||||
}
|
||||
PX_FREE(mPrunerSyncData);
|
||||
}
|
||||
|
||||
void SqBoundsManagerEx::resize(PxU32 index)
|
||||
{
|
||||
PxU32 size = mPrunerSyncDataSize ? mPrunerSyncDataSize*2 : 64;
|
||||
const PxU32 minSize = index+1;
|
||||
if(minSize>size)
|
||||
size = minSize*2;
|
||||
|
||||
PrunerSyncData** items = PX_ALLOCATE(PrunerSyncData*, size, "PrunerSyncData");
|
||||
if(mPrunerSyncData)
|
||||
PxMemCopy(items, mPrunerSyncData, mPrunerSyncDataSize*sizeof(PrunerSyncData*));
|
||||
PxMemZero(items+mPrunerSyncDataSize, (size-mPrunerSyncDataSize)*sizeof(PrunerSyncData*));
|
||||
PX_FREE(mPrunerSyncData);
|
||||
mPrunerSyncData = items;
|
||||
mPrunerSyncDataSize = size;
|
||||
}
|
||||
|
||||
void SqBoundsManagerEx::addSyncShape(ShapeSimBase& shape)
|
||||
{
|
||||
PX_ASSERT(shape.getFlags() & PxShapeFlag::eSCENE_QUERY_SHAPE);
|
||||
PX_ASSERT(!shape.getBodySim()->usingSqKinematicTarget());
|
||||
PX_ASSERT(!shape.getBodySim()->isFrozen());
|
||||
|
||||
PX_ASSERT(shape.getSqBoundsId()==PX_INVALID_U32);
|
||||
PX_ASSERT(shape.getSqPrunerIndex()==PX_INVALID_U32);
|
||||
|
||||
const PxU32 id = mWaitingRoom.size();
|
||||
mWaitingRoom.pushBack(&shape);
|
||||
shape.setSqBoundsId(id);
|
||||
shape.setSqPrunerIndex(PX_INVALID_U32);
|
||||
}
|
||||
|
||||
void SqBoundsManagerEx::removeSyncShape(ShapeSimBase& shape)
|
||||
{
|
||||
const PxU32 id = shape.getSqBoundsId();
|
||||
const PxU32 prunerIndex = shape.getSqPrunerIndex();
|
||||
PX_ASSERT(id!=PX_INVALID_U32);
|
||||
shape.setSqBoundsId(PX_INVALID_U32);
|
||||
shape.setSqPrunerIndex(PX_INVALID_U32);
|
||||
|
||||
if(prunerIndex==PX_INVALID_U32)
|
||||
{
|
||||
// PT: this shape is still in the waiting room
|
||||
PX_ASSERT(mWaitingRoom[id]==&shape);
|
||||
|
||||
mWaitingRoom[id] = mWaitingRoom.back();
|
||||
if(id+1 != mWaitingRoom.size())
|
||||
mWaitingRoom[id]->setSqBoundsId(id);
|
||||
mWaitingRoom.popBack();
|
||||
}
|
||||
else
|
||||
{
|
||||
// PT: this shape is active
|
||||
PX_ASSERT(prunerIndex<mPrunerSyncDataSize);
|
||||
PrunerSyncData* psd = mPrunerSyncData[prunerIndex];
|
||||
PX_ASSERT(psd);
|
||||
PX_ASSERT(psd->mShapes[id]==&shape);
|
||||
|
||||
psd->mShapes[id] = psd->mShapes.back();
|
||||
psd->mBoundsIndices[id] = psd->mBoundsIndices.back();
|
||||
psd->mRefs[id] = psd->mRefs.back();
|
||||
|
||||
if(id+1 != psd->mShapes.size())
|
||||
psd->mShapes[id]->setSqBoundsId(id);
|
||||
|
||||
psd->mShapes.popBack();
|
||||
psd->mBoundsIndices.popBack();
|
||||
psd->mRefs.popBack();
|
||||
|
||||
if(!psd->mShapes.size())
|
||||
{
|
||||
PX_DELETE(psd);
|
||||
mPrunerSyncData[prunerIndex] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SqBoundsManagerEx::syncBounds(SqBoundsSync& sync, SqRefFinder& finder, const PxBounds3* bounds, const PxTransform32* transforms, PxU64 contextID, const PxBitMap& ignoredIndices)
|
||||
{
|
||||
PX_PROFILE_ZONE("Sim.sceneQuerySyncBounds", contextID);
|
||||
PX_UNUSED(contextID);
|
||||
/*
|
||||
#if PX_DEBUG
|
||||
for(PxU32 i=0;i<mShapeData.size();i++)
|
||||
{
|
||||
const ShapeSQData& shape = mShapeData[i];
|
||||
PX_UNUSED(shape);
|
||||
PX_ASSERT(shape.mSim->getFlags() & PxShapeFlag::eSCENE_QUERY_SHAPE);
|
||||
PX_ASSERT(!shape.mSim->getBodySim()->usingSqKinematicTarget());
|
||||
PX_ASSERT(!shape.mSim->getBodySim()->isFrozen());
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
const PxU32 nbToGo = mWaitingRoom.size();
|
||||
if(nbToGo)
|
||||
{
|
||||
for(PxU32 i=0;i<nbToGo;i++)
|
||||
{
|
||||
ShapeSimBase* sim = mWaitingRoom[i];
|
||||
PX_ASSERT(i==sim->getSqBoundsId());
|
||||
PX_ASSERT(PX_INVALID_U32==sim->getSqPrunerIndex());
|
||||
|
||||
PxU32 prunerIndex = 0xffffffff;
|
||||
const ScPrunerHandle prunerHandle = finder.find(static_cast<PxRigidBody*>(sim->getBodySim()->getPxActor()), sim->getPxShape(), prunerIndex);
|
||||
|
||||
PX_ASSERT(prunerIndex!=0xffffffff);
|
||||
|
||||
if(prunerIndex>=mPrunerSyncDataSize)
|
||||
resize(prunerIndex);
|
||||
|
||||
PrunerSyncData* psd = mPrunerSyncData[prunerIndex];
|
||||
if(!psd)
|
||||
{
|
||||
psd = PX_NEW(PrunerSyncData);
|
||||
mPrunerSyncData[prunerIndex] = psd;
|
||||
}
|
||||
|
||||
PxArray<ShapeSimBase*>& shapes = psd->mShapes;
|
||||
PxArray<ScPrunerHandle>& refs = psd->mRefs;
|
||||
PxArray<PxU32>& boundsIndices = psd->mBoundsIndices;
|
||||
|
||||
const PxU32 id = shapes.size();
|
||||
PX_ASSERT(id == refs.size());
|
||||
PX_ASSERT(id == boundsIndices.size());
|
||||
|
||||
sim->setSqBoundsId(id);
|
||||
sim->setSqPrunerIndex(prunerIndex);
|
||||
|
||||
// PT: mShapes / mRefs / mBoundsIndices are "parallel arrays". These arrays are persistent.
|
||||
// mRefless is temporary/transient data to help populate mRefs each frame.
|
||||
// mRefs / mBoundsIndices will be ultimately passed to updateObjects, whose API dictates the layout here.
|
||||
// mShapes is not actually used for the sync, it's only here to be able to call setSqBoundsId in removeShape.
|
||||
|
||||
shapes.pushBack(sim);
|
||||
refs.pushBack(prunerHandle);
|
||||
boundsIndices.pushBack(sim->getElementID());
|
||||
}
|
||||
mWaitingRoom.clear(); // PT: TODO: optimize wasted memory here
|
||||
}
|
||||
|
||||
// PT: TODO: optimize this
|
||||
{
|
||||
const PxU32 nb = mPrunerSyncDataSize;
|
||||
for(PxU32 i=0;i<nb;i++)
|
||||
{
|
||||
PrunerSyncData* psd = mPrunerSyncData[i];
|
||||
if(psd)
|
||||
sync.sync(i, psd->mRefs.begin(), psd->mBoundsIndices.begin(), bounds, transforms, psd->mRefs.size(), ignoredIndices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
106
engine/third_party/physx/source/simulationcontroller/src/ScSqBoundsManager.h
vendored
Normal file
106
engine/third_party/physx/source/simulationcontroller/src/ScSqBoundsManager.h
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_SQ_BOUNDS_MANAGER_H
|
||||
#define SC_SQ_BOUNDS_MANAGER_H
|
||||
|
||||
#include "foundation/PxUserAllocated.h"
|
||||
#include "foundation/PxBitMap.h"
|
||||
#include "foundation/PxArray.h"
|
||||
|
||||
#include "ScSqBoundsSync.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
class PxBounds3;
|
||||
|
||||
namespace Sc
|
||||
{
|
||||
struct SqBoundsSync;
|
||||
struct SqRefFinder;
|
||||
class ShapeSimBase;
|
||||
|
||||
class SqBoundsManager0 : public PxUserAllocated
|
||||
{
|
||||
PX_NOCOPY(SqBoundsManager0)
|
||||
public:
|
||||
SqBoundsManager0();
|
||||
|
||||
void addSyncShape(ShapeSimBase& shape);
|
||||
void removeSyncShape(ShapeSimBase& shape);
|
||||
void syncBounds(SqBoundsSync& sync, SqRefFinder& finder, const PxBounds3* bounds, const PxTransform32* transforms, PxU64 contextID, const PxBitMap& ignoredIndices);
|
||||
|
||||
private:
|
||||
|
||||
PxArray<ShapeSimBase*> mShapes; //
|
||||
PxArray<ScPrunerHandle> mRefs; // SQ pruner references
|
||||
PxArray<PxU32> mBoundsIndices; // indices into the Sc bounds array
|
||||
PxArray<ShapeSimBase*> mRefless; // shapesims without references
|
||||
};
|
||||
|
||||
class SqBoundsManagerEx : public PxUserAllocated
|
||||
{
|
||||
PX_NOCOPY(SqBoundsManagerEx)
|
||||
public:
|
||||
SqBoundsManagerEx();
|
||||
~SqBoundsManagerEx();
|
||||
|
||||
void addSyncShape(ShapeSimBase& shape);
|
||||
void removeSyncShape(ShapeSimBase& shape);
|
||||
void syncBounds(SqBoundsSync& sync, SqRefFinder& finder, const PxBounds3* bounds, const PxTransform32* transforms, PxU64 contextID, const PxBitMap& ignoredIndices);
|
||||
|
||||
private:
|
||||
|
||||
PxArray<ShapeSimBase*> mWaitingRoom;
|
||||
|
||||
// PT: one of the many solutions discussed in https://confluence.nvidia.com/display/~pterdiman/The+new+SQ+system
|
||||
// Just to get something working. This will most likely need revisiting later.
|
||||
|
||||
struct PrunerSyncData : public PxUserAllocated
|
||||
{
|
||||
PxArray<ShapeSimBase*> mShapes; //
|
||||
// PT: layout dictated by the SqPruner API here. We could consider merging these two arrays.
|
||||
PxArray<ScPrunerHandle> mRefs; // SQ pruner references
|
||||
PxArray<PxU32> mBoundsIndices; // indices into the Sc bounds array
|
||||
};
|
||||
|
||||
PrunerSyncData** mPrunerSyncData;
|
||||
PxU32 mPrunerSyncDataSize;
|
||||
|
||||
void resize(PxU32 index);
|
||||
};
|
||||
|
||||
//class SqBoundsManager : public SqBoundsManager0
|
||||
class SqBoundsManager : public SqBoundsManagerEx
|
||||
{
|
||||
public:
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
48
engine/third_party/physx/source/simulationcontroller/src/ScStaticCore.cpp
vendored
Normal file
48
engine/third_party/physx/source/simulationcontroller/src/ScStaticCore.cpp
vendored
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-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
|
||||
#include "ScStaticCore.h"
|
||||
#include "ScStaticSim.h"
|
||||
#include "PxRigidStatic.h"
|
||||
|
||||
using namespace physx;
|
||||
|
||||
Sc::StaticSim* Sc::StaticCore::getSim() const
|
||||
{
|
||||
return static_cast<StaticSim*>(Sc::ActorCore::getSim());
|
||||
}
|
||||
|
||||
void Sc::StaticCore::setActor2World(const PxTransform& actor2World)
|
||||
{
|
||||
mCore.body2World = actor2World;
|
||||
|
||||
StaticSim* sim = getSim();
|
||||
if(sim)
|
||||
sim->notifyShapesOfTransformChange();
|
||||
}
|
||||
55
engine/third_party/physx/source/simulationcontroller/src/ScStaticSim.h
vendored
Normal file
55
engine/third_party/physx/source/simulationcontroller/src/ScStaticSim.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
||||
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
||||
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
||||
|
||||
#ifndef SC_STATIC_SIM_H
|
||||
#define SC_STATIC_SIM_H
|
||||
|
||||
#include "ScRigidSim.h"
|
||||
#include "ScStaticCore.h"
|
||||
|
||||
namespace physx
|
||||
{
|
||||
namespace Sc
|
||||
{
|
||||
class StaticSim : public RigidSim
|
||||
{
|
||||
//---------------------------------------------------------------------------------
|
||||
// Construction, destruction & initialization
|
||||
//---------------------------------------------------------------------------------
|
||||
public:
|
||||
StaticSim(Scene& scene, StaticCore& core) : RigidSim(scene, core) {}
|
||||
~StaticSim() { getStaticCore().setSim(NULL); }
|
||||
|
||||
PX_FORCE_INLINE StaticCore& getStaticCore() const { return static_cast<StaticCore&>(getRigidCore()); }
|
||||
};
|
||||
|
||||
} // namespace Sc
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user