Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Ragdoll/Ragdoll.h
22800 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/Result.h>
9
#include <Jolt/Physics/Body/BodyCreationSettings.h>
10
#include <Jolt/Physics/Constraints/TwoBodyConstraint.h>
11
#include <Jolt/Skeleton/Skeleton.h>
12
#include <Jolt/Skeleton/SkeletonPose.h>
13
#include <Jolt/Physics/EActivation.h>
14
15
JPH_NAMESPACE_BEGIN
16
17
class Ragdoll;
18
class PhysicsSystem;
19
20
/// Contains the structure of a ragdoll
21
class JPH_EXPORT RagdollSettings : public RefTarget<RagdollSettings>
22
{
23
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, RagdollSettings)
24
25
public:
26
/// Stabilize the constraints of the ragdoll
27
/// @return True on success, false on failure.
28
bool Stabilize();
29
30
/// Initializes the constraint priorities so that constraints near the leaves of the ragdoll have a lower priority
31
/// than constraints near the root of the ragdoll.
32
/// @param inBasePriority The lowest priority that will be used in the ragdoll.
33
void CalculateConstraintPriorities(uint32 inBasePriority = 0);
34
35
/// After the ragdoll has been fully configured, call this function to automatically create and add a GroupFilterTable collision filter to all bodies
36
/// and configure them so that parent and children don't collide.
37
///
38
/// This will:
39
/// - Create a GroupFilterTable and assign it to all of the bodies in a ragdoll.
40
/// - Each body in your ragdoll will get a SubGroupID that is equal to the joint index in the Skeleton that it is attached to.
41
/// - Loop over all joints in the Skeleton and call GroupFilterTable::DisableCollision(joint index, parent joint index).
42
/// - When a pose is provided through inJointMatrices the function will detect collisions between joints
43
/// (they must be separated by more than inMinSeparationDistance to be treated as not colliding) and automatically disable collisions.
44
///
45
/// When you create an instance using Ragdoll::CreateRagdoll pass in a unique GroupID for each ragdoll (e.g. a simple counter), note that this number
46
/// should be unique throughout the PhysicsSystem, so if you have different types of ragdolls they should not share the same GroupID.
47
void DisableParentChildCollisions(const Mat44 *inJointMatrices = nullptr, float inMinSeparationDistance = 0.0f);
48
49
/// Saves the state of this object in binary form to inStream.
50
/// @param inStream The stream to save the state to
51
/// @param inSaveShapes If the shapes should be saved as well (these could be shared between ragdolls, in which case the calling application may want to write custom code to restore them)
52
/// @param inSaveGroupFilter If the group filter should be saved as well (these could be shared)
53
void SaveBinaryState(StreamOut &inStream, bool inSaveShapes, bool inSaveGroupFilter) const;
54
55
using RagdollResult = Result<Ref<RagdollSettings>>;
56
57
/// Restore a saved ragdoll from inStream
58
static RagdollResult sRestoreFromBinaryState(StreamIn &inStream);
59
60
/// Create ragdoll instance from these settings
61
/// @return Newly created ragdoll or null when out of bodies
62
Ragdoll * CreateRagdoll(CollisionGroup::GroupID inCollisionGroup, uint64 inUserData, PhysicsSystem *inSystem) const;
63
64
/// Access to the skeleton of this ragdoll
65
const Skeleton * GetSkeleton() const { return mSkeleton; }
66
Skeleton * GetSkeleton() { return mSkeleton; }
67
68
/// Calculate the map needed for GetBodyIndexToConstraintIndex()
69
void CalculateBodyIndexToConstraintIndex();
70
71
/// Get table that maps a body index to the constraint index with which it is connected to its parent. -1 if there is no constraint associated with the body.
72
/// Note that this will only tell you which constraint connects the body to its parent, it will not look in the additional constraint list.
73
const Array<int> & GetBodyIndexToConstraintIndex() const { return mBodyIndexToConstraintIndex; }
74
75
/// Map a single body index to a constraint index
76
int GetConstraintIndexForBodyIndex(int inBodyIndex) const { return mBodyIndexToConstraintIndex[inBodyIndex]; }
77
78
/// Calculate the map needed for GetConstraintIndexToBodyIdxPair()
79
void CalculateConstraintIndexToBodyIdxPair();
80
81
using BodyIdxPair = std::pair<int, int>;
82
83
/// Table that maps a constraint index (index in mConstraints) to the indices of the bodies that the constraint is connected to (index in mBodyIDs)
84
const Array<BodyIdxPair> & GetConstraintIndexToBodyIdxPair() const { return mConstraintIndexToBodyIdxPair; }
85
86
/// Map a single constraint index (index in mConstraints) to the indices of the bodies that the constraint is connected to (index in mBodyIDs)
87
BodyIdxPair GetBodyIndicesForConstraintIndex(int inConstraintIndex) const { return mConstraintIndexToBodyIdxPair[inConstraintIndex]; }
88
89
/// A single rigid body sub part of the ragdoll
90
class Part : public BodyCreationSettings
91
{
92
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, Part)
93
94
public:
95
Ref<TwoBodyConstraintSettings> mToParent;
96
};
97
98
/// List of ragdoll parts
99
using PartVector = Array<Part>; ///< The constraint that connects this part to its parent part (should be null for the root)
100
101
/// A constraint that connects two bodies in a ragdoll (for non parent child related constraints)
102
class AdditionalConstraint
103
{
104
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, AdditionalConstraint)
105
106
public:
107
/// Constructors
108
AdditionalConstraint() = default;
109
AdditionalConstraint(int inBodyIdx1, int inBodyIdx2, TwoBodyConstraintSettings *inConstraint) : mBodyIdx { inBodyIdx1, inBodyIdx2 }, mConstraint(inConstraint) { }
110
111
int mBodyIdx[2]; ///< Indices of the bodies that this constraint connects
112
Ref<TwoBodyConstraintSettings> mConstraint; ///< The constraint that connects these bodies
113
};
114
115
/// List of additional constraints
116
using AdditionalConstraintVector = Array<AdditionalConstraint>;
117
118
/// The skeleton for this ragdoll
119
Ref<Skeleton> mSkeleton;
120
121
/// For each of the joints, the body and constraint attaching it to its parent body (1-on-1 with mSkeleton.GetJoints())
122
PartVector mParts;
123
124
/// A list of constraints that connects two bodies in a ragdoll (for non parent child related constraints)
125
AdditionalConstraintVector mAdditionalConstraints;
126
127
private:
128
/// Table that maps a body index (index in mBodyIDs) to the constraint index with which it is connected to its parent. -1 if there is no constraint associated with the body.
129
Array<int> mBodyIndexToConstraintIndex;
130
131
/// Table that maps a constraint index (index in mConstraints) to the indices of the bodies that the constraint is connected to (index in mBodyIDs)
132
Array<BodyIdxPair> mConstraintIndexToBodyIdxPair;
133
};
134
135
/// Runtime ragdoll information
136
class JPH_EXPORT Ragdoll : public RefTarget<Ragdoll>, public NonCopyable
137
{
138
public:
139
JPH_OVERRIDE_NEW_DELETE
140
141
/// Constructor
142
explicit Ragdoll(PhysicsSystem *inSystem) : mSystem(inSystem) { }
143
144
/// Destructor
145
~Ragdoll();
146
147
/// Add bodies and constraints to the system and optionally activate the bodies
148
void AddToPhysicsSystem(EActivation inActivationMode, bool inLockBodies = true);
149
150
/// Remove bodies and constraints from the system
151
void RemoveFromPhysicsSystem(bool inLockBodies = true);
152
153
/// Wake up all bodies in the ragdoll
154
void Activate(bool inLockBodies = true);
155
156
/// Check if one or more of the bodies in the ragdoll are active.
157
/// Note that this involves locking the bodies (if inLockBodies is true) and looping over them. An alternative and possibly faster
158
/// way could be to install a BodyActivationListener and count the number of active bodies of a ragdoll as they're activated / deactivated
159
/// (basically check if the body that activates / deactivates is in GetBodyIDs() and increment / decrement a counter).
160
bool IsActive(bool inLockBodies = true) const;
161
162
/// Set the group ID on all bodies in the ragdoll
163
void SetGroupID(CollisionGroup::GroupID inGroupID, bool inLockBodies = true);
164
165
/// Set the ragdoll to a pose (calls BodyInterface::SetPositionAndRotation to instantly move the ragdoll)
166
void SetPose(const SkeletonPose &inPose, bool inLockBodies = true);
167
168
/// Lower level version of SetPose that directly takes the world space joint matrices
169
void SetPose(RVec3Arg inRootOffset, const Mat44 *inJointMatrices, bool inLockBodies = true);
170
171
/// Get the ragdoll pose (uses the world transform of the bodies to calculate the pose)
172
void GetPose(SkeletonPose &outPose, bool inLockBodies = true);
173
174
/// Lower level version of GetPose that directly returns the world space joint matrices
175
void GetPose(RVec3 &outRootOffset, Mat44 *outJointMatrices, bool inLockBodies = true);
176
177
/// This function calls ResetWarmStart on all constraints. It can be used after calling SetPose to reset previous frames impulses. See: Constraint::ResetWarmStart.
178
void ResetWarmStart();
179
180
/// Drive the ragdoll to a specific pose by setting velocities on each of the bodies so that it will reach inPose in inDeltaTime
181
void DriveToPoseUsingKinematics(const SkeletonPose &inPose, float inDeltaTime, bool inLockBodies = true);
182
183
/// Lower level version of DriveToPoseUsingKinematics that directly takes the world space joint matrices
184
void DriveToPoseUsingKinematics(RVec3Arg inRootOffset, const Mat44 *inJointMatrices, float inDeltaTime, bool inLockBodies = true);
185
186
/// Drive the ragdoll to a specific pose by activating the motors on each constraint
187
void DriveToPoseUsingMotors(const SkeletonPose &inPose);
188
189
/// Control the linear and velocity of all bodies in the ragdoll
190
void SetLinearAndAngularVelocity(Vec3Arg inLinearVelocity, Vec3Arg inAngularVelocity, bool inLockBodies = true);
191
192
/// Set the world space linear velocity of all bodies in the ragdoll.
193
void SetLinearVelocity(Vec3Arg inLinearVelocity, bool inLockBodies = true);
194
195
/// Add a world space velocity (in m/s) to all bodies in the ragdoll.
196
void AddLinearVelocity(Vec3Arg inLinearVelocity, bool inLockBodies = true);
197
198
/// Add impulse to all bodies of the ragdoll (center of mass of each of them)
199
void AddImpulse(Vec3Arg inImpulse, bool inLockBodies = true);
200
201
/// Get the position and orientation of the root of the ragdoll
202
void GetRootTransform(RVec3 &outPosition, Quat &outRotation, bool inLockBodies = true) const;
203
204
/// Get number of bodies in the ragdoll
205
size_t GetBodyCount() const { return mBodyIDs.size(); }
206
207
/// Access a body ID
208
BodyID GetBodyID(int inBodyIndex) const { return mBodyIDs[inBodyIndex]; }
209
210
/// Access to the array of body IDs
211
const Array<BodyID> & GetBodyIDs() const { return mBodyIDs; }
212
213
/// Get number of constraints in the ragdoll
214
size_t GetConstraintCount() const { return mConstraints.size(); }
215
216
/// Access a constraint by index
217
TwoBodyConstraint * GetConstraint(int inConstraintIndex) { return mConstraints[inConstraintIndex]; }
218
219
/// Access a constraint by index
220
const TwoBodyConstraint * GetConstraint(int inConstraintIndex) const { return mConstraints[inConstraintIndex]; }
221
222
/// Get world space bounding box for all bodies of the ragdoll
223
AABox GetWorldSpaceBounds(bool inLockBodies = true) const;
224
225
/// Get the settings object that created this ragdoll
226
const RagdollSettings * GetRagdollSettings() const { return mRagdollSettings; }
227
228
private:
229
/// For RagdollSettings::CreateRagdoll function
230
friend class RagdollSettings;
231
232
/// The settings that created this ragdoll
233
RefConst<RagdollSettings> mRagdollSettings;
234
235
/// The bodies and constraints that this ragdoll consists of (1-on-1 with mRagdollSettings->mParts)
236
Array<BodyID> mBodyIDs;
237
238
/// Array of constraints that connect the bodies together
239
Array<Ref<TwoBodyConstraint>> mConstraints;
240
241
/// Cached physics system
242
PhysicsSystem * mSystem;
243
};
244
245
JPH_NAMESPACE_END
246
247