Files
XCEngine/engine/third_party/physx/source/simulationcontroller/src/ScSimStateData.h

214 lines
9.2 KiB
C++

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