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
22061 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
/// Don't allow (copy) constructing this base class, but allow derived classes to (copy) construct themselves
98
ConstraintSettings() = default;
99
ConstraintSettings(const ConstraintSettings &) = default;
100
ConstraintSettings & operator = (const ConstraintSettings &) = default;
101
102
/// This function should not be called directly, it is used by sRestoreFromBinaryState.
103
virtual void RestoreBinaryState(StreamIn &inStream);
104
};
105
106
/// Base class for all physics constraints. A constraint removes one or more degrees of freedom for a rigid body.
107
class JPH_EXPORT Constraint : public RefTarget<Constraint>, public NonCopyable
108
{
109
public:
110
JPH_OVERRIDE_NEW_DELETE
111
112
/// Constructor
113
explicit Constraint(const ConstraintSettings &inSettings) :
114
#ifdef JPH_DEBUG_RENDERER
115
mDrawConstraintSize(inSettings.mDrawConstraintSize),
116
#endif // JPH_DEBUG_RENDERER
117
mConstraintPriority(inSettings.mConstraintPriority),
118
mNumVelocityStepsOverride(uint8(inSettings.mNumVelocityStepsOverride)),
119
mNumPositionStepsOverride(uint8(inSettings.mNumPositionStepsOverride)),
120
mEnabled(inSettings.mEnabled),
121
mUserData(inSettings.mUserData)
122
{
123
JPH_ASSERT(inSettings.mNumVelocityStepsOverride < 256);
124
JPH_ASSERT(inSettings.mNumPositionStepsOverride < 256);
125
}
126
127
/// Virtual destructor
128
virtual ~Constraint() = default;
129
130
/// Get the type of a constraint
131
virtual EConstraintType GetType() const { return EConstraintType::Constraint; }
132
133
/// Get the sub type of a constraint
134
virtual EConstraintSubType GetSubType() const = 0;
135
136
/// Priority of the constraint when solving. Higher numbers have are more likely to be solved correctly.
137
/// 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.
138
uint32 GetConstraintPriority() const { return mConstraintPriority; }
139
void SetConstraintPriority(uint32 inPriority) { mConstraintPriority = inPriority; }
140
141
/// 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.
142
void SetNumVelocityStepsOverride(uint inN) { JPH_ASSERT(inN < 256); mNumVelocityStepsOverride = uint8(inN); }
143
uint GetNumVelocityStepsOverride() const { return mNumVelocityStepsOverride; }
144
145
/// 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.
146
void SetNumPositionStepsOverride(uint inN) { JPH_ASSERT(inN < 256); mNumPositionStepsOverride = uint8(inN); }
147
uint GetNumPositionStepsOverride() const { return mNumPositionStepsOverride; }
148
149
/// Enable / disable this constraint. This can e.g. be used to implement a breakable constraint by detecting that the constraint impulse
150
/// (see e.g. PointConstraint::GetTotalLambdaPosition) went over a certain limit and then disabling the constraint.
151
/// Note that although a disabled constraint will not affect the simulation in any way anymore, it does incur some processing overhead.
152
/// 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).
153
void SetEnabled(bool inEnabled) { mEnabled = inEnabled; }
154
155
/// Test if a constraint is enabled.
156
bool GetEnabled() const { return mEnabled; }
157
158
/// Access to the user data, can be used for anything by the application
159
uint64 GetUserData() const { return mUserData; }
160
void SetUserData(uint64 inUserData) { mUserData = inUserData; }
161
162
/// Notify the constraint that the shape of a body has changed and that its center of mass has moved by inDeltaCOM.
163
/// Bodies don't know which constraints are connected to them so the user is responsible for notifying the relevant constraints when a body changes.
164
/// @param inBodyID ID of the body that has changed
165
/// @param inDeltaCOM The delta of the center of mass of the body (shape->GetCenterOfMass() - shape_before_change->GetCenterOfMass())
166
virtual void NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inDeltaCOM) = 0;
167
168
/// 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.
169
/// 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
170
/// 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
171
/// 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).
172
virtual void ResetWarmStart() = 0;
173
174
///@name Solver interface
175
///@{
176
virtual bool IsActive() const { return mEnabled; }
177
virtual void SetupVelocityConstraint(float inDeltaTime) = 0;
178
virtual void WarmStartVelocityConstraint(float inWarmStartImpulseRatio) = 0;
179
virtual bool SolveVelocityConstraint(float inDeltaTime) = 0;
180
virtual bool SolvePositionConstraint(float inDeltaTime, float inBaumgarte) = 0;
181
///@}
182
183
/// Link bodies that are connected by this constraint in the island builder
184
virtual void BuildIslands(uint32 inConstraintIndex, IslandBuilder &ioBuilder, BodyManager &inBodyManager) = 0;
185
186
/// Link bodies that are connected by this constraint in the same split. Returns the split index.
187
virtual uint BuildIslandSplits(LargeIslandSplitter &ioSplitter) const = 0;
188
189
#ifdef JPH_DEBUG_RENDERER
190
// Drawing interface
191
virtual void DrawConstraint(DebugRenderer *inRenderer) const = 0;
192
virtual void DrawConstraintLimits([[maybe_unused]] DebugRenderer *inRenderer) const { }
193
virtual void DrawConstraintReferenceFrame([[maybe_unused]] DebugRenderer *inRenderer) const { }
194
195
/// Size of constraint when drawing it through the debug renderer
196
float GetDrawConstraintSize() const { return mDrawConstraintSize; }
197
void SetDrawConstraintSize(float inSize) { mDrawConstraintSize = inSize; }
198
#endif // JPH_DEBUG_RENDERER
199
200
/// Saving state for replay
201
virtual void SaveState(StateRecorder &inStream) const;
202
203
/// Restoring state for replay
204
virtual void RestoreState(StateRecorder &inStream);
205
206
/// Debug function to convert a constraint to its settings, note that this will not save to which bodies the constraint is connected to
207
virtual Ref<ConstraintSettings> GetConstraintSettings() const = 0;
208
209
protected:
210
/// Helper function to copy settings back to constraint settings for this base class
211
void ToConstraintSettings(ConstraintSettings &outSettings) const;
212
213
#ifdef JPH_DEBUG_RENDERER
214
/// Size of constraint when drawing it through the debug renderer
215
float mDrawConstraintSize;
216
#endif // JPH_DEBUG_RENDERER
217
218
private:
219
friend class ConstraintManager;
220
221
/// Index that indicates this constraint is not in the constraint manager
222
static constexpr uint32 cInvalidConstraintIndex = 0xffffffff;
223
224
/// Index in the mConstraints list of the ConstraintManager for easy finding
225
uint32 mConstraintIndex = cInvalidConstraintIndex;
226
227
/// Priority of the constraint when solving. Higher numbers have are more likely to be solved correctly.
228
uint32 mConstraintPriority = 0;
229
230
/// 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.
231
uint8 mNumVelocityStepsOverride = 0;
232
233
/// 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.
234
uint8 mNumPositionStepsOverride = 0;
235
236
/// If this constraint is currently enabled
237
bool mEnabled = true;
238
239
/// User data value (can be used by application)
240
uint64 mUserData;
241
};
242
243
JPH_NAMESPACE_END
244
245