Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Constraints/SixDOFConstraint.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/Physics/Constraints/TwoBodyConstraint.h>
8
#include <Jolt/Physics/Constraints/MotorSettings.h>
9
#include <Jolt/Physics/Constraints/ConstraintPart/PointConstraintPart.h>
10
#include <Jolt/Physics/Constraints/ConstraintPart/AxisConstraintPart.h>
11
#include <Jolt/Physics/Constraints/ConstraintPart/AngleConstraintPart.h>
12
#include <Jolt/Physics/Constraints/ConstraintPart/RotationEulerConstraintPart.h>
13
#include <Jolt/Physics/Constraints/ConstraintPart/SwingTwistConstraintPart.h>
14
15
JPH_NAMESPACE_BEGIN
16
17
/// 6 Degree Of Freedom Constraint setup structure. Allows control over each of the 6 degrees of freedom.
18
class JPH_EXPORT SixDOFConstraintSettings final : public TwoBodyConstraintSettings
19
{
20
JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, SixDOFConstraintSettings)
21
22
public:
23
/// Constraint is split up into translation/rotation around X, Y and Z axis.
24
enum EAxis
25
{
26
TranslationX,
27
TranslationY,
28
TranslationZ,
29
30
RotationX,
31
RotationY,
32
RotationZ,
33
34
Num,
35
NumTranslation = TranslationZ + 1,
36
};
37
38
// See: ConstraintSettings::SaveBinaryState
39
virtual void SaveBinaryState(StreamOut &inStream) const override;
40
41
/// Create an instance of this constraint
42
virtual TwoBodyConstraint * Create(Body &inBody1, Body &inBody2) const override;
43
44
/// This determines in which space the constraint is setup, all properties below should be in the specified space
45
EConstraintSpace mSpace = EConstraintSpace::WorldSpace;
46
47
/// Body 1 constraint reference frame (space determined by mSpace)
48
RVec3 mPosition1 = RVec3::sZero();
49
Vec3 mAxisX1 = Vec3::sAxisX();
50
Vec3 mAxisY1 = Vec3::sAxisY();
51
52
/// Body 2 constraint reference frame (space determined by mSpace)
53
RVec3 mPosition2 = RVec3::sZero();
54
Vec3 mAxisX2 = Vec3::sAxisX();
55
Vec3 mAxisY2 = Vec3::sAxisY();
56
57
/// Friction settings.
58
/// For translation: Max friction force in N. 0 = no friction.
59
/// For rotation: Max friction torque in Nm. 0 = no friction.
60
float mMaxFriction[EAxis::Num] = { 0, 0, 0, 0, 0, 0 };
61
62
/// The type of swing constraint that we want to use.
63
ESwingType mSwingType = ESwingType::Cone;
64
65
/// Limits.
66
/// For translation: Min and max linear limits in m (0 is frame of body 1 and 2 coincide).
67
/// For rotation: Min and max angular limits in rad (0 is frame of body 1 and 2 coincide). See comments at Axis enum for limit ranges.
68
///
69
/// Remove degree of freedom by setting min = FLT_MAX and max = -FLT_MAX. The constraint will be driven to 0 for this axis.
70
///
71
/// Free movement over an axis is allowed when min = -FLT_MAX and max = FLT_MAX.
72
///
73
/// Rotation limit around X-Axis: When limited, should be \f$\in [-\pi, \pi]\f$. Can be asymmetric around zero.
74
///
75
/// Rotation limit around Y-Z Axis: Forms a pyramid or cone shaped limit:
76
/// * For pyramid, should be \f$\in [-\pi, \pi]\f$ and does not need to be symmetrical around zero.
77
/// * For cone should be \f$\in [0, \pi]\f$ and needs to be symmetrical around zero (min limit is assumed to be -max limit).
78
float mLimitMin[EAxis::Num] = { -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX };
79
float mLimitMax[EAxis::Num] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX };
80
81
/// When enabled, this makes the limits soft. When the constraint exceeds the limits, a spring force will pull it back.
82
/// Only soft translation limits are supported, soft rotation limits are not currently supported.
83
SpringSettings mLimitsSpringSettings[EAxis::NumTranslation];
84
85
/// Make axis free (unconstrained)
86
void MakeFreeAxis(EAxis inAxis) { mLimitMin[inAxis] = -FLT_MAX; mLimitMax[inAxis] = FLT_MAX; }
87
bool IsFreeAxis(EAxis inAxis) const { return mLimitMin[inAxis] == -FLT_MAX && mLimitMax[inAxis] == FLT_MAX; }
88
89
/// Make axis fixed (fixed at value 0)
90
void MakeFixedAxis(EAxis inAxis) { mLimitMin[inAxis] = FLT_MAX; mLimitMax[inAxis] = -FLT_MAX; }
91
bool IsFixedAxis(EAxis inAxis) const { return mLimitMin[inAxis] >= mLimitMax[inAxis]; }
92
93
/// Set a valid range for the constraint (if inMax < inMin, the axis will become fixed)
94
void SetLimitedAxis(EAxis inAxis, float inMin, float inMax) { mLimitMin[inAxis] = inMin; mLimitMax[inAxis] = inMax; }
95
96
/// Motor settings for each axis
97
MotorSettings mMotorSettings[EAxis::Num];
98
99
protected:
100
// See: ConstraintSettings::RestoreBinaryState
101
virtual void RestoreBinaryState(StreamIn &inStream) override;
102
};
103
104
/// 6 Degree Of Freedom Constraint. Allows control over each of the 6 degrees of freedom.
105
class JPH_EXPORT SixDOFConstraint final : public TwoBodyConstraint
106
{
107
public:
108
JPH_OVERRIDE_NEW_DELETE
109
110
/// Get Axis from settings class
111
using EAxis = SixDOFConstraintSettings::EAxis;
112
113
/// Construct six DOF constraint
114
SixDOFConstraint(Body &inBody1, Body &inBody2, const SixDOFConstraintSettings &inSettings);
115
116
/// Generic interface of a constraint
117
virtual EConstraintSubType GetSubType() const override { return EConstraintSubType::SixDOF; }
118
virtual void NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inDeltaCOM) override;
119
virtual void SetupVelocityConstraint(float inDeltaTime) override;
120
virtual void ResetWarmStart() override;
121
virtual void WarmStartVelocityConstraint(float inWarmStartImpulseRatio) override;
122
virtual bool SolveVelocityConstraint(float inDeltaTime) override;
123
virtual bool SolvePositionConstraint(float inDeltaTime, float inBaumgarte) override;
124
#ifdef JPH_DEBUG_RENDERER
125
virtual void DrawConstraint(DebugRenderer *inRenderer) const override;
126
virtual void DrawConstraintLimits(DebugRenderer *inRenderer) const override;
127
#endif // JPH_DEBUG_RENDERER
128
virtual void SaveState(StateRecorder &inStream) const override;
129
virtual void RestoreState(StateRecorder &inStream) override;
130
virtual Ref<ConstraintSettings> GetConstraintSettings() const override;
131
132
// See: TwoBodyConstraint
133
virtual Mat44 GetConstraintToBody1Matrix() const override { return Mat44::sRotationTranslation(mConstraintToBody1, mLocalSpacePosition1); }
134
virtual Mat44 GetConstraintToBody2Matrix() const override { return Mat44::sRotationTranslation(mConstraintToBody2, mLocalSpacePosition2); }
135
136
/// Update the translation limits for this constraint
137
void SetTranslationLimits(Vec3Arg inLimitMin, Vec3Arg inLimitMax);
138
139
/// Update the rotational limits for this constraint
140
void SetRotationLimits(Vec3Arg inLimitMin, Vec3Arg inLimitMax);
141
142
/// Get constraint Limits
143
float GetLimitsMin(EAxis inAxis) const { return mLimitMin[inAxis]; }
144
float GetLimitsMax(EAxis inAxis) const { return mLimitMax[inAxis]; }
145
Vec3 GetTranslationLimitsMin() const { return Vec3::sLoadFloat3Unsafe(*reinterpret_cast<const Float3 *>(&mLimitMin[EAxis::TranslationX])); }
146
Vec3 GetTranslationLimitsMax() const { return Vec3::sLoadFloat3Unsafe(*reinterpret_cast<const Float3 *>(&mLimitMax[EAxis::TranslationX])); }
147
Vec3 GetRotationLimitsMin() const { return Vec3::sLoadFloat3Unsafe(*reinterpret_cast<const Float3 *>(&mLimitMin[EAxis::RotationX])); }
148
Vec3 GetRotationLimitsMax() const { return Vec3::sLoadFloat3Unsafe(*reinterpret_cast<const Float3 *>(&mLimitMax[EAxis::RotationX])); }
149
150
/// Check which axis are fixed/free
151
inline bool IsFixedAxis(EAxis inAxis) const { return (mFixedAxis & (1 << inAxis)) != 0; }
152
inline bool IsFreeAxis(EAxis inAxis) const { return (mFreeAxis & (1 << inAxis)) != 0; }
153
154
/// Update the limits spring settings
155
const SpringSettings & GetLimitsSpringSettings(EAxis inAxis) const { JPH_ASSERT(inAxis < EAxis::NumTranslation); return mLimitsSpringSettings[inAxis]; }
156
void SetLimitsSpringSettings(EAxis inAxis, const SpringSettings& inLimitsSpringSettings) { JPH_ASSERT(inAxis < EAxis::NumTranslation); mLimitsSpringSettings[inAxis] = inLimitsSpringSettings; CacheHasSpringLimits(); }
157
158
/// Set the max friction for each axis
159
void SetMaxFriction(EAxis inAxis, float inFriction);
160
float GetMaxFriction(EAxis inAxis) const { return mMaxFriction[inAxis]; }
161
162
/// Get rotation of constraint in constraint space
163
Quat GetRotationInConstraintSpace() const;
164
165
/// Motor settings
166
MotorSettings & GetMotorSettings(EAxis inAxis) { return mMotorSettings[inAxis]; }
167
const MotorSettings & GetMotorSettings(EAxis inAxis) const { return mMotorSettings[inAxis]; }
168
169
/// Motor controls.
170
/// Translation motors work in constraint space of body 1.
171
/// Rotation motors work in constraint space of body 2 (!).
172
void SetMotorState(EAxis inAxis, EMotorState inState);
173
EMotorState GetMotorState(EAxis inAxis) const { return mMotorState[inAxis]; }
174
175
/// Set the target velocity in body 1 constraint space
176
Vec3 GetTargetVelocityCS() const { return mTargetVelocity; }
177
void SetTargetVelocityCS(Vec3Arg inVelocity) { mTargetVelocity = inVelocity; }
178
179
/// Set the target angular velocity in body 2 constraint space (!)
180
void SetTargetAngularVelocityCS(Vec3Arg inAngularVelocity) { mTargetAngularVelocity = inAngularVelocity; }
181
Vec3 GetTargetAngularVelocityCS() const { return mTargetAngularVelocity; }
182
183
/// Set the target position in body 1 constraint space
184
Vec3 GetTargetPositionCS() const { return mTargetPosition; }
185
void SetTargetPositionCS(Vec3Arg inPosition) { mTargetPosition = inPosition; }
186
187
/// Set the target orientation in body 1 constraint space
188
void SetTargetOrientationCS(QuatArg inOrientation);
189
Quat GetTargetOrientationCS() const { return mTargetOrientation; }
190
191
/// Set the target orientation in body space (R2 = R1 * inOrientation, where R1 and R2 are the world space rotations for body 1 and 2).
192
/// Solve: R2 * ConstraintToBody2 = R1 * ConstraintToBody1 * q (see SwingTwistConstraint::GetSwingTwist) and R2 = R1 * inOrientation for q.
193
void SetTargetOrientationBS(QuatArg inOrientation) { SetTargetOrientationCS(mConstraintToBody1.Conjugated() * inOrientation * mConstraintToBody2); }
194
195
///@name Get Lagrange multiplier from last physics update (the linear/angular impulse applied to satisfy the constraint)
196
inline Vec3 GetTotalLambdaPosition() const { return IsTranslationFullyConstrained()? mPointConstraintPart.GetTotalLambda() : Vec3(mTranslationConstraintPart[0].GetTotalLambda(), mTranslationConstraintPart[1].GetTotalLambda(), mTranslationConstraintPart[2].GetTotalLambda()); }
197
inline Vec3 GetTotalLambdaRotation() const { return IsRotationFullyConstrained()? mRotationConstraintPart.GetTotalLambda() : Vec3(mSwingTwistConstraintPart.GetTotalTwistLambda(), mSwingTwistConstraintPart.GetTotalSwingYLambda(), mSwingTwistConstraintPart.GetTotalSwingZLambda()); }
198
inline Vec3 GetTotalLambdaMotorTranslation() const { return Vec3(mMotorTranslationConstraintPart[0].GetTotalLambda(), mMotorTranslationConstraintPart[1].GetTotalLambda(), mMotorTranslationConstraintPart[2].GetTotalLambda()); }
199
inline Vec3 GetTotalLambdaMotorRotation() const { return Vec3(mMotorRotationConstraintPart[0].GetTotalLambda(), mMotorRotationConstraintPart[1].GetTotalLambda(), mMotorRotationConstraintPart[2].GetTotalLambda()); }
200
201
private:
202
// Calculate properties needed for the position constraint
203
inline void GetPositionConstraintProperties(Vec3 &outR1PlusU, Vec3 &outR2, Vec3 &outU) const;
204
205
// Sanitize the translation limits
206
inline void UpdateTranslationLimits();
207
208
// Propagate the rotation limits to the constraint part
209
inline void UpdateRotationLimits();
210
211
// Update the cached state of which axis are free and which ones are fixed
212
inline void UpdateFixedFreeAxis();
213
214
// Cache the state of mTranslationMotorActive
215
void CacheTranslationMotorActive();
216
217
// Cache the state of mRotationMotorActive
218
void CacheRotationMotorActive();
219
220
// Cache the state of mRotationPositionMotorActive
221
void CacheRotationPositionMotorActive();
222
223
/// Cache the state of mHasSpringLimits
224
void CacheHasSpringLimits();
225
226
// Constraint settings helper functions
227
inline bool IsTranslationConstrained() const { return (mFreeAxis & 0b111) != 0b111; }
228
inline bool IsTranslationFullyConstrained() const { return (mFixedAxis & 0b111) == 0b111 && !mHasSpringLimits; }
229
inline bool IsRotationConstrained() const { return (mFreeAxis & 0b111000) != 0b111000; }
230
inline bool IsRotationFullyConstrained() const { return (mFixedAxis & 0b111000) == 0b111000; }
231
inline bool HasFriction(EAxis inAxis) const { return !IsFixedAxis(inAxis) && mMaxFriction[inAxis] > 0.0f; }
232
233
// CONFIGURATION PROPERTIES FOLLOW
234
235
// Local space constraint positions
236
Vec3 mLocalSpacePosition1;
237
Vec3 mLocalSpacePosition2;
238
239
// Transforms from constraint space to body space
240
Quat mConstraintToBody1;
241
Quat mConstraintToBody2;
242
243
// Limits
244
uint8 mFreeAxis = 0; // Bitmask of free axis (bit 0 = TranslationX)
245
uint8 mFixedAxis = 0; // Bitmask of fixed axis (bit 0 = TranslationX)
246
bool mTranslationMotorActive = false; // If any of the translational frictions / motors are active
247
bool mRotationMotorActive = false; // If any of the rotational frictions / motors are active
248
uint8 mRotationPositionMotorActive = 0; // Bitmask of axis that have position motor active (bit 0 = RotationX)
249
bool mHasSpringLimits = false; // If any of the limit springs have a non-zero frequency/stiffness
250
float mLimitMin[EAxis::Num];
251
float mLimitMax[EAxis::Num];
252
SpringSettings mLimitsSpringSettings[EAxis::NumTranslation];
253
254
// Motor settings for each axis
255
MotorSettings mMotorSettings[EAxis::Num];
256
257
// Friction settings for each axis
258
float mMaxFriction[EAxis::Num];
259
260
// Motor controls
261
EMotorState mMotorState[EAxis::Num] = { EMotorState::Off, EMotorState::Off, EMotorState::Off, EMotorState::Off, EMotorState::Off, EMotorState::Off };
262
Vec3 mTargetVelocity = Vec3::sZero();
263
Vec3 mTargetAngularVelocity = Vec3::sZero();
264
Vec3 mTargetPosition = Vec3::sZero();
265
Quat mTargetOrientation = Quat::sIdentity();
266
267
// RUN TIME PROPERTIES FOLLOW
268
269
// Constraint space axis in world space
270
Vec3 mTranslationAxis[3];
271
Vec3 mRotationAxis[3];
272
273
// Translation displacement (valid when translation axis has a range limit)
274
float mDisplacement[3];
275
276
// Individual constraint parts for translation, or a combined point constraint part if all axis are fixed
277
AxisConstraintPart mTranslationConstraintPart[3];
278
PointConstraintPart mPointConstraintPart;
279
280
// Individual constraint parts for rotation or a combined constraint part if rotation is fixed
281
SwingTwistConstraintPart mSwingTwistConstraintPart;
282
RotationEulerConstraintPart mRotationConstraintPart;
283
284
// Motor or friction constraints
285
AxisConstraintPart mMotorTranslationConstraintPart[3];
286
AngleConstraintPart mMotorRotationConstraintPart[3];
287
};
288
289
JPH_NAMESPACE_END
290
291