Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Constraints/Constraint.h
9913 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/Core/Reference.h>
8
#include <Jolt/Core/NonCopyable.h>
9
#include <Jolt/Core/Result.h>
10
#include <Jolt/ObjectStream/SerializableObject.h>
11
12
JPH_NAMESPACE_BEGIN
13
14
class BodyID;
15
class IslandBuilder;
16
class LargeIslandSplitter;
17
class BodyManager;
18
class StateRecorder;
19
class StreamIn;
20
class StreamOut;
21
#ifdef JPH_DEBUG_RENDERER
22
class DebugRenderer;
23
#endif // JPH_DEBUG_RENDERER
24
25
/// Enum to identify constraint type
26
enum class EConstraintType
27
{
28
Constraint,
29
TwoBodyConstraint,
30
};
31
32
/// Enum to identify constraint sub type
33
enum class EConstraintSubType
34
{
35
Fixed,
36
Point,
37
Hinge,
38
Slider,
39
Distance,
40
Cone,
41
SwingTwist,
42
SixDOF,
43
Path,
44
Vehicle,
45
RackAndPinion,
46
Gear,
47
Pulley,
48
49
/// User defined constraint types start here
50
User1,
51
User2,
52
User3,
53
User4
54
};
55
56
/// Certain constraints support setting them up in local or world space. This governs what is used.
57
enum class EConstraintSpace
58
{
59
LocalToBodyCOM, ///< All constraint properties are specified in local space to center of mass of the bodies that are being constrained (so e.g. 'constraint position 1' will be local to body 1 COM, 'constraint position 2' will be local to body 2 COM). Note that this means you need to subtract Shape::GetCenterOfMass() from positions!
60
WorldSpace, ///< All constraint properties are specified in world space
61
};
62
63
/// Class used to store the configuration of a constraint. Allows run-time creation of constraints.
64
class JPH_EXPORT ConstraintSettings : public SerializableObject, public RefTarget<ConstraintSettings>
65
{
66
JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, ConstraintSettings)
67
68
public:
69
using ConstraintResult = Result<Ref<ConstraintSettings>>;
70
71
/// Saves the contents of the constraint settings in binary form to inStream.
72
virtual void SaveBinaryState(StreamOut &inStream) const;
73
74
/// Creates a constraint of the correct type and restores its contents from the binary stream inStream.
75
static ConstraintResult sRestoreFromBinaryState(StreamIn &inStream);
76
77
/// If this constraint is enabled initially. Use Constraint::SetEnabled to toggle after creation.
78
bool mEnabled = true;
79
80
/// Priority of the constraint when solving. Higher numbers have are more likely to be solved correctly.
81
/// Note that if you want a deterministic simulation and you cannot guarantee the order in which constraints are added/removed, you can make the priority for all constraints unique to get a deterministic ordering.
82
uint32 mConstraintPriority = 0;
83
84
/// Used only when the constraint is active. 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.
85
uint mNumVelocityStepsOverride = 0;
86
87
/// Used only when the constraint is active. 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.
88
uint mNumPositionStepsOverride = 0;
89
90
/// Size of constraint when drawing it through the debug renderer
91
float mDrawConstraintSize = 1.0f;
92
93
/// User data value (can be used by application)
94
uint64 mUserData = 0;
95
96
protected:
97
/// This function should not be called directly, it is used by sRestoreFromBinaryState.
98
virtual void RestoreBinaryState(StreamIn &inStream);
99
};
100
101
/// Base class for all physics constraints. A constraint removes one or more degrees of freedom for a rigid body.
102
class JPH_EXPORT Constraint : public RefTarget<Constraint>, public NonCopyable
103
{
104
public:
105
JPH_OVERRIDE_NEW_DELETE
106
107
/// Constructor
108
explicit Constraint(const ConstraintSettings &inSettings) :
109
#ifdef JPH_DEBUG_RENDERER
110
mDrawConstraintSize(inSettings.mDrawConstraintSize),
111
#endif // JPH_DEBUG_RENDERER
112
mConstraintPriority(inSettings.mConstraintPriority),
113
mNumVelocityStepsOverride(uint8(inSettings.mNumVelocityStepsOverride)),
114
mNumPositionStepsOverride(uint8(inSettings.mNumPositionStepsOverride)),
115
mEnabled(inSettings.mEnabled),
116
mUserData(inSettings.mUserData)
117
{
118
JPH_ASSERT(inSettings.mNumVelocityStepsOverride < 256);
119
JPH_ASSERT(inSettings.mNumPositionStepsOverride < 256);
120
}
121
122
/// Virtual destructor
123
virtual ~Constraint() = default;
124
125
/// Get the type of a constraint
126
virtual EConstraintType GetType() const { return EConstraintType::Constraint; }
127
128
/// Get the sub type of a constraint
129
virtual EConstraintSubType GetSubType() const = 0;
130
131
/// Priority of the constraint when solving. Higher numbers have are more likely to be solved correctly.
132
/// Note that if you want a deterministic simulation and you cannot guarantee the order in which constraints are added/removed, you can make the priority for all constraints unique to get a deterministic ordering.
133
uint32 GetConstraintPriority() const { return mConstraintPriority; }
134
void SetConstraintPriority(uint32 inPriority) { mConstraintPriority = inPriority; }
135
136
/// Used only when the constraint is active. 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.
137
void SetNumVelocityStepsOverride(uint inN) { JPH_ASSERT(inN < 256); mNumVelocityStepsOverride = uint8(inN); }
138
uint GetNumVelocityStepsOverride() const { return mNumVelocityStepsOverride; }
139
140
/// Used only when the constraint is active. 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.
141
void SetNumPositionStepsOverride(uint inN) { JPH_ASSERT(inN < 256); mNumPositionStepsOverride = uint8(inN); }
142
uint GetNumPositionStepsOverride() const { return mNumPositionStepsOverride; }
143
144
/// Enable / disable this constraint. This can e.g. be used to implement a breakable constraint by detecting that the constraint impulse
145
/// (see e.g. PointConstraint::GetTotalLambdaPosition) went over a certain limit and then disabling the constraint.
146
/// Note that although a disabled constraint will not affect the simulation in any way anymore, it does incur some processing overhead.
147
/// Alternatively you can remove a constraint from the constraint manager (which may be more costly if you want to disable the constraint for a short while).
148
void SetEnabled(bool inEnabled) { mEnabled = inEnabled; }
149
150
/// Test if a constraint is enabled.
151
bool GetEnabled() const { return mEnabled; }
152
153
/// Access to the user data, can be used for anything by the application
154
uint64 GetUserData() const { return mUserData; }
155
void SetUserData(uint64 inUserData) { mUserData = inUserData; }
156
157
/// Notify the constraint that the shape of a body has changed and that its center of mass has moved by inDeltaCOM.
158
/// Bodies don't know which constraints are connected to them so the user is responsible for notifying the relevant constraints when a body changes.
159
/// @param inBodyID ID of the body that has changed
160
/// @param inDeltaCOM The delta of the center of mass of the body (shape->GetCenterOfMass() - shape_before_change->GetCenterOfMass())
161
virtual void NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inDeltaCOM) = 0;
162
163
/// Notify the system that the configuration of the bodies and/or constraint has changed enough so that the warm start impulses should not be applied the next frame.
164
/// You can use this function for example when repositioning a ragdoll through Ragdoll::SetPose in such a way that the orientation of the bodies completely changes so that
165
/// the previous frame impulses are no longer a good approximation of what the impulses will be in the next frame. Calling this function when there are no big changes
166
/// will result in the constraints being much 'softer' than usual so they are more easily violated (e.g. a long chain of bodies might sag a bit if you call this every frame).
167
virtual void ResetWarmStart() = 0;
168
169
///@name Solver interface
170
///@{
171
virtual bool IsActive() const { return mEnabled; }
172
virtual void SetupVelocityConstraint(float inDeltaTime) = 0;
173
virtual void WarmStartVelocityConstraint(float inWarmStartImpulseRatio) = 0;
174
virtual bool SolveVelocityConstraint(float inDeltaTime) = 0;
175
virtual bool SolvePositionConstraint(float inDeltaTime, float inBaumgarte) = 0;
176
///@}
177
178
/// Link bodies that are connected by this constraint in the island builder
179
virtual void BuildIslands(uint32 inConstraintIndex, IslandBuilder &ioBuilder, BodyManager &inBodyManager) = 0;
180
181
/// Link bodies that are connected by this constraint in the same split. Returns the split index.
182
virtual uint BuildIslandSplits(LargeIslandSplitter &ioSplitter) const = 0;
183
184
#ifdef JPH_DEBUG_RENDERER
185
// Drawing interface
186
virtual void DrawConstraint(DebugRenderer *inRenderer) const = 0;
187
virtual void DrawConstraintLimits([[maybe_unused]] DebugRenderer *inRenderer) const { }
188
virtual void DrawConstraintReferenceFrame([[maybe_unused]] DebugRenderer *inRenderer) const { }
189
190
/// Size of constraint when drawing it through the debug renderer
191
float GetDrawConstraintSize() const { return mDrawConstraintSize; }
192
void SetDrawConstraintSize(float inSize) { mDrawConstraintSize = inSize; }
193
#endif // JPH_DEBUG_RENDERER
194
195
/// Saving state for replay
196
virtual void SaveState(StateRecorder &inStream) const;
197
198
/// Restoring state for replay
199
virtual void RestoreState(StateRecorder &inStream);
200
201
/// Debug function to convert a constraint to its settings, note that this will not save to which bodies the constraint is connected to
202
virtual Ref<ConstraintSettings> GetConstraintSettings() const = 0;
203
204
protected:
205
/// Helper function to copy settings back to constraint settings for this base class
206
void ToConstraintSettings(ConstraintSettings &outSettings) const;
207
208
#ifdef JPH_DEBUG_RENDERER
209
/// Size of constraint when drawing it through the debug renderer
210
float mDrawConstraintSize;
211
#endif // JPH_DEBUG_RENDERER
212
213
private:
214
friend class ConstraintManager;
215
216
/// Index that indicates this constraint is not in the constraint manager
217
static constexpr uint32 cInvalidConstraintIndex = 0xffffffff;
218
219
/// Index in the mConstraints list of the ConstraintManager for easy finding
220
uint32 mConstraintIndex = cInvalidConstraintIndex;
221
222
/// Priority of the constraint when solving. Higher numbers have are more likely to be solved correctly.
223
uint32 mConstraintPriority = 0;
224
225
/// Used only when the constraint is active. 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.
226
uint8 mNumVelocityStepsOverride = 0;
227
228
/// Used only when the constraint is active. 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.
229
uint8 mNumPositionStepsOverride = 0;
230
231
/// If this constraint is currently enabled
232
bool mEnabled = true;
233
234
/// User data value (can be used by application)
235
uint64 mUserData;
236
};
237
238
JPH_NAMESPACE_END
239
240