Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Constraints/PathConstraint.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/Physics/Constraints/TwoBodyConstraint.h>
8
#include <Jolt/Physics/Constraints/PathConstraintPath.h>
9
#include <Jolt/Physics/Constraints/MotorSettings.h>
10
#include <Jolt/Physics/Constraints/ConstraintPart/AxisConstraintPart.h>
11
#include <Jolt/Physics/Constraints/ConstraintPart/DualAxisConstraintPart.h>
12
#include <Jolt/Physics/Constraints/ConstraintPart/HingeRotationConstraintPart.h>
13
#include <Jolt/Physics/Constraints/ConstraintPart/RotationEulerConstraintPart.h>
14
15
JPH_NAMESPACE_BEGIN
16
17
JPH_SUPPRESS_WARNING_PUSH
18
JPH_GCC_SUPPRESS_WARNING("-Wshadow") // GCC complains about the 'Free' value conflicting with the 'Free' method
19
20
/// How to constrain the rotation of the body to a PathConstraint
21
enum class EPathRotationConstraintType
22
{
23
Free, ///< Do not constrain the rotation of the body at all
24
ConstrainAroundTangent, ///< Only allow rotation around the tangent vector (following the path)
25
ConstrainAroundNormal, ///< Only allow rotation around the normal vector (perpendicular to the path)
26
ConstrainAroundBinormal, ///< Only allow rotation around the binormal vector (perpendicular to the path)
27
ConstrainToPath, ///< Fully constrain the rotation of body 2 to the path (following the tangent and normal of the path)
28
FullyConstrained, ///< Fully constrain the rotation of the body 2 to the rotation of body 1
29
};
30
31
JPH_SUPPRESS_WARNING_POP
32
33
/// Path constraint settings, used to constrain the degrees of freedom between two bodies to a path
34
///
35
/// The requirements of the path are that:
36
/// * Tangent, normal and bi-normal form an orthonormal basis with: tangent cross bi-normal = normal
37
/// * The path points along the tangent vector
38
/// * The path is continuous so doesn't contain any sharp corners
39
///
40
/// The reason for all this is that the constraint acts like a slider constraint with the sliding axis being the tangent vector (the assumption here is that delta time will be small enough so that the path is linear for that delta time).
41
class JPH_EXPORT PathConstraintSettings final : public TwoBodyConstraintSettings
42
{
43
JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, PathConstraintSettings)
44
45
public:
46
// See: ConstraintSettings::SaveBinaryState
47
virtual void SaveBinaryState(StreamOut &inStream) const override;
48
49
/// Create an instance of this constraint
50
virtual TwoBodyConstraint * Create(Body &inBody1, Body &inBody2) const override;
51
52
/// The path that constrains the two bodies
53
RefConst<PathConstraintPath> mPath;
54
55
/// The position of the path start relative to world transform of body 1
56
Vec3 mPathPosition = Vec3::sZero();
57
58
/// The rotation of the path start relative to world transform of body 1
59
Quat mPathRotation = Quat::sIdentity();
60
61
/// The fraction along the path that corresponds to the initial position of body 2. Usually this is 0, the beginning of the path. But if you want to start an object halfway the path you can calculate this with mPath->GetClosestPoint(point on path to attach body to).
62
float mPathFraction = 0.0f;
63
64
/// Maximum amount of friction force to apply (N) when not driven by a motor.
65
float mMaxFrictionForce = 0.0f;
66
67
/// In case the constraint is powered, this determines the motor settings along the path
68
MotorSettings mPositionMotorSettings;
69
70
/// How to constrain the rotation of the body to the path
71
EPathRotationConstraintType mRotationConstraintType = EPathRotationConstraintType::Free;
72
73
protected:
74
// See: ConstraintSettings::RestoreBinaryState
75
virtual void RestoreBinaryState(StreamIn &inStream) override;
76
};
77
78
/// Path constraint, used to constrain the degrees of freedom between two bodies to a path
79
class JPH_EXPORT PathConstraint final : public TwoBodyConstraint
80
{
81
public:
82
JPH_OVERRIDE_NEW_DELETE
83
84
/// Construct point constraint
85
PathConstraint(Body &inBody1, Body &inBody2, const PathConstraintSettings &inSettings);
86
87
// Generic interface of a constraint
88
virtual EConstraintSubType GetSubType() const override { return EConstraintSubType::Path; }
89
virtual void NotifyShapeChanged(const BodyID &inBodyID, Vec3Arg inDeltaCOM) override;
90
virtual void SetupVelocityConstraint(float inDeltaTime) override;
91
virtual void ResetWarmStart() override;
92
virtual void WarmStartVelocityConstraint(float inWarmStartImpulseRatio) override;
93
virtual bool SolveVelocityConstraint(float inDeltaTime) override;
94
virtual bool SolvePositionConstraint(float inDeltaTime, float inBaumgarte) override;
95
#ifdef JPH_DEBUG_RENDERER
96
virtual void DrawConstraint(DebugRenderer *inRenderer) const override;
97
#endif // JPH_DEBUG_RENDERER
98
virtual void SaveState(StateRecorder &inStream) const override;
99
virtual void RestoreState(StateRecorder &inStream) override;
100
virtual bool IsActive() const override { return TwoBodyConstraint::IsActive() && mPath != nullptr; }
101
virtual Ref<ConstraintSettings> GetConstraintSettings() const override;
102
103
// See: TwoBodyConstraint
104
virtual Mat44 GetConstraintToBody1Matrix() const override { return mPathToBody1; }
105
virtual Mat44 GetConstraintToBody2Matrix() const override { return mPathToBody2; }
106
107
/// Update the path for this constraint
108
void SetPath(const PathConstraintPath *inPath, float inPathFraction);
109
110
/// Access to the current path
111
const PathConstraintPath * GetPath() const { return mPath; }
112
113
/// Access to the current fraction along the path e [0, GetPath()->GetMaxPathFraction()]
114
float GetPathFraction() const { return mPathFraction; }
115
116
/// Friction control
117
void SetMaxFrictionForce(float inFrictionForce) { mMaxFrictionForce = inFrictionForce; }
118
float GetMaxFrictionForce() const { return mMaxFrictionForce; }
119
120
/// Position motor settings
121
MotorSettings & GetPositionMotorSettings() { return mPositionMotorSettings; }
122
const MotorSettings & GetPositionMotorSettings() const { return mPositionMotorSettings; }
123
124
// Position motor controls (drives body 2 along the path)
125
void SetPositionMotorState(EMotorState inState) { JPH_ASSERT(inState == EMotorState::Off || mPositionMotorSettings.IsValid()); mPositionMotorState = inState; }
126
EMotorState GetPositionMotorState() const { return mPositionMotorState; }
127
void SetTargetVelocity(float inVelocity) { mTargetVelocity = inVelocity; }
128
float GetTargetVelocity() const { return mTargetVelocity; }
129
void SetTargetPathFraction(float inFraction) { JPH_ASSERT(mPath->IsLooping() || (inFraction >= 0.0f && inFraction <= mPath->GetPathMaxFraction())); mTargetPathFraction = inFraction; }
130
float GetTargetPathFraction() const { return mTargetPathFraction; }
131
132
///@name Get Lagrange multiplier from last physics update (the linear/angular impulse applied to satisfy the constraint)
133
inline Vector<2> GetTotalLambdaPosition() const { return mPositionConstraintPart.GetTotalLambda(); }
134
inline float GetTotalLambdaPositionLimits() const { return mPositionLimitsConstraintPart.GetTotalLambda(); }
135
inline float GetTotalLambdaMotor() const { return mPositionMotorConstraintPart.GetTotalLambda(); }
136
inline Vector<2> GetTotalLambdaRotationHinge() const { return mHingeConstraintPart.GetTotalLambda(); }
137
inline Vec3 GetTotalLambdaRotation() const { return mRotationConstraintPart.GetTotalLambda(); }
138
139
private:
140
// Internal helper function to calculate the values below
141
void CalculateConstraintProperties(float inDeltaTime);
142
143
// CONFIGURATION PROPERTIES FOLLOW
144
145
RefConst<PathConstraintPath> mPath; ///< The path that attaches the two bodies
146
Mat44 mPathToBody1; ///< Transform that takes a quantity from path space to body 1 center of mass space
147
Mat44 mPathToBody2; ///< Transform that takes a quantity from path space to body 2 center of mass space
148
EPathRotationConstraintType mRotationConstraintType; ///< How to constrain the rotation of the path
149
150
// Friction
151
float mMaxFrictionForce;
152
153
// Motor controls
154
MotorSettings mPositionMotorSettings;
155
EMotorState mPositionMotorState = EMotorState::Off;
156
float mTargetVelocity = 0.0f;
157
float mTargetPathFraction = 0.0f;
158
159
// RUN TIME PROPERTIES FOLLOW
160
161
// Positions where the point constraint acts on in world space
162
Vec3 mR1;
163
Vec3 mR2;
164
165
// X2 + R2 - X1 - R1
166
Vec3 mU;
167
168
// World space path tangent
169
Vec3 mPathTangent;
170
171
// Normals to the path tangent
172
Vec3 mPathNormal;
173
Vec3 mPathBinormal;
174
175
// Inverse of initial rotation from body 1 to body 2 in body 1 space (only used when rotation constraint type is FullyConstrained)
176
Quat mInvInitialOrientation;
177
178
// Current fraction along the path where body 2 is attached
179
float mPathFraction = 0.0f;
180
181
// Translation constraint parts
182
DualAxisConstraintPart mPositionConstraintPart; ///< Constraint part that keeps the movement along the tangent of the path
183
AxisConstraintPart mPositionLimitsConstraintPart; ///< Constraint part that prevents movement beyond the beginning and end of the path
184
AxisConstraintPart mPositionMotorConstraintPart; ///< Constraint to drive the object along the path or to apply friction
185
186
// Rotation constraint parts
187
HingeRotationConstraintPart mHingeConstraintPart; ///< Constraint part that removes 2 degrees of rotation freedom
188
RotationEulerConstraintPart mRotationConstraintPart; ///< Constraint part that removes all rotational freedom
189
};
190
191
JPH_NAMESPACE_END
192
193