feat(physics): wire physx sdk into build
This commit is contained in:
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user