214 lines
9.2 KiB
C++
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
|
|
|