Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
MotionProperties.inl
Go to the documentation of this file.
1// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
8
9void MotionProperties::MoveKinematic(Vec3Arg inDeltaPosition, QuatArg inDeltaRotation, float inDeltaTime)
10{
11 JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::ReadWrite));
12 JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sPositionAccess(), BodyAccess::EAccess::Read));
13 JPH_ASSERT(mCachedBodyType == EBodyType::RigidBody);
14 JPH_ASSERT(mCachedMotionType != EMotionType::Static);
15
16 // Calculate required linear velocity
17 mLinearVelocity = LockTranslation(inDeltaPosition / inDeltaTime);
18
19 // Calculate required angular velocity
20 mAngularVelocity = LockAngular(inDeltaRotation.GetAngularVelocity(inDeltaTime));
21}
22
24{
25 JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::ReadWrite));
26
27 float len_sq = mLinearVelocity.LengthSq();
28 JPH_ASSERT(isfinite(len_sq));
29 if (len_sq > Square(mMaxLinearVelocity))
30 mLinearVelocity *= mMaxLinearVelocity / sqrt(len_sq);
31}
32
34{
35 JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::ReadWrite));
36
37 float len_sq = mAngularVelocity.LengthSq();
38 JPH_ASSERT(isfinite(len_sq));
39 if (len_sq > Square(mMaxAngularVelocity))
40 mAngularVelocity *= mMaxAngularVelocity / sqrt(len_sq);
41}
42
44{
45 Mat44 rotation = Mat44::sRotation(mInertiaRotation);
46 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));
47 return rotation.Multiply3x3RightTransposed(rotation_mul_scale_transposed);
48}
49
50inline void MotionProperties::ScaleToMass(float inMass)
51{
52 JPH_ASSERT(mInvMass > 0.0f, "Body must have finite mass");
53 JPH_ASSERT(inMass > 0.0f, "New mass cannot be zero");
54
55 float new_inv_mass = 1.0f / inMass;
56 mInvInertiaDiagonal *= new_inv_mass / mInvMass;
57 mInvMass = new_inv_mass;
58}
59
65
67{
68 JPH_ASSERT(mCachedMotionType == EMotionType::Dynamic);
69
70 Mat44 rotation = inRotation.Multiply3x3(Mat44::sRotation(mInertiaRotation));
71 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));
72 Mat44 inverse_inertia = rotation.Multiply3x3RightTransposed(rotation_mul_scale_transposed);
73
74 // We need to mask out both the rows and columns of DOFs that are not allowed
75 Vec4 angular_dofs_mask = GetAngularDOFsMask().ReinterpretAsFloat();
76 inverse_inertia.SetColumn4(0, Vec4::sAnd(inverse_inertia.GetColumn4(0), Vec4::sAnd(angular_dofs_mask, angular_dofs_mask.SplatX())));
77 inverse_inertia.SetColumn4(1, Vec4::sAnd(inverse_inertia.GetColumn4(1), Vec4::sAnd(angular_dofs_mask, angular_dofs_mask.SplatY())));
78 inverse_inertia.SetColumn4(2, Vec4::sAnd(inverse_inertia.GetColumn4(2), Vec4::sAnd(angular_dofs_mask, angular_dofs_mask.SplatZ())));
79
80 return inverse_inertia;
81}
82
84{
85 JPH_ASSERT(mCachedMotionType == EMotionType::Dynamic);
86
87 // Mask out columns of DOFs that are not allowed
88 Vec3 angular_dofs_mask = Vec3(GetAngularDOFsMask().ReinterpretAsFloat());
89 Vec3 v = Vec3::sAnd(inV, angular_dofs_mask);
90
91 // Multiply vector by inverse inertia
92 Mat44 rotation = Mat44::sRotation(inBodyRotation * mInertiaRotation);
93 Vec3 result = rotation.Multiply3x3(mInvInertiaDiagonal * rotation.Multiply3x3Transposed(v));
94
95 // Mask out rows of DOFs that are not allowed
96 return Vec3::sAnd(result, angular_dofs_mask);
97}
98
99void MotionProperties::ApplyGyroscopicForceInternal(QuatArg inBodyRotation, float inDeltaTime)
100{
101 JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::ReadWrite));
102 JPH_ASSERT(mCachedBodyType == EBodyType::RigidBody);
103 JPH_ASSERT(mCachedMotionType == EMotionType::Dynamic);
104
105 // Calculate local space inertia tensor (a diagonal in local space)
106 UVec4 is_zero = Vec3::sEquals(mInvInertiaDiagonal, Vec3::sZero());
107 Vec3 denominator = Vec3::sSelect(mInvInertiaDiagonal, Vec3::sOne(), is_zero);
108 Vec3 nominator = Vec3::sSelect(Vec3::sOne(), Vec3::sZero(), is_zero);
109 Vec3 local_inertia = nominator / denominator; // Avoid dividing by zero, inertia in this axis will be zero
110
111 // Calculate local space angular momentum
112 Quat inertia_space_to_world_space = inBodyRotation * mInertiaRotation;
113 Vec3 local_angular_velocity = inertia_space_to_world_space.InverseRotate(mAngularVelocity);
114 Vec3 local_momentum = local_inertia * local_angular_velocity;
115
116 // The gyroscopic force applies a torque: T = -w x I w where w is angular velocity and I the inertia tensor
117 // Calculate the new angular momentum by applying the gyroscopic force and make sure the new magnitude is the same as the old one
118 // to avoid introducing energy into the system due to the Euler step
119 Vec3 new_local_momentum = local_momentum - inDeltaTime * local_angular_velocity.Cross(local_momentum);
120 float new_local_momentum_len_sq = new_local_momentum.LengthSq();
121 new_local_momentum = new_local_momentum_len_sq > 0.0f? new_local_momentum * sqrt(local_momentum.LengthSq() / new_local_momentum_len_sq) : Vec3::sZero();
122
123 // Convert back to world space angular velocity
124 mAngularVelocity = inertia_space_to_world_space * (mInvInertiaDiagonal * new_local_momentum);
125}
126
127void MotionProperties::ApplyForceTorqueAndDragInternal(QuatArg inBodyRotation, Vec3Arg inGravity, float inDeltaTime)
128{
129 JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::ReadWrite));
130 JPH_ASSERT(mCachedBodyType == EBodyType::RigidBody);
131 JPH_ASSERT(mCachedMotionType == EMotionType::Dynamic);
132
133 // Update linear velocity
134 mLinearVelocity = LockTranslation(mLinearVelocity + inDeltaTime * (mGravityFactor * inGravity + mInvMass * GetAccumulatedForce()));
135
136 // Update angular velocity
137 mAngularVelocity += inDeltaTime * MultiplyWorldSpaceInverseInertiaByVector(inBodyRotation, GetAccumulatedTorque());
138
139 // Linear damping: dv/dt = -c * v
140 // Solution: v(t) = v(0) * e^(-c * t) or v2 = v1 * e^(-c * dt)
141 // Taylor expansion of e^(-c * dt) = 1 - c * dt + ...
142 // Since dt is usually in the order of 1/60 and c is a low number too this approximation is good enough
143 mLinearVelocity *= max(0.0f, 1.0f - mLinearDamping * inDeltaTime);
144 mAngularVelocity *= max(0.0f, 1.0f - mAngularDamping * inDeltaTime);
145
146 // Clamp velocities
149}
150
152{
153#ifdef JPH_DOUBLE_PRECISION
154 // Make spheres relative to the first point and initialize them to zero radius
155 DVec3 offset = inPoints[0];
156 offset.StoreDouble3(&mSleepTestOffset);
157 mSleepTestSpheres[0] = Sphere(Vec3::sZero(), 0.0f);
158 for (int i = 1; i < 3; ++i)
159 mSleepTestSpheres[i] = Sphere(Vec3(inPoints[i] - offset), 0.0f);
160#else
161 // Initialize the spheres to zero radius around the supplied points
162 for (int i = 0; i < 3; ++i)
163 mSleepTestSpheres[i] = Sphere(inPoints[i], 0.0f);
164#endif
165
166 mSleepTestTimer = 0.0f;
167}
168
169ECanSleep MotionProperties::AccumulateSleepTime(float inDeltaTime, float inTimeBeforeSleep)
170{
171 mSleepTestTimer += inDeltaTime;
172 return mSleepTestTimer >= inTimeBeforeSleep? ECanSleep::CanSleep : ECanSleep::CannotSleep;
173}
174
@ RigidBody
Rigid body consisting of a rigid shape.
#define JPH_NAMESPACE_END
Definition Core.h:425
#define JPH_NAMESPACE_BEGIN
Definition Core.h:419
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
JPH_INLINE constexpr T Square(T inV)
Square a value.
Definition Math.h:55
ECanSleep
Enum that determines if an object can go to sleep.
Definition MotionProperties.h:22
@ CanSleep
Object can go to sleep.
@ CannotSleep
Object cannot go to sleep.
@ Static
Non movable.
@ Dynamic
Responds to forces as a normal physics object.
Definition DVec3.h:14
JPH_INLINE void StoreDouble3(Double3 *outV) const
Store 3 doubles to memory.
Definition DVec3.inl:176
Holds a 4x4 matrix of floats, but supports also operations on the 3x3 upper left part of the matrix.
Definition Mat44.h:13
JPH_INLINE Vec3 Multiply3x3Transposed(Vec3Arg inV) const
Multiply vector by only 3x3 part of the transpose of the matrix ( )
Definition Mat44.inl:336
JPH_INLINE Mat44 Multiply3x3RightTransposed(Mat44Arg inM) const
Multiply 3x3 matrix by the transpose of a 3x3 matrix ( )
Definition Mat44.inl:397
JPH_INLINE Vec4 GetColumn4(uint inCol) const
Definition Mat44.h:160
JPH_INLINE Vec3 Multiply3x3(Vec3Arg inV) const
Multiply vector by only 3x3 part of the matrix.
Definition Mat44.inl:316
static JPH_INLINE Mat44 sRotation(Vec3Arg inAxis, float inAngle)
Rotate around arbitrary axis.
Definition Mat44.inl:139
JPH_INLINE void SetColumn4(uint inCol, Vec4Arg inV)
Definition Mat44.h:161
void ClampAngularVelocity()
Definition MotionProperties.inl:33
void ScaleToMass(float inMass)
Definition MotionProperties.inl:50
ECanSleep AccumulateSleepTime(float inDeltaTime, float inTimeBeforeSleep)
Accumulate sleep time and return if a body can go to sleep.
Definition MotionProperties.inl:169
void ClampLinearVelocity()
Clamp velocity according to limit.
Definition MotionProperties.inl:23
JPH_INLINE Vec3 LockAngular(Vec3Arg inV) const
Takes an angular velocity / torque vector inV and returns a vector where the components that are not ...
Definition MotionProperties.h:176
JPH_INLINE Vec3 GetAccumulatedTorque() const
Definition MotionProperties.h:139
void ApplyGyroscopicForceInternal(QuatArg inBodyRotation, float inDeltaTime)
Apply the gyroscopic force (aka Dzhanibekov effect, see https://en.wikipedia.org/wiki/Tennis_racket_t...
Definition MotionProperties.inl:99
Mat44 GetLocalSpaceInverseInertiaUnchecked() const
Same as GetLocalSpaceInverseInertia() but doesn't check if the body is dynamic.
Definition MotionProperties.inl:43
JPH_INLINE Vec3 MultiplyWorldSpaceInverseInertiaByVector(QuatArg inBodyRotation, Vec3Arg inV) const
Multiply a vector with the inverse world space inertia tensor ( ). Zero if object is static or kinema...
Definition MotionProperties.inl:83
void ResetSleepTestSpheres(const RVec3 *inPoints)
Reset spheres to center around inPoints with radius 0.
Definition MotionProperties.inl:151
JPH_INLINE Vec3 GetAccumulatedForce() const
Definition MotionProperties.h:136
JPH_INLINE Vec3 LockTranslation(Vec3Arg inV) const
Takes a translation vector inV and returns a vector where the components that are not allowed by mAll...
Definition MotionProperties.h:163
Mat44 GetInverseInertiaForRotation(Mat44Arg inRotation) const
Get inverse inertia matrix ( ) for a given object rotation (translation will be ignored)....
Definition MotionProperties.inl:66
Mat44 GetLocalSpaceInverseInertia() const
Get inverse inertia matrix ( ). Will be a matrix of zeros for a static or kinematic object.
Definition MotionProperties.inl:60
JPH_INLINE UVec4 GetAngularDOFsMask() const
Returns a vector where the angular components that are not allowed by mAllowedDOFs are set to 0 and t...
Definition MotionProperties.h:169
void ApplyForceTorqueAndDragInternal(QuatArg inBodyRotation, Vec3Arg inGravity, float inDeltaTime)
Apply all accumulated forces, torques and drag (should only be called by the PhysicsSystem)
Definition MotionProperties.inl:127
void MoveKinematic(Vec3Arg inDeltaPosition, QuatArg inDeltaRotation, float inDeltaTime)
Set velocity of body such that it will be rotate/translate by inDeltaPosition/Rotation in inDeltaTime...
Definition MotionProperties.inl:9
Definition Quat.h:33
JPH_INLINE Vec3 InverseRotate(Vec3Arg inValue) const
Rotate a vector by the inverse of this quaternion.
Definition Quat.inl:373
JPH_INLINE Vec3 GetAngularVelocity(float inDeltaTime) const
Calculate angular velocity given that this quaternion represents the rotation that is reached after i...
Definition Quat.inl:154
Definition UVec4.h:12
JPH_INLINE Vec4 ReinterpretAsFloat() const
Reinterpret UVec4 as a Vec4 (doesn't change the bits)
Definition UVec4.inl:367
Definition Vec3.h:17
JPH_INLINE Vec4 SplatX() const
Replicate the X component to all components.
Definition Vec3.inl:534
JPH_INLINE Vec3 Cross(Vec3Arg inV2) const
Cross product.
Definition Vec3.inl:595
static JPH_INLINE Vec3 sOne()
Vector with all ones.
Definition Vec3.inl:125
JPH_INLINE Vec4 SplatZ() const
Replicate the Z component to all components.
Definition Vec3.inl:556
static JPH_INLINE Vec3 sAnd(Vec3Arg inV1, Vec3Arg inV2)
Logical and (component wise)
Definition Vec3.inl:315
JPH_INLINE Vec4 SplatY() const
Replicate the Y component to all components.
Definition Vec3.inl:545
JPH_INLINE float LengthSq() const
Squared length of vector.
Definition Vec3.inl:666
static JPH_INLINE UVec4 sEquals(Vec3Arg inV1, Vec3Arg inV2)
Equals (component wise)
Definition Vec3.inl:178
static JPH_INLINE Vec3 sZero()
Vector with all zeros.
Definition Vec3.inl:103
static JPH_INLINE Vec3 sSelect(Vec3Arg inNotSet, Vec3Arg inSet, UVec4Arg inControl)
Component wise select, returns inNotSet when highest bit of inControl = 0 and inSet when highest bit ...
Definition Vec3.inl:270
Definition Vec4.h:14
JPH_INLINE Vec4 SplatX() const
Replicate the X component to all components.
Definition Vec4.inl:573
static JPH_INLINE Vec4 sAnd(Vec4Arg inV1, Vec4Arg inV2)
Logical and (component wise)
Definition Vec4.inl:303
JPH_INLINE Vec4 SplatY() const
Replicate the Y component to all components.
Definition Vec4.inl:584
JPH_INLINE Vec4 SplatZ() const
Replicate the Z component to all components.
Definition Vec4.inl:595