Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Body/MotionProperties.h
9912 views
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
7
#include <Jolt/Geometry/Sphere.h>
8
#include <Jolt/Physics/Body/AllowedDOFs.h>
9
#include <Jolt/Physics/Body/MotionQuality.h>
10
#include <Jolt/Physics/Body/BodyAccess.h>
11
#include <Jolt/Physics/Body/MotionType.h>
12
#include <Jolt/Physics/Body/BodyType.h>
13
#include <Jolt/Physics/Body/MassProperties.h>
14
#include <Jolt/Physics/DeterminismLog.h>
15
16
JPH_NAMESPACE_BEGIN
17
18
class StateRecorder;
19
20
/// Enum that determines if an object can go to sleep
21
enum class ECanSleep
22
{
23
CannotSleep = 0, ///< Object cannot go to sleep
24
CanSleep = 1, ///< Object can go to sleep
25
};
26
27
/// The Body class only keeps track of state for static bodies, the MotionProperties class keeps the additional state needed for a moving Body. It has a 1-on-1 relationship with the body.
28
class JPH_EXPORT MotionProperties
29
{
30
public:
31
JPH_OVERRIDE_NEW_DELETE
32
33
/// Motion quality, or how well it detects collisions when it has a high velocity
34
EMotionQuality GetMotionQuality() const { return mMotionQuality; }
35
36
/// Get the allowed degrees of freedom that this body has (this can be changed by calling SetMassProperties)
37
inline EAllowedDOFs GetAllowedDOFs() const { return mAllowedDOFs; }
38
39
/// If this body can go to sleep.
40
inline bool GetAllowSleeping() const { return mAllowSleeping; }
41
42
/// Get world space linear velocity of the center of mass
43
inline Vec3 GetLinearVelocity() const { JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::Read)); return mLinearVelocity; }
44
45
/// Set world space linear velocity of the center of mass
46
void SetLinearVelocity(Vec3Arg inLinearVelocity) { JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::ReadWrite)); JPH_ASSERT(inLinearVelocity.Length() <= mMaxLinearVelocity); mLinearVelocity = LockTranslation(inLinearVelocity); }
47
48
/// Set world space linear velocity of the center of mass, will make sure the value is clamped against the maximum linear velocity
49
void SetLinearVelocityClamped(Vec3Arg inLinearVelocity) { mLinearVelocity = LockTranslation(inLinearVelocity); ClampLinearVelocity(); }
50
51
/// Get world space angular velocity of the center of mass
52
inline Vec3 GetAngularVelocity() const { JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::Read)); return mAngularVelocity; }
53
54
/// Set world space angular velocity of the center of mass
55
void SetAngularVelocity(Vec3Arg inAngularVelocity) { JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::ReadWrite)); JPH_ASSERT(inAngularVelocity.Length() <= mMaxAngularVelocity); mAngularVelocity = LockAngular(inAngularVelocity); }
56
57
/// Set world space angular velocity of the center of mass, will make sure the value is clamped against the maximum angular velocity
58
void SetAngularVelocityClamped(Vec3Arg inAngularVelocity) { mAngularVelocity = LockAngular(inAngularVelocity); ClampAngularVelocity(); }
59
60
/// Set velocity of body such that it will be rotate/translate by inDeltaPosition/Rotation in inDeltaTime seconds.
61
inline void MoveKinematic(Vec3Arg inDeltaPosition, QuatArg inDeltaRotation, float inDeltaTime);
62
63
///@name Velocity limits
64
///@{
65
66
/// Maximum linear velocity that a body can achieve. Used to prevent the system from exploding.
67
inline float GetMaxLinearVelocity() const { return mMaxLinearVelocity; }
68
inline void SetMaxLinearVelocity(float inLinearVelocity) { JPH_ASSERT(inLinearVelocity >= 0.0f); mMaxLinearVelocity = inLinearVelocity; }
69
70
/// Maximum angular velocity that a body can achieve. Used to prevent the system from exploding.
71
inline float GetMaxAngularVelocity() const { return mMaxAngularVelocity; }
72
inline void SetMaxAngularVelocity(float inAngularVelocity) { JPH_ASSERT(inAngularVelocity >= 0.0f); mMaxAngularVelocity = inAngularVelocity; }
73
///@}
74
75
/// Clamp velocity according to limit
76
inline void ClampLinearVelocity();
77
inline void ClampAngularVelocity();
78
79
/// Get linear damping: dv/dt = -c * v. c must be between 0 and 1 but is usually close to 0.
80
inline float GetLinearDamping() const { return mLinearDamping; }
81
void SetLinearDamping(float inLinearDamping) { JPH_ASSERT(inLinearDamping >= 0.0f); mLinearDamping = inLinearDamping; }
82
83
/// Get angular damping: dw/dt = -c * w. c must be between 0 and 1 but is usually close to 0.
84
inline float GetAngularDamping() const { return mAngularDamping; }
85
void SetAngularDamping(float inAngularDamping) { JPH_ASSERT(inAngularDamping >= 0.0f); mAngularDamping = inAngularDamping; }
86
87
/// Get gravity factor (1 = normal gravity, 0 = no gravity)
88
inline float GetGravityFactor() const { return mGravityFactor; }
89
void SetGravityFactor(float inGravityFactor) { mGravityFactor = inGravityFactor; }
90
91
/// Set the mass and inertia tensor
92
void SetMassProperties(EAllowedDOFs inAllowedDOFs, const MassProperties &inMassProperties);
93
94
/// Get inverse mass (1 / mass). Should only be called on a dynamic object (static or kinematic bodies have infinite mass so should be treated as 1 / mass = 0)
95
inline float GetInverseMass() const { JPH_ASSERT(mCachedMotionType == EMotionType::Dynamic); return mInvMass; }
96
inline float GetInverseMassUnchecked() const { return mInvMass; }
97
98
/// Set the inverse mass (1 / mass).
99
/// Note that mass and inertia are linearly related (e.g. inertia of a sphere with mass m and radius r is \f$2/5 \: m \: r^2\f$).
100
/// If you change mass, inertia should probably change as well. You can use ScaleToMass to update mass and inertia at the same time.
101
/// If all your translation degrees of freedom are restricted, make sure this is zero (see EAllowedDOFs).
102
void SetInverseMass(float inInverseMass) { mInvMass = inInverseMass; }
103
104
/// Diagonal of inverse inertia matrix: D. Should only be called on a dynamic object (static or kinematic bodies have infinite mass so should be treated as D = 0)
105
inline Vec3 GetInverseInertiaDiagonal() const { JPH_ASSERT(mCachedMotionType == EMotionType::Dynamic); return mInvInertiaDiagonal; }
106
107
/// Rotation (R) that takes inverse inertia diagonal to local space: \f$I_{body}^{-1} = R \: D \: R^{-1}\f$
108
inline Quat GetInertiaRotation() const { return mInertiaRotation; }
109
110
/// Set the inverse inertia tensor in local space by setting the diagonal and the rotation: \f$I_{body}^{-1} = R \: D \: R^{-1}\f$.
111
/// Note that mass and inertia are linearly related (e.g. inertia of a sphere with mass m and radius r is \f$2/5 \: m \: r^2\f$).
112
/// If you change inertia, mass should probably change as well. You can use ScaleToMass to update mass and inertia at the same time.
113
/// If all your rotation degrees of freedom are restricted, make sure this is zero (see EAllowedDOFs).
114
void SetInverseInertia(Vec3Arg inDiagonal, QuatArg inRot) { mInvInertiaDiagonal = inDiagonal; mInertiaRotation = inRot; }
115
116
/// Sets the mass to inMass and scale the inertia tensor based on the ratio between the old and new mass.
117
/// Note that this only works when the current mass is finite (i.e. the body is dynamic and translational degrees of freedom are not restricted).
118
void ScaleToMass(float inMass);
119
120
/// Get inverse inertia matrix (\f$I_{body}^{-1}\f$). Will be a matrix of zeros for a static or kinematic object.
121
inline Mat44 GetLocalSpaceInverseInertia() const;
122
123
/// Same as GetLocalSpaceInverseInertia() but doesn't check if the body is dynamic
124
inline Mat44 GetLocalSpaceInverseInertiaUnchecked() const;
125
126
/// Get inverse inertia matrix (\f$I^{-1}\f$) for a given object rotation (translation will be ignored). Zero if object is static or kinematic.
127
inline Mat44 GetInverseInertiaForRotation(Mat44Arg inRotation) const;
128
129
/// Multiply a vector with the inverse world space inertia tensor (\f$I_{world}^{-1}\f$). Zero if object is static or kinematic.
130
JPH_INLINE Vec3 MultiplyWorldSpaceInverseInertiaByVector(QuatArg inBodyRotation, Vec3Arg inV) const;
131
132
/// Velocity of point inPoint (in center of mass space, e.g. on the surface of the body) of the body (unit: m/s)
133
JPH_INLINE Vec3 GetPointVelocityCOM(Vec3Arg inPointRelativeToCOM) const { return mLinearVelocity + mAngularVelocity.Cross(inPointRelativeToCOM); }
134
135
// Get the total amount of force applied to the center of mass this time step (through Body::AddForce calls). Note that it will reset to zero after PhysicsSystem::Update.
136
JPH_INLINE Vec3 GetAccumulatedForce() const { return Vec3::sLoadFloat3Unsafe(mForce); }
137
138
// Get the total amount of torque applied to the center of mass this time step (through Body::AddForce/Body::AddTorque calls). Note that it will reset to zero after PhysicsSystem::Update.
139
JPH_INLINE Vec3 GetAccumulatedTorque() const { return Vec3::sLoadFloat3Unsafe(mTorque); }
140
141
// Reset the total accumulated force, note that this will be done automatically after every time step.
142
JPH_INLINE void ResetForce() { mForce = Float3(0, 0, 0); }
143
144
// Reset the total accumulated torque, note that this will be done automatically after every time step.
145
JPH_INLINE void ResetTorque() { mTorque = Float3(0, 0, 0); }
146
147
// Reset the current velocity and accumulated force and torque.
148
JPH_INLINE void ResetMotion()
149
{
150
JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::ReadWrite));
151
mLinearVelocity = mAngularVelocity = Vec3::sZero();
152
mForce = mTorque = Float3(0, 0, 0);
153
}
154
155
/// Returns a vector where the linear components that are not allowed by mAllowedDOFs are set to 0 and the rest to 0xffffffff
156
JPH_INLINE UVec4 GetLinearDOFsMask() const
157
{
158
UVec4 mask(uint32(EAllowedDOFs::TranslationX), uint32(EAllowedDOFs::TranslationY), uint32(EAllowedDOFs::TranslationZ), 0);
159
return UVec4::sEquals(UVec4::sAnd(UVec4::sReplicate(uint32(mAllowedDOFs)), mask), mask);
160
}
161
162
/// Takes a translation vector inV and returns a vector where the components that are not allowed by mAllowedDOFs are set to 0
163
JPH_INLINE Vec3 LockTranslation(Vec3Arg inV) const
164
{
165
return Vec3::sAnd(inV, Vec3(GetLinearDOFsMask().ReinterpretAsFloat()));
166
}
167
168
/// Returns a vector where the angular components that are not allowed by mAllowedDOFs are set to 0 and the rest to 0xffffffff
169
JPH_INLINE UVec4 GetAngularDOFsMask() const
170
{
171
UVec4 mask(uint32(EAllowedDOFs::RotationX), uint32(EAllowedDOFs::RotationY), uint32(EAllowedDOFs::RotationZ), 0);
172
return UVec4::sEquals(UVec4::sAnd(UVec4::sReplicate(uint32(mAllowedDOFs)), mask), mask);
173
}
174
175
/// Takes an angular velocity / torque vector inV and returns a vector where the components that are not allowed by mAllowedDOFs are set to 0
176
JPH_INLINE Vec3 LockAngular(Vec3Arg inV) const
177
{
178
return Vec3::sAnd(inV, Vec3(GetAngularDOFsMask().ReinterpretAsFloat()));
179
}
180
181
/// Used only when this body is dynamic and colliding. Override for the number of solver velocity iterations to run, 0 means use the default in PhysicsSettings::mNumVelocitySteps. The number of iterations to use is the max of all contacts and constraints in the island.
182
void SetNumVelocityStepsOverride(uint inN) { JPH_ASSERT(inN < 256); mNumVelocityStepsOverride = uint8(inN); }
183
uint GetNumVelocityStepsOverride() const { return mNumVelocityStepsOverride; }
184
185
/// Used only when this body is dynamic and colliding. Override for the number of solver position iterations to run, 0 means use the default in PhysicsSettings::mNumPositionSteps. The number of iterations to use is the max of all contacts and constraints in the island.
186
void SetNumPositionStepsOverride(uint inN) { JPH_ASSERT(inN < 256); mNumPositionStepsOverride = uint8(inN); }
187
uint GetNumPositionStepsOverride() const { return mNumPositionStepsOverride; }
188
189
////////////////////////////////////////////////////////////
190
// FUNCTIONS BELOW THIS LINE ARE FOR INTERNAL USE ONLY
191
////////////////////////////////////////////////////////////
192
193
///@name Update linear and angular velocity (used during constraint solving)
194
///@{
195
inline void AddLinearVelocityStep(Vec3Arg inLinearVelocityChange) { JPH_DET_LOG("AddLinearVelocityStep: " << inLinearVelocityChange); JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::ReadWrite)); mLinearVelocity = LockTranslation(mLinearVelocity + inLinearVelocityChange); JPH_ASSERT(!mLinearVelocity.IsNaN()); }
196
inline void SubLinearVelocityStep(Vec3Arg inLinearVelocityChange) { JPH_DET_LOG("SubLinearVelocityStep: " << inLinearVelocityChange); JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::ReadWrite)); mLinearVelocity = LockTranslation(mLinearVelocity - inLinearVelocityChange); JPH_ASSERT(!mLinearVelocity.IsNaN()); }
197
inline void AddAngularVelocityStep(Vec3Arg inAngularVelocityChange) { JPH_DET_LOG("AddAngularVelocityStep: " << inAngularVelocityChange); JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::ReadWrite)); mAngularVelocity += inAngularVelocityChange; JPH_ASSERT(!mAngularVelocity.IsNaN()); }
198
inline void SubAngularVelocityStep(Vec3Arg inAngularVelocityChange) { JPH_DET_LOG("SubAngularVelocityStep: " << inAngularVelocityChange); JPH_ASSERT(BodyAccess::sCheckRights(BodyAccess::sVelocityAccess(), BodyAccess::EAccess::ReadWrite)); mAngularVelocity -= inAngularVelocityChange; JPH_ASSERT(!mAngularVelocity.IsNaN()); }
199
///@}
200
201
/// Apply the gyroscopic force (aka Dzhanibekov effect, see https://en.wikipedia.org/wiki/Tennis_racket_theorem)
202
inline void ApplyGyroscopicForceInternal(QuatArg inBodyRotation, float inDeltaTime);
203
204
/// Apply all accumulated forces, torques and drag (should only be called by the PhysicsSystem)
205
inline void ApplyForceTorqueAndDragInternal(QuatArg inBodyRotation, Vec3Arg inGravity, float inDeltaTime);
206
207
/// Access to the island index
208
uint32 GetIslandIndexInternal() const { return mIslandIndex; }
209
void SetIslandIndexInternal(uint32 inIndex) { mIslandIndex = inIndex; }
210
211
/// Access to the index in the active bodies array
212
uint32 GetIndexInActiveBodiesInternal() const { return mIndexInActiveBodies; }
213
214
#ifdef JPH_DOUBLE_PRECISION
215
inline DVec3 GetSleepTestOffset() const { return DVec3::sLoadDouble3Unsafe(mSleepTestOffset); }
216
#endif // JPH_DOUBLE_PRECISION
217
218
/// Reset spheres to center around inPoints with radius 0
219
inline void ResetSleepTestSpheres(const RVec3 *inPoints);
220
221
/// Reset the sleep test timer without resetting the sleep test spheres
222
inline void ResetSleepTestTimer() { mSleepTestTimer = 0.0f; }
223
224
/// Accumulate sleep time and return if a body can go to sleep
225
inline ECanSleep AccumulateSleepTime(float inDeltaTime, float inTimeBeforeSleep);
226
227
/// Saving state for replay
228
void SaveState(StateRecorder &inStream) const;
229
230
/// Restoring state for replay
231
void RestoreState(StateRecorder &inStream);
232
233
static constexpr uint32 cInactiveIndex = uint32(-1); ///< Constant indicating that body is not active
234
235
private:
236
friend class BodyManager;
237
friend class Body;
238
239
// 1st cache line
240
// 16 byte aligned
241
Vec3 mLinearVelocity { Vec3::sZero() }; ///< World space linear velocity of the center of mass (m/s)
242
Vec3 mAngularVelocity { Vec3::sZero() }; ///< World space angular velocity (rad/s)
243
Vec3 mInvInertiaDiagonal; ///< Diagonal of inverse inertia matrix: D
244
Quat mInertiaRotation; ///< Rotation (R) that takes inverse inertia diagonal to local space: Ibody^-1 = R * D * R^-1
245
246
// 2nd cache line
247
// 4 byte aligned
248
Float3 mForce { 0, 0, 0 }; ///< Accumulated world space force (N). Note loaded through intrinsics so ensure that the 4 bytes after this are readable!
249
Float3 mTorque { 0, 0, 0 }; ///< Accumulated world space torque (N m). Note loaded through intrinsics so ensure that the 4 bytes after this are readable!
250
float mInvMass; ///< Inverse mass of the object (1/kg)
251
float mLinearDamping; ///< Linear damping: dv/dt = -c * v. c must be between 0 and 1 but is usually close to 0.
252
float mAngularDamping; ///< Angular damping: dw/dt = -c * w. c must be between 0 and 1 but is usually close to 0.
253
float mMaxLinearVelocity; ///< Maximum linear velocity that this body can reach (m/s)
254
float mMaxAngularVelocity; ///< Maximum angular velocity that this body can reach (rad/s)
255
float mGravityFactor; ///< Factor to multiply gravity with
256
uint32 mIndexInActiveBodies = cInactiveIndex; ///< If the body is active, this is the index in the active body list or cInactiveIndex if it is not active (note that there are 2 lists, one for rigid and one for soft bodies)
257
uint32 mIslandIndex = cInactiveIndex; ///< Index of the island that this body is part of, when the body has not yet been updated or is not active this is cInactiveIndex
258
259
// 1 byte aligned
260
EMotionQuality mMotionQuality; ///< Motion quality, or how well it detects collisions when it has a high velocity
261
bool mAllowSleeping; ///< If this body can go to sleep
262
EAllowedDOFs mAllowedDOFs = EAllowedDOFs::All; ///< Allowed degrees of freedom for this body
263
uint8 mNumVelocityStepsOverride = 0; ///< Used only when this body is dynamic and colliding. Override for the number of solver velocity iterations to run, 0 means use the default in PhysicsSettings::mNumVelocitySteps. The number of iterations to use is the max of all contacts and constraints in the island.
264
uint8 mNumPositionStepsOverride = 0; ///< Used only when this body is dynamic and colliding. Override for the number of solver position iterations to run, 0 means use the default in PhysicsSettings::mNumPositionSteps. The number of iterations to use is the max of all contacts and constraints in the island.
265
266
// 3rd cache line (least frequently used)
267
// 4 byte aligned (or 8 byte if running in double precision)
268
#ifdef JPH_DOUBLE_PRECISION
269
Double3 mSleepTestOffset; ///< mSleepTestSpheres are relative to this offset to prevent floating point inaccuracies. Warning: Loaded using sLoadDouble3Unsafe which will read 8 extra bytes.
270
#endif // JPH_DOUBLE_PRECISION
271
Sphere mSleepTestSpheres[3]; ///< Measure motion for 3 points on the body to see if it is resting: COM, COM + largest bounding box axis, COM + second largest bounding box axis
272
float mSleepTestTimer; ///< How long this body has been within the movement tolerance
273
274
#ifdef JPH_ENABLE_ASSERTS
275
EBodyType mCachedBodyType; ///< Copied from Body::mBodyType and cached for asserting purposes
276
EMotionType mCachedMotionType; ///< Copied from Body::mMotionType and cached for asserting purposes
277
#endif
278
};
279
280
JPH_NAMESPACE_END
281
282
#include "MotionProperties.inl"
283
284