MotionProperties.inl 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. JPH_NAMESPACE_BEGIN
  5. void MotionProperties::SetMassProperties(const MassProperties &inMassProperties)
  6. {
  7. // Set inverse mass
  8. JPH_ASSERT(inMassProperties.mMass > 0.0f);
  9. mInvMass = 1.0f / inMassProperties.mMass;
  10. // Set inverse inertia
  11. Mat44 rotation;
  12. Vec3 diagonal;
  13. if (inMassProperties.DecomposePrincipalMomentsOfInertia(rotation, diagonal)
  14. && !diagonal.IsNearZero())
  15. {
  16. mInvInertiaDiagonal = diagonal.Reciprocal();
  17. mInertiaRotation = rotation.GetQuaternion();
  18. }
  19. else
  20. {
  21. // Failed! Fall back to inertia tensor of sphere with radius 1.
  22. mInvInertiaDiagonal = Vec3::sReplicate(2.5f * mInvMass);
  23. mInertiaRotation = Quat::sIdentity();
  24. }
  25. }
  26. void MotionProperties::MoveKinematic(Vec3Arg inDeltaPosition, QuatArg inDeltaRotation, float inDeltaTime)
  27. {
  28. JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess, BodyAccess::EAccess::ReadWrite));
  29. JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sPositionAccess, BodyAccess::EAccess::Read));
  30. JPH_ASSERT(mCachedMotionType != EMotionType::Static);
  31. // Calculate required linear velocity
  32. mLinearVelocity = inDeltaPosition / inDeltaTime;
  33. // Calculate required angular velocity
  34. Vec3 axis;
  35. float angle;
  36. inDeltaRotation.GetAxisAngle(axis, angle);
  37. mAngularVelocity = axis * (angle / inDeltaTime);
  38. }
  39. void MotionProperties::ClampLinearVelocity()
  40. {
  41. JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess, BodyAccess::EAccess::ReadWrite));
  42. float len_sq = mLinearVelocity.LengthSq();
  43. JPH_ASSERT(isfinite(len_sq));
  44. if (len_sq > Square(mMaxLinearVelocity))
  45. mLinearVelocity *= mMaxLinearVelocity / sqrt(len_sq);
  46. }
  47. void MotionProperties::ClampAngularVelocity()
  48. {
  49. JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess, BodyAccess::EAccess::ReadWrite));
  50. float len_sq = mAngularVelocity.LengthSq();
  51. JPH_ASSERT(isfinite(len_sq));
  52. if (len_sq > Square(mMaxAngularVelocity))
  53. mAngularVelocity *= mMaxAngularVelocity / sqrt(len_sq);
  54. }
  55. inline Mat44 MotionProperties::GetLocalSpaceInverseInertiaUnchecked() const
  56. {
  57. Mat44 rotation = Mat44::sRotation(mInertiaRotation);
  58. Mat44 rotation_mul_scale_transposed(mInvInertiaDiagonal.SplatX() * rotation.GetColumn4(0), mInvInertiaDiagonal.SplatY() * rotation.GetColumn4(1), mInvInertiaDiagonal.SplatZ() * rotation.GetColumn4(2), Vec4(0, 0, 0, 1));
  59. return rotation.Multiply3x3RightTransposed(rotation_mul_scale_transposed);
  60. }
  61. inline Mat44 MotionProperties::GetLocalSpaceInverseInertia() const
  62. {
  63. JPH_ASSERT(mCachedMotionType == EMotionType::Dynamic);
  64. return GetLocalSpaceInverseInertiaUnchecked();
  65. }
  66. Mat44 MotionProperties::GetInverseInertiaForRotation(Mat44Arg inRotation) const
  67. {
  68. JPH_ASSERT(mCachedMotionType == EMotionType::Dynamic);
  69. Mat44 rotation = inRotation * Mat44::sRotation(mInertiaRotation);
  70. Mat44 rotation_mul_scale_transposed(mInvInertiaDiagonal.SplatX() * rotation.GetColumn4(0), mInvInertiaDiagonal.SplatY() * rotation.GetColumn4(1), mInvInertiaDiagonal.SplatZ() * rotation.GetColumn4(2), Vec4(0, 0, 0, 1));
  71. return rotation.Multiply3x3RightTransposed(rotation_mul_scale_transposed);
  72. }
  73. Vec3 MotionProperties::MultiplyWorldSpaceInverseInertiaByVector(QuatArg inBodyRotation, Vec3Arg inV) const
  74. {
  75. JPH_ASSERT(mCachedMotionType == EMotionType::Dynamic);
  76. Mat44 rotation = Mat44::sRotation(inBodyRotation * mInertiaRotation);
  77. return rotation.Multiply3x3(mInvInertiaDiagonal * rotation.Multiply3x3Transposed(inV));
  78. }
  79. void MotionProperties::ApplyForceTorqueAndDragInternal(QuatArg inBodyRotation, Vec3Arg inGravity, float inDeltaTime)
  80. {
  81. JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess, BodyAccess::EAccess::ReadWrite));
  82. JPH_ASSERT(mCachedMotionType == EMotionType::Dynamic);
  83. // Update linear velocity
  84. mLinearVelocity += inDeltaTime * (mGravityFactor * inGravity + mInvMass * Vec3::sLoadFloat3Unsafe(mForce));
  85. // Update angular velocity
  86. mAngularVelocity += inDeltaTime * MultiplyWorldSpaceInverseInertiaByVector(inBodyRotation, Vec3::sLoadFloat3Unsafe(mTorque));
  87. // Linear damping: dv/dt = -c * v
  88. // Solution: v(t) = v(0) * e^(-c * t) or v2 = v1 * e^(-c * dt)
  89. // Taylor expansion of e^(-c * dt) = 1 - c * dt + ...
  90. // Since dt is usually in the order of 1/60 and c is a low number too this approximation is good enough
  91. mLinearVelocity *= max(0.0f, 1.0f - mLinearDamping * inDeltaTime);
  92. mAngularVelocity *= max(0.0f, 1.0f - mAngularDamping * inDeltaTime);
  93. // Clamp velocities
  94. ClampLinearVelocity();
  95. ClampAngularVelocity();
  96. }
  97. void MotionProperties::ResetSleepTestSpheres(const Vec3 *inPoints)
  98. {
  99. for (int i = 0; i < 3; ++i)
  100. mSleepTestSpheres[i] = Sphere(inPoints[i], 0.0f);
  101. mSleepTestTimer = 0.0f;
  102. }
  103. JPH_NAMESPACE_END