Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodySharedSettings.h
21884 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#pragma once
6
7
#include <Jolt/Core/Reference.h>
8
#include <Jolt/Physics/Collision/PhysicsMaterial.h>
9
#include <Jolt/Core/StreamUtils.h>
10
11
JPH_NAMESPACE_BEGIN
12
13
/// This class defines the setup of all particles and their constraints.
14
/// It is used during the simulation and can be shared between multiple soft bodies.
15
class JPH_EXPORT SoftBodySharedSettings : public RefTarget<SoftBodySharedSettings>
16
{
17
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, SoftBodySharedSettings)
18
19
public:
20
/// Which type of bend constraint should be created
21
enum class EBendType
22
{
23
None, ///< No bend constraints will be created
24
Distance, ///< A simple distance constraint
25
Dihedral, ///< A dihedral bend constraint (most expensive, but also supports triangles that are initially not in the same plane)
26
};
27
28
/// The type of long range attachment constraint to create
29
enum class ELRAType
30
{
31
None, ///< Don't create a LRA constraint
32
EuclideanDistance, ///< Create a LRA constraint based on Euclidean distance between the closest kinematic vertex and this vertex
33
GeodesicDistance, ///< Create a LRA constraint based on the geodesic distance between the closest kinematic vertex and this vertex (follows the edge constraints)
34
};
35
36
/// Per vertex attributes used during the CreateConstraints function.
37
/// For an edge or shear constraint, the compliance is averaged between the two attached vertices.
38
/// For a bend constraint, the compliance is averaged between the two vertices on the shared edge.
39
struct JPH_EXPORT VertexAttributes
40
{
41
/// Constructor
42
VertexAttributes() = default;
43
VertexAttributes(float inCompliance, float inShearCompliance, float inBendCompliance, ELRAType inLRAType = ELRAType::None, float inLRAMaxDistanceMultiplier = 1.0f) : mCompliance(inCompliance), mShearCompliance(inShearCompliance), mBendCompliance(inBendCompliance), mLRAType(inLRAType), mLRAMaxDistanceMultiplier(inLRAMaxDistanceMultiplier) { }
44
45
float mCompliance = 0.0f; ///< The compliance of the normal edges. Set to FLT_MAX to disable regular edges for any edge involving this vertex.
46
float mShearCompliance = 0.0f; ///< The compliance of the shear edges. Set to FLT_MAX to disable shear edges for any edge involving this vertex.
47
float mBendCompliance = FLT_MAX; ///< The compliance of the bend edges. Set to FLT_MAX to disable bend edges for any bend constraint involving this vertex.
48
ELRAType mLRAType = ELRAType::None; ///< The type of long range attachment constraint to create.
49
float mLRAMaxDistanceMultiplier = 1.0f; ///< Multiplier for the max distance of the LRA constraint, e.g. 1.01 means the max distance is 1% longer than the calculated distance in the rest pose.
50
};
51
52
/// Automatically create constraints based on the faces of the soft body
53
/// @param inVertexAttributes A list of attributes for each vertex (1-on-1 with mVertices, note that if the list is smaller than mVertices the last element will be repeated). This defines the properties of the constraints that are created.
54
/// @param inVertexAttributesLength The length of inVertexAttributes
55
/// @param inBendType The type of bend constraint to create
56
/// @param inAngleTolerance Shear edges are created when two connected triangles form a quad (are roughly in the same plane and form a square with roughly 90 degree angles). This defines the tolerance (in radians).
57
void CreateConstraints(const VertexAttributes *inVertexAttributes, uint inVertexAttributesLength, EBendType inBendType = EBendType::Distance, float inAngleTolerance = DegreesToRadians(8.0f));
58
59
/// Calculate the initial lengths of all springs of the edges of this soft body (if you use CreateConstraint, this is already done)
60
void CalculateEdgeLengths();
61
62
/// Calculate the properties of the rods
63
/// Note that this can swap mVertex of the RodStretchShear constraints if two rods are connected through a RodBendTwist constraint but point in opposite directions.
64
void CalculateRodProperties();
65
66
/// Calculate the max lengths for the long range attachment constraints based on Euclidean distance (if you use CreateConstraints, this is already done)
67
/// @param inMaxDistanceMultiplier Multiplier for the max distance of the LRA constraint, e.g. 1.01 means the max distance is 1% longer than the calculated distance in the rest pose.
68
void CalculateLRALengths(float inMaxDistanceMultiplier = 1.0f);
69
70
/// Calculate the constants for the bend constraints (if you use CreateConstraints, this is already done)
71
void CalculateBendConstraintConstants();
72
73
/// Calculates the initial volume of all tetrahedra of this soft body
74
void CalculateVolumeConstraintVolumes();
75
76
/// Calculate information needed to be able to calculate the skinned constraint normals at run-time
77
void CalculateSkinnedConstraintNormals();
78
79
/// Information about the optimization of the soft body, the indices of certain elements may have changed.
80
class OptimizationResults
81
{
82
public:
83
Array<uint> mEdgeRemap; ///< Maps old edge index to new edge index
84
Array<uint> mLRARemap; ///< Maps old LRA index to new LRA index
85
Array<uint> mRodStretchShearConstraintRemap; ///< Maps old rod stretch shear constraint index to new stretch shear rod constraint index
86
Array<uint> mRodBendTwistConstraintRemap; ///< Maps old rod bend twist constraint index to new bend twist rod constraint index
87
Array<uint> mDihedralBendRemap; ///< Maps old dihedral bend index to new dihedral bend index
88
Array<uint> mVolumeRemap; ///< Maps old volume constraint index to new volume constraint index
89
Array<uint> mSkinnedRemap; ///< Maps old skinned constraint index to new skinned constraint index
90
};
91
92
/// Optimize the soft body settings for simulation. This will reorder constraints so they can be executed in parallel.
93
void Optimize(OptimizationResults &outResults);
94
95
/// Optimize the soft body settings without results
96
void Optimize() { OptimizationResults results; Optimize(results); }
97
98
/// Clone this object
99
Ref<SoftBodySharedSettings> Clone() const;
100
101
/// Saves the state of this object in binary form to inStream. Doesn't store the material list.
102
void SaveBinaryState(StreamOut &inStream) const;
103
104
/// Restore the state of this object from inStream. Doesn't restore the material list.
105
void RestoreBinaryState(StreamIn &inStream);
106
107
using SharedSettingsToIDMap = StreamUtils::ObjectToIDMap<SoftBodySharedSettings>;
108
using IDToSharedSettingsMap = StreamUtils::IDToObjectMap<SoftBodySharedSettings>;
109
using MaterialToIDMap = StreamUtils::ObjectToIDMap<PhysicsMaterial>;
110
using IDToMaterialMap = StreamUtils::IDToObjectMap<PhysicsMaterial>;
111
112
/// Save this shared settings and its materials. Pass in an empty map ioSettingsMap / ioMaterialMap or reuse the same map while saving multiple settings objects to the same stream in order to avoid writing duplicates.
113
void SaveWithMaterials(StreamOut &inStream, SharedSettingsToIDMap &ioSettingsMap, MaterialToIDMap &ioMaterialMap) const;
114
115
using SettingsResult = Result<Ref<SoftBodySharedSettings>>;
116
117
/// Restore a shape and materials. Pass in an empty map in ioSettingsMap / ioMaterialMap or reuse the same map while reading multiple settings objects from the same stream in order to restore duplicates.
118
static SettingsResult sRestoreWithMaterials(StreamIn &inStream, IDToSharedSettingsMap &ioSettingsMap, IDToMaterialMap &ioMaterialMap);
119
120
/// Create a cube. This can be used to create a simple soft body for testing purposes.
121
/// It will contain edge constraints, volume constraints and faces.
122
/// @param inGridSize Number of points along each axis
123
/// @param inGridSpacing Distance between points
124
static Ref<SoftBodySharedSettings> sCreateCube(uint inGridSize, float inGridSpacing);
125
126
/// A vertex is a particle, the data in this structure is only used during creation of the soft body and not during simulation
127
struct JPH_EXPORT Vertex
128
{
129
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, Vertex)
130
131
/// Constructor
132
Vertex() = default;
133
Vertex(const Float3 &inPosition, const Float3 &inVelocity = Float3(0, 0, 0), float inInvMass = 1.0f) : mPosition(inPosition), mVelocity(inVelocity), mInvMass(inInvMass) { }
134
135
Float3 mPosition { 0, 0, 0 }; ///< Initial position of the vertex
136
Float3 mVelocity { 0, 0, 0 }; ///< Initial velocity of the vertex
137
float mInvMass = 1.0f; ///< Initial inverse of the mass of the vertex
138
};
139
140
/// A face defines the surface of the body
141
struct JPH_EXPORT Face
142
{
143
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, Face)
144
145
/// Constructor
146
Face() = default;
147
Face(uint32 inVertex1, uint32 inVertex2, uint32 inVertex3, uint32 inMaterialIndex = 0) : mVertex { inVertex1, inVertex2, inVertex3 }, mMaterialIndex(inMaterialIndex) { }
148
149
/// Check if this is a degenerate face (a face which points to the same vertex twice)
150
bool IsDegenerate() const { return mVertex[0] == mVertex[1] || mVertex[0] == mVertex[2] || mVertex[1] == mVertex[2]; }
151
152
uint32 mVertex[3]; ///< Indices of the vertices that form the face
153
uint32 mMaterialIndex = 0; ///< Index of the material of the face in SoftBodySharedSettings::mMaterials
154
};
155
156
/// An edge keeps two vertices at a constant distance using a spring: |x1 - x2| = rest length
157
struct JPH_EXPORT Edge
158
{
159
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, Edge)
160
161
/// Constructor
162
Edge() = default;
163
Edge(uint32 inVertex1, uint32 inVertex2, float inCompliance = 0.0f) : mVertex { inVertex1, inVertex2 }, mCompliance(inCompliance) { }
164
165
/// Return the lowest vertex index of this constraint
166
uint32 GetMinVertexIndex() const { return min(mVertex[0], mVertex[1]); }
167
168
uint32 mVertex[2]; ///< Indices of the vertices that form the edge
169
float mRestLength = 1.0f; ///< Rest length of the spring, calculated by CalculateEdgeLengths
170
float mCompliance = 0.0f; ///< Inverse of the stiffness of the spring
171
};
172
173
/**
174
* A dihedral bend constraint keeps the angle between two triangles constant along their shared edge.
175
*
176
* x2
177
* / \
178
* / t0 \
179
* x0----x1
180
* \ t1 /
181
* \ /
182
* x3
183
*
184
* x0..x3 are the vertices, t0 and t1 are the triangles that share the edge x0..x1
185
*
186
* Based on:
187
* - "Position Based Dynamics" - Matthias Muller et al.
188
* - "Strain Based Dynamics" - Matthias Muller et al.
189
* - "Simulation of Clothing with Folds and Wrinkles" - R. Bridson et al.
190
*/
191
struct JPH_EXPORT DihedralBend
192
{
193
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, DihedralBend)
194
195
/// Constructor
196
DihedralBend() = default;
197
DihedralBend(uint32 inVertex1, uint32 inVertex2, uint32 inVertex3, uint32 inVertex4, float inCompliance = 0.0f) : mVertex { inVertex1, inVertex2, inVertex3, inVertex4 }, mCompliance(inCompliance) { }
198
199
/// Return the lowest vertex index of this constraint
200
uint32 GetMinVertexIndex() const { return min(min(mVertex[0], mVertex[1]), min(mVertex[2], mVertex[3])); }
201
202
uint32 mVertex[4]; ///< Indices of the vertices of the 2 triangles that share an edge (the first 2 vertices are the shared edge)
203
float mCompliance = 0.0f; ///< Inverse of the stiffness of the constraint
204
float mInitialAngle = 0.0f; ///< Initial angle between the normals of the triangles (pi - dihedral angle), calculated by CalculateBendConstraintConstants
205
};
206
207
/// Volume constraint, keeps the volume of a tetrahedron constant
208
struct JPH_EXPORT Volume
209
{
210
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, Volume)
211
212
/// Constructor
213
Volume() = default;
214
Volume(uint32 inVertex1, uint32 inVertex2, uint32 inVertex3, uint32 inVertex4, float inCompliance = 0.0f) : mVertex { inVertex1, inVertex2, inVertex3, inVertex4 }, mCompliance(inCompliance) { }
215
216
/// Return the lowest vertex index of this constraint
217
uint32 GetMinVertexIndex() const { return min(min(mVertex[0], mVertex[1]), min(mVertex[2], mVertex[3])); }
218
219
uint32 mVertex[4]; ///< Indices of the vertices that form the tetrahedron
220
float mSixRestVolume = 1.0f; ///< 6 times the rest volume of the tetrahedron, calculated by CalculateVolumeConstraintVolumes
221
float mCompliance = 0.0f; ///< Inverse of the stiffness of the constraint
222
};
223
224
/// An inverse bind matrix take a skinned vertex from its bind pose into joint local space
225
class JPH_EXPORT InvBind
226
{
227
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, InvBind)
228
229
public:
230
/// Constructor
231
InvBind() = default;
232
InvBind(uint32 inJointIndex, Mat44Arg inInvBind) : mJointIndex(inJointIndex), mInvBind(inInvBind) { }
233
234
uint32 mJointIndex = 0; ///< Joint index to which this is attached
235
Mat44 mInvBind = Mat44::sIdentity(); ///< The inverse bind matrix, this takes a vertex in its bind pose (Vertex::mPosition) to joint local space
236
};
237
238
/// A joint and its skin weight
239
class JPH_EXPORT SkinWeight
240
{
241
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, SkinWeight)
242
243
public:
244
/// Constructor
245
SkinWeight() = default;
246
SkinWeight(uint32 inInvBindIndex, float inWeight) : mInvBindIndex(inInvBindIndex), mWeight(inWeight) { }
247
248
uint32 mInvBindIndex = 0; ///< Index in mInvBindMatrices
249
float mWeight = 0.0f; ///< Weight with which it is skinned
250
};
251
252
/// A constraint that skins a vertex to joints and limits the distance that the simulated vertex can travel from this vertex
253
class JPH_EXPORT Skinned
254
{
255
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, Skinned)
256
257
public:
258
/// Constructor
259
Skinned() = default;
260
Skinned(uint32 inVertex, float inMaxDistance, float inBackStopDistance, float inBackStopRadius) : mVertex(inVertex), mMaxDistance(inMaxDistance), mBackStopDistance(inBackStopDistance), mBackStopRadius(inBackStopRadius) { }
261
262
/// Normalize the weights so that they add up to 1
263
void NormalizeWeights()
264
{
265
// Get the total weight
266
float total = 0.0f;
267
for (const SkinWeight &w : mWeights)
268
total += w.mWeight;
269
270
// Normalize
271
if (total > 0.0f)
272
for (SkinWeight &w : mWeights)
273
w.mWeight /= total;
274
}
275
276
/// Maximum number of skin weights
277
static constexpr uint cMaxSkinWeights = 4;
278
279
uint32 mVertex = 0; ///< Index in mVertices which indicates which vertex is being skinned
280
SkinWeight mWeights[cMaxSkinWeights]; ///< Skin weights, the bind pose of the vertex is assumed to be stored in Vertex::mPosition. The first weight that is zero indicates the end of the list. Weights should add up to 1.
281
float mMaxDistance = FLT_MAX; ///< Maximum distance that this vertex can reach from the skinned vertex, disabled when FLT_MAX. 0 when you want to hard skin the vertex to the skinned vertex.
282
float mBackStopDistance = FLT_MAX; ///< Disabled if mBackStopDistance >= mMaxDistance. The faces surrounding mVertex determine an average normal. mBackStopDistance behind the vertex in the opposite direction of this normal, the back stop sphere starts. The simulated vertex will be pushed out of this sphere and it can be used to approximate the volume of the skinned mesh behind the skinned vertex.
283
float mBackStopRadius = 40.0f; ///< Radius of the backstop sphere. By default this is a fairly large radius so the sphere approximates a plane.
284
uint32 mNormalInfo = 0; ///< Information needed to calculate the normal of this vertex, lowest 24 bit is start index in mSkinnedConstraintNormals, highest 8 bit is number of faces (generated by CalculateSkinnedConstraintNormals)
285
};
286
287
/// A long range attachment constraint, this is a constraint that sets a max distance between a kinematic vertex and a dynamic vertex
288
/// See: "Long Range Attachments - A Method to Simulate Inextensible Clothing in Computer Games", Tae-Yong Kim, Nuttapong Chentanez and Matthias Mueller-Fischer
289
class JPH_EXPORT LRA
290
{
291
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, LRA)
292
293
public:
294
/// Constructor
295
LRA() = default;
296
LRA(uint32 inVertex1, uint32 inVertex2, float inMaxDistance) : mVertex { inVertex1, inVertex2 }, mMaxDistance(inMaxDistance) { }
297
298
/// Return the lowest vertex index of this constraint
299
uint32 GetMinVertexIndex() const { return min(mVertex[0], mVertex[1]); }
300
301
uint32 mVertex[2]; ///< The vertices that are connected. The first vertex should be kinematic, the 2nd dynamic.
302
float mMaxDistance = 0.0f; ///< The maximum distance between the vertices, calculated by CalculateLRALengths
303
};
304
305
/// A discrete Cosserat rod connects two particles with a rigid rod that has fixed length and inertia.
306
/// A rod can be used instead of an Edge to constraint two vertices. The orientation of the rod can be
307
/// used to orient geometry attached to the rod (e.g. a plant leaf). Note that each rod needs to be constrained
308
/// by at least one RodBendTwist constraint in order to constrain the rotation of the rod. If you don't do
309
/// this then the orientation is likely to rotate around the rod axis with constant velocity.
310
/// Based on "Position and Orientation Based Cosserat Rods" - Kugelstadt and Schoemer - SIGGRAPH 2016
311
/// See: https://www.researchgate.net/publication/325597548_Position_and_Orientation_Based_Cosserat_Rods
312
struct JPH_EXPORT RodStretchShear
313
{
314
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, RodStretchShear)
315
316
/// Constructor
317
RodStretchShear() = default;
318
RodStretchShear(uint32 inVertex1, uint32 inVertex2, float inCompliance = 0.0f) : mVertex { inVertex1, inVertex2 }, mCompliance(inCompliance) { }
319
320
/// Return the lowest vertex index of this constraint
321
uint32 GetMinVertexIndex() const { return min(mVertex[0], mVertex[1]); }
322
323
uint32 mVertex[2]; ///< Indices of the vertices that form the rod
324
float mLength = 1.0f; ///< Fixed length of the rod, calculated by CalculateRodProperties
325
float mInvMass = 1.0f; ///< Inverse of the mass of the rod (0 for static rods), calculated by CalculateRodProperties but can be overridden afterwards
326
float mCompliance = 0.0f; ///< Inverse of the stiffness of the rod
327
Quat mBishop = Quat::sZero(); ///< The Bishop frame of the rod (the rotation of the rod in its rest pose so that it has zero twist towards adjacent rods), calculated by CalculateRodProperties
328
};
329
330
/// A constraint that connects two Cosserat rods and limits bend and twist between the rods.
331
struct JPH_EXPORT RodBendTwist
332
{
333
JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(JPH_EXPORT, RodBendTwist)
334
335
/// Constructor
336
RodBendTwist() = default;
337
RodBendTwist(uint32 inRod1, uint32 inRod2, float inCompliance = 0.0f) : mRod { inRod1, inRod2 }, mCompliance(inCompliance) { }
338
339
uint32 mRod[2]; ///< Indices of rods that are constrained (index in mRodStretchShearConstraints)
340
float mCompliance = 0.0f; ///< Inverse of the stiffness of the rod
341
Quat mOmega0 = Quat::sZero(); ///< The initial rotation between the rods: rod1.mBishop.Conjugated() * rod2.mBishop, calculated by CalculateRodProperties
342
};
343
344
/// Add a face to this soft body
345
void AddFace(const Face &inFace) { JPH_ASSERT(!inFace.IsDegenerate()); mFaces.push_back(inFace); }
346
347
Array<Vertex> mVertices; ///< The list of vertices or particles of the body
348
Array<Face> mFaces; ///< The list of faces of the body
349
Array<Edge> mEdgeConstraints; ///< The list of edges or springs of the body
350
Array<DihedralBend> mDihedralBendConstraints; ///< The list of dihedral bend constraints of the body
351
Array<Volume> mVolumeConstraints; ///< The list of volume constraints of the body that keep the volume of tetrahedra in the soft body constant
352
Array<Skinned> mSkinnedConstraints; ///< The list of vertices that are constrained to a skinned vertex
353
Array<InvBind> mInvBindMatrices; ///< The list of inverse bind matrices for skinning vertices
354
Array<LRA> mLRAConstraints; ///< The list of long range attachment constraints
355
Array<RodStretchShear> mRodStretchShearConstraints; ///< The list of Cosserat rod constraints that connect two vertices and that limit stretch and shear
356
Array<RodBendTwist> mRodBendTwistConstraints; ///< The list of Cosserat rod constraints that connect two rods and limit the bend and twist
357
PhysicsMaterialList mMaterials { PhysicsMaterial::sDefault }; ///< The materials of the faces of the body, referenced by Face::mMaterialIndex
358
359
private:
360
friend class SoftBodyMotionProperties;
361
362
/// Calculate the closest kinematic vertex array
363
void CalculateClosestKinematic();
364
365
/// Tracks the closest kinematic vertex
366
struct ClosestKinematic
367
{
368
uint32 mVertex = 0xffffffff; ///< Vertex index of closest kinematic vertex
369
uint32 mHops = 0xffffffff; ///< Number of hops to the closest kinematic vertex
370
float mDistance = FLT_MAX; ///< Distance to the closest kinematic vertex
371
};
372
373
/// Tracks the end indices of the various constraint groups
374
struct UpdateGroup
375
{
376
uint mEdgeEndIndex; ///< The end index of the edge constraints in this group
377
uint mLRAEndIndex; ///< The end index of the LRA constraints in this group
378
uint mRodStretchShearEndIndex; ///< The end index of the rod stretch shear constraints in this group
379
uint mRodBendTwistEndIndex; ///< The end index of the rod bend twist constraints in this group
380
uint mDihedralBendEndIndex; ///< The end index of the dihedral bend constraints in this group
381
uint mVolumeEndIndex; ///< The end index of the volume constraints in this group
382
uint mSkinnedEndIndex; ///< The end index of the skinned constraints in this group
383
};
384
385
Array<ClosestKinematic> mClosestKinematic; ///< The closest kinematic vertex to each vertex in mVertices
386
Array<UpdateGroup> mUpdateGroups; ///< The end indices for each group of constraints that can be updated in parallel
387
Array<uint32> mSkinnedConstraintNormals; ///< A list of indices in the mFaces array used by mSkinnedConstraints, calculated by CalculateSkinnedConstraintNormals
388
};
389
390
JPH_NAMESPACE_END
391
392