29#ifndef DY_BODYCORE_INTEGRATOR_H
30#define DY_BODYCORE_INTEGRATOR_H
33#include "PxsRigidBody.h"
34#include "DySolverBody.h"
35#include "DySleepingConfigulation.h"
36#include "PxsIslandSim.h"
45(
const PxVec3& gravity,
const PxReal dt,
const PxReal linearDamping,
const PxReal angularDamping,
const PxReal accelScale,
46const PxReal maxLinearVelocitySq,
const PxReal maxAngularVelocitySq, PxVec3& inOutLinearVelocity, PxVec3& inOutAngularVelocity,
52 PxVec3 linearVelocity = inOutLinearVelocity;
53 PxVec3 angularVelocity = inOutAngularVelocity;
55 const PxReal linearDampingTimesDT=linearDamping*dt;
56 const PxReal angularDampingTimesDT=angularDamping*dt;
57 const PxReal oneMinusLinearDampingTimesDT=1.0f-linearDampingTimesDT;
58 const PxReal oneMinusAngularDampingTimesDT=1.0f-angularDampingTimesDT;
63 const PxVec3 linearAccelTimesDT = gravity*dt *accelScale;
64 linearVelocity += linearAccelTimesDT;
68 const PxReal linVelMultiplier = physx::intrinsics::fsel(oneMinusLinearDampingTimesDT, oneMinusLinearDampingTimesDT, 0.0f);
69 const PxReal angVelMultiplier = physx::intrinsics::fsel(oneMinusAngularDampingTimesDT, oneMinusAngularDampingTimesDT, 0.0f);
70 linearVelocity*=linVelMultiplier;
71 angularVelocity*=angVelMultiplier;
74 const PxReal linVelSq = linearVelocity.magnitudeSquared();
75 if(linVelSq > maxLinearVelocitySq)
77 linearVelocity *=
PxSqrt(maxLinearVelocitySq / linVelSq);
79 const PxReal angVelSq = angularVelocity.magnitudeSquared();
80 if(angVelSq > maxAngularVelocitySq)
82 angularVelocity *=
PxSqrt(maxAngularVelocitySq / angVelSq);
85 inOutLinearVelocity = linearVelocity;
86 inOutAngularVelocity = angularVelocity;
90PX_FORCE_INLINE void integrateCore(PxVec3& motionLinearVelocity, PxVec3& motionAngularVelocity,
91 PxSolverBody& solverBody, PxSolverBodyData& solverBodyData,
const PxF32 dt,
const PxU32 lockFlags)
95 if (lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_X)
97 motionLinearVelocity.x = 0.f;
98 solverBody.linearVelocity.x = 0.f;
100 if (lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_Y)
102 motionLinearVelocity.y = 0.f;
103 solverBody.linearVelocity.y = 0.f;
105 if (lockFlags & PxRigidDynamicLockFlag::eLOCK_LINEAR_Z)
107 motionLinearVelocity.z = 0.f;
108 solverBody.linearVelocity.z = 0.f;
112 if (lockFlags & PxRigidDynamicLockFlag::eLOCK_ANGULAR_X)
114 motionAngularVelocity.x = 0.f;
115 solverBody.angularState.x = 0.f;
117 if (lockFlags & PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y)
119 motionAngularVelocity.y = 0.f;
120 solverBody.angularState.y = 0.f;
122 if (lockFlags & PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z)
124 motionAngularVelocity.z = 0.f;
125 solverBody.angularState.z = 0.f;
130 PxVec3 linearMotionVel = solverBodyData.linearVelocity + motionLinearVelocity;
131 PxVec3 delta = linearMotionVel * dt;
132 PxVec3 angularMotionVel = solverBodyData.angularVelocity + solverBodyData.sqrtInvInertia * motionAngularVelocity;
133 PxReal w = angularMotionVel.magnitudeSquared();
134 solverBodyData.body2World.p += delta;
135 PX_ASSERT(solverBodyData.body2World.p.isFinite());
139 solverBodyData.linearVelocity += solverBody.linearVelocity;
140 solverBodyData.angularVelocity += solverBodyData.sqrtInvInertia * solverBody.angularState;
149 const PxReal maxW = 1e+7f;
152 angularMotionVel = angularMotionVel.getNormalized() * maxW;
155 const PxReal v = dt * w * 0.5f;
160 const PxVec3 pqr = angularMotionVel * s;
161 const PxQuat quatVel(pqr.x, pqr.y, pqr.z, 0);
162 PxQuat result = quatVel * solverBodyData.body2World.q;
164 result += solverBodyData.body2World.q * q;
166 solverBodyData.body2World.q = result.getNormalized();
167 PX_ASSERT(solverBodyData.body2World.q.isSane());
168 PX_ASSERT(solverBodyData.body2World.q.isFinite());
171 motionLinearVelocity = linearMotionVel;
172 motionAngularVelocity = angularMotionVel;
177PX_FORCE_INLINE PxReal _updateWakeCounter(PxsRigidBody* originalBody, PxReal dt, PxReal ,
const bool enableStabilization,
const Cm::SpatialVector& motionVelocity,
180 PxsBodyCore& bodyCore = originalBody->getCore();
183 PxReal wakeCounterResetTime = 20.0f*0.02f;
185 PxReal wc = bodyCore.wakeCounter;
188 if (enableStabilization)
191 const PxTransform& body2World = bodyCore.body2World;
195 const PxVec3& t = bodyCore.inverseInertia;
196 const PxVec3 inertia(t.x > 0.f ? 1.0f / t.x : 1.f, t.y > 0.f ? 1.0f / t.y : 1.f, t.z > 0.f ? 1.0f / t.z : 1.f);
198 const PxVec3& sleepLinVelAcc = motionVelocity.linear;
199 const PxVec3 sleepAngVelAcc = body2World.q.rotateInv(motionVelocity.angular);
204 PxReal invMass = bodyCore.inverseMass;
208 const PxReal angular = sleepAngVelAcc.multiply(sleepAngVelAcc).dot(inertia) * invMass;
209 const PxReal linear = sleepLinVelAcc.magnitudeSquared();
210 const PxReal frameNormalizedEnergy = 0.5f * (angular + linear);
212 const PxReal cf = hasStaticTouch ? PxReal(
PxMin(10u, bodyCore.numCountedInteractions)) : 0.f;
213 const PxReal freezeThresh = cf*bodyCore.freezeThreshold;
215 originalBody->freezeCount =
PxMax(originalBody->freezeCount - dt, 0.0f);
218 PxReal accelScale =
PxMin(1.f, originalBody->accelScale + dt);
220 if (frameNormalizedEnergy >= freezeThresh)
223 originalBody->freezeCount = PXD_FREEZE_INTERVAL;
238 const PxReal sleepDamping = PXD_SLEEP_DAMPING;
239 const PxReal sleepDampingTimesDT = sleepDamping*dt;
240 const PxReal d = 1.0f - sleepDampingTimesDT;
241 bodyCore.linearVelocity = bodyCore.linearVelocity * d;
242 bodyCore.angularVelocity = bodyCore.angularVelocity * d;
243 accelScale = accelScale * 0.75f + 0.25f*PXD_FREEZE_SCALE;
245 freeze = originalBody->freezeCount == 0.f && frameNormalizedEnergy < (bodyCore.freezeThreshold * PXD_FREEZE_TOLERANCE);
248 originalBody->accelScale = accelScale;
250 const PxU32 wasFrozen = originalBody->mInternalFlags & PxsRigidBody::eFROZEN;
255 flags = PxU16(PxsRigidBody::eFROZEN);
257 flags |= PxsRigidBody::eFREEZE_THIS_FRAME;
258 bodyCore.body2World = originalBody->getLastCCDTransform();
264 flags |= PxsRigidBody::eUNFREEZE_THIS_FRAME;
266 originalBody->mInternalFlags = flags;
272 if (wc < wakeCounterResetTime * 0.5f || wc < dt)
275 originalBody->sleepLinVelAcc += sleepLinVelAcc;
276 originalBody->sleepAngVelAcc += sleepAngVelAcc;
279 if (frameNormalizedEnergy >= bodyCore.sleepThreshold)
282 const PxReal sleepAngular = originalBody->sleepAngVelAcc.multiply(originalBody->sleepAngVelAcc).dot(inertia) * invMass;
283 const PxReal sleepLinear = originalBody->sleepLinVelAcc.magnitudeSquared();
284 const PxReal normalizedEnergy = 0.5f * (sleepAngular + sleepLinear);
285 const PxReal sleepClusterFactor = PxReal(1u + bodyCore.numCountedInteractions);
287 const PxReal threshold = sleepClusterFactor*bodyCore.sleepThreshold;
290 if (normalizedEnergy >= threshold)
294 originalBody->sleepAngVelAcc = PxVec3(0);
295 originalBody->sleepLinVelAcc = PxVec3(0);
297 const float factor = bodyCore.sleepThreshold == 0.f ? 2.0f :
PxMin(normalizedEnergy / threshold, 2.0f);
299 wc = factor * 0.5f * wakeCounterResetTime + dt * (sleepClusterFactor - 1.0f);
300 bodyCore.solverWakeCounter = wc;
305 originalBody->mInternalFlags |= PxsRigidBody::eACTIVATE_THIS_FRAME;
315 if (wc < wakeCounterResetTime * 0.5f || wc < dt)
317 const PxTransform& body2World = bodyCore.body2World;
320 const PxVec3& t = bodyCore.inverseInertia;
321 const PxVec3 inertia(t.x > 0.f ? 1.0f / t.x : 1.f, t.y > 0.f ? 1.0f / t.y : 1.f, t.z > 0.f ? 1.0f / t.z : 1.f);
323 const PxVec3& sleepLinVelAcc = motionVelocity.linear;
324 const PxVec3 sleepAngVelAcc = body2World.q.rotateInv(motionVelocity.angular);
326 originalBody->sleepLinVelAcc += sleepLinVelAcc;
327 originalBody->sleepAngVelAcc += sleepAngVelAcc;
329 PxReal invMass = bodyCore.inverseMass;
333 const PxReal angular = originalBody->sleepAngVelAcc.multiply(originalBody->sleepAngVelAcc).dot(inertia) * invMass;
334 const PxReal linear = originalBody->sleepLinVelAcc.magnitudeSquared();
335 const PxReal normalizedEnergy = 0.5f * (angular + linear);
338 const PxReal clusterFactor = PxReal(1 + bodyCore.numCountedInteractions);
339 const PxReal threshold = clusterFactor*bodyCore.sleepThreshold;
341 if (normalizedEnergy >= threshold)
344 originalBody->sleepLinVelAcc = PxVec3(0);
345 originalBody->sleepAngVelAcc = PxVec3(0);
346 const float factor = threshold == 0.f ? 2.0f :
PxMin(normalizedEnergy / threshold, 2.0f);
348 wc = factor * 0.5f * wakeCounterResetTime + dt * (clusterFactor - 1.0f);
349 bodyCore.solverWakeCounter = wc;
353 flags |= PxsRigidBody::eACTIVATE_THIS_FRAME;
357 originalBody->mInternalFlags = flags;
365 wc =
PxMax(wc - dt, 0.0f);
366 bodyCore.solverWakeCounter = wc;
370PX_FORCE_INLINE void sleepCheck(PxsRigidBody* originalBody,
const PxReal dt,
const PxReal intDt,
const bool enableStabilization,
const Cm::SpatialVector& motionVelocity,
373 const PxReal wc = _updateWakeCounter(originalBody, dt, intDt, enableStabilization, motionVelocity, hasStaticTouch);
374 const bool wakeCounterZero = (wc == 0.0f);
379 originalBody->mInternalFlags |= PxsRigidBody::eDEACTIVATE_THIS_FRAME;
381 originalBody->sleepLinVelAcc = PxVec3(0);
382 originalBody->sleepAngVelAcc = PxVec3(0);
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
PX_CUDA_CALLABLE PX_FORCE_INLINE float PxSqrt(float a)
Square root.
Definition PxMath.h:146
PX_CUDA_CALLABLE PX_FORCE_INLINE T PxMax(T a, T b)
The return value is the greater of the two specified values.
Definition PxMath.h:72
PX_CUDA_CALLABLE PX_FORCE_INLINE void PxSinCos(const PxF32 a, PxF32 &sin, PxF32 &cos)
compute sine and cosine at the same time
Definition PxMath.h:202
PX_CUDA_CALLABLE PX_FORCE_INLINE T PxMin(T a, T b)
The return value is the lesser of the two specified values.
Definition PxMath.h:88