Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyShape.cpp
21350 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#include <Jolt/Jolt.h>
6
7
#include <Jolt/Physics/SoftBody/SoftBodyShape.h>
8
#include <Jolt/Core/Profiler.h>
9
#include <Jolt/Geometry/RayTriangle.h>
10
#include <Jolt/Physics/Collision/RayCast.h>
11
#include <Jolt/Physics/Collision/CastResult.h>
12
#include <Jolt/Physics/Collision/TransformedShape.h>
13
#include <Jolt/Physics/SoftBody/SoftBodyMotionProperties.h>
14
#include <Jolt/Physics/Collision/CastConvexVsTriangles.h>
15
#include <Jolt/Physics/Collision/CastSphereVsTriangles.h>
16
#include <Jolt/Physics/Collision/CollideConvexVsTriangles.h>
17
#include <Jolt/Physics/Collision/CollideSphereVsTriangles.h>
18
#include <Jolt/Physics/Collision/CollisionDispatch.h>
19
#ifdef JPH_DEBUG_RENDERER
20
#include <Jolt/Renderer/DebugRenderer.h>
21
#endif // JPH_DEBUG_RENDERER
22
23
JPH_NAMESPACE_BEGIN
24
25
uint SoftBodyShape::GetSubShapeIDBits() const
26
{
27
// Ensure we have enough bits to encode our shape [0, n - 1]
28
uint32 n = (uint32)mSoftBodyMotionProperties->GetFaces().size() - 1;
29
return 32 - CountLeadingZeros(n);
30
}
31
32
uint32 SoftBodyShape::GetFaceIndex(const SubShapeID &inSubShapeID) const
33
{
34
SubShapeID remainder;
35
uint32 face_index = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);
36
JPH_ASSERT(remainder.IsEmpty());
37
return face_index;
38
}
39
40
AABox SoftBodyShape::GetLocalBounds() const
41
{
42
return mSoftBodyMotionProperties->GetLocalBounds();
43
}
44
45
bool SoftBodyShape::CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const
46
{
47
JPH_PROFILE_FUNCTION();
48
49
uint num_triangle_bits = GetSubShapeIDBits();
50
uint triangle_idx = uint(-1);
51
52
const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
53
for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())
54
{
55
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
56
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
57
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
58
59
float fraction = RayTriangle(inRay.mOrigin, inRay.mDirection, x1, x2, x3);
60
if (fraction < ioHit.mFraction)
61
{
62
// Store fraction
63
ioHit.mFraction = fraction;
64
65
// Store triangle index
66
triangle_idx = uint(&f - mSoftBodyMotionProperties->GetFaces().data());
67
}
68
}
69
70
if (triangle_idx == uint(-1))
71
return false;
72
73
ioHit.mSubShapeID2 = inSubShapeIDCreator.PushID(triangle_idx, num_triangle_bits).GetID();
74
return true;
75
}
76
77
void SoftBodyShape::CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter) const
78
{
79
JPH_PROFILE_FUNCTION();
80
81
// Test shape filter
82
if (!inShapeFilter.ShouldCollide(this, inSubShapeIDCreator.GetID()))
83
return;
84
85
uint num_triangle_bits = GetSubShapeIDBits();
86
bool check_backfaces = inRayCastSettings.mBackFaceModeTriangles == EBackFaceMode::IgnoreBackFaces && !mSoftBodyMotionProperties->GetFacesDoubleSided();
87
88
const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
89
for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())
90
{
91
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
92
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
93
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
94
95
// Back facing check
96
if (check_backfaces && (x2 - x1).Cross(x3 - x1).Dot(inRay.mDirection) > 0.0f)
97
continue;
98
99
// Test ray against triangle
100
float fraction = RayTriangle(inRay.mOrigin, inRay.mDirection, x1, x2, x3);
101
if (fraction < ioCollector.GetEarlyOutFraction())
102
{
103
// Better hit than the current hit
104
RayCastResult hit;
105
hit.mBodyID = TransformedShape::sGetBodyID(ioCollector.GetContext());
106
hit.mFraction = fraction;
107
hit.mSubShapeID2 = inSubShapeIDCreator.PushID(uint(&f - mSoftBodyMotionProperties->GetFaces().data()), num_triangle_bits).GetID();
108
ioCollector.AddHit(hit);
109
}
110
}
111
}
112
113
void SoftBodyShape::CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter) const
114
{
115
sCollidePointUsingRayCast(*this, inPoint, inSubShapeIDCreator, ioCollector, inShapeFilter);
116
}
117
118
void SoftBodyShape::CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const CollideSoftBodyVertexIterator &inVertices, uint inNumVertices, int inCollidingShapeIndex) const
119
{
120
/* Not implemented */
121
}
122
123
const PhysicsMaterial *SoftBodyShape::GetMaterial(const SubShapeID &inSubShapeID) const
124
{
125
SubShapeID remainder;
126
uint triangle_idx = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);
127
JPH_ASSERT(remainder.IsEmpty());
128
129
const SoftBodyMotionProperties::Face &f = mSoftBodyMotionProperties->GetFace(triangle_idx);
130
return mSoftBodyMotionProperties->GetMaterials()[f.mMaterialIndex];
131
}
132
133
Vec3 SoftBodyShape::GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const
134
{
135
SubShapeID remainder;
136
uint triangle_idx = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);
137
JPH_ASSERT(remainder.IsEmpty());
138
139
const SoftBodyMotionProperties::Face &f = mSoftBodyMotionProperties->GetFace(triangle_idx);
140
const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
141
142
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
143
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
144
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
145
146
return (x2 - x1).Cross(x3 - x1).NormalizedOr(Vec3::sAxisY());
147
}
148
149
void SoftBodyShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
150
{
151
SubShapeID remainder;
152
uint triangle_idx = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);
153
JPH_ASSERT(remainder.IsEmpty());
154
155
const SoftBodyMotionProperties::Face &f = mSoftBodyMotionProperties->GetFace(triangle_idx);
156
const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
157
158
for (uint32 i : f.mVertex)
159
outVertices.push_back(inCenterOfMassTransform * (inScale * vertices[i].mPosition));
160
}
161
162
void SoftBodyShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy JPH_IF_DEBUG_RENDERER(, RVec3Arg inBaseOffset)) const
163
{
164
outSubmergedVolume = 0.0f;
165
outTotalVolume = mSoftBodyMotionProperties->GetVolume();
166
outCenterOfBuoyancy = Vec3::sZero();
167
}
168
169
#ifdef JPH_DEBUG_RENDERER
170
171
void SoftBodyShape::Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const
172
{
173
const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
174
for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())
175
{
176
RVec3 x1 = inCenterOfMassTransform * vertices[f.mVertex[0]].mPosition;
177
RVec3 x2 = inCenterOfMassTransform * vertices[f.mVertex[1]].mPosition;
178
RVec3 x3 = inCenterOfMassTransform * vertices[f.mVertex[2]].mPosition;
179
180
inRenderer->DrawTriangle(x1, x2, x3, inColor, DebugRenderer::ECastShadow::On);
181
}
182
}
183
184
#endif // JPH_DEBUG_RENDERER
185
186
struct SoftBodyShape::SBSGetTrianglesContext
187
{
188
Mat44 mCenterOfMassTransform;
189
int mTriangleIndex;
190
};
191
192
void SoftBodyShape::GetTrianglesStart(GetTrianglesContext &ioContext, [[maybe_unused]] const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale) const
193
{
194
SBSGetTrianglesContext &context = reinterpret_cast<SBSGetTrianglesContext &>(ioContext);
195
context.mCenterOfMassTransform = Mat44::sRotationTranslation(inRotation, inPositionCOM) * Mat44::sScale(inScale);
196
context.mTriangleIndex = 0;
197
}
198
199
int SoftBodyShape::GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials) const
200
{
201
SBSGetTrianglesContext &context = reinterpret_cast<SBSGetTrianglesContext &>(ioContext);
202
203
const Array<SoftBodyMotionProperties::Face> &faces = mSoftBodyMotionProperties->GetFaces();
204
const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();
205
const PhysicsMaterialList &materials = mSoftBodyMotionProperties->GetMaterials();
206
207
int num_triangles = min(inMaxTrianglesRequested, (int)faces.size() - context.mTriangleIndex);
208
for (int i = 0; i < num_triangles; ++i)
209
{
210
const SoftBodyMotionProperties::Face &f = faces[context.mTriangleIndex + i];
211
212
Vec3 x1 = context.mCenterOfMassTransform * vertices[f.mVertex[0]].mPosition;
213
Vec3 x2 = context.mCenterOfMassTransform * vertices[f.mVertex[1]].mPosition;
214
Vec3 x3 = context.mCenterOfMassTransform * vertices[f.mVertex[2]].mPosition;
215
216
x1.StoreFloat3(outTriangleVertices++);
217
x2.StoreFloat3(outTriangleVertices++);
218
x3.StoreFloat3(outTriangleVertices++);
219
220
if (outMaterials != nullptr)
221
*outMaterials++ = materials[f.mMaterialIndex];
222
}
223
224
context.mTriangleIndex += num_triangles;
225
return num_triangles;
226
}
227
228
Shape::Stats SoftBodyShape::GetStats() const
229
{
230
return Stats(sizeof(*this), (uint)mSoftBodyMotionProperties->GetFaces().size());
231
}
232
233
float SoftBodyShape::GetVolume() const
234
{
235
return mSoftBodyMotionProperties->GetVolume();
236
}
237
238
void SoftBodyShape::sCollideConvexVsSoftBody(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, [[maybe_unused]] const ShapeFilter &inShapeFilter)
239
{
240
JPH_ASSERT(inShape1->GetType() == EShapeType::Convex);
241
const ConvexShape *shape1 = static_cast<const ConvexShape *>(inShape1);
242
JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::SoftBody);
243
const SoftBodyShape *shape2 = static_cast<const SoftBodyShape *>(inShape2);
244
245
const Array<SoftBodyVertex> &vertices = shape2->mSoftBodyMotionProperties->GetVertices();
246
const Array<SoftBodyMotionProperties::Face> &faces = shape2->mSoftBodyMotionProperties->GetFaces();
247
uint num_triangle_bits = shape2->GetSubShapeIDBits();
248
249
CollideShapeSettings settings(inCollideShapeSettings);
250
if (shape2->mSoftBodyMotionProperties->GetFacesDoubleSided())
251
settings.mBackFaceMode = EBackFaceMode::CollideWithBackFaces;
252
CollideConvexVsTriangles collider(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), settings, ioCollector);
253
for (const SoftBodyMotionProperties::Face &f : faces)
254
{
255
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
256
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
257
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
258
259
collider.Collide(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());
260
}
261
}
262
263
void SoftBodyShape::sCollideSphereVsSoftBody(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, [[maybe_unused]] const ShapeFilter &inShapeFilter)
264
{
265
JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::Sphere);
266
const SphereShape *shape1 = static_cast<const SphereShape *>(inShape1);
267
JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::SoftBody);
268
const SoftBodyShape *shape2 = static_cast<const SoftBodyShape *>(inShape2);
269
270
const Array<SoftBodyVertex> &vertices = shape2->mSoftBodyMotionProperties->GetVertices();
271
const Array<SoftBodyMotionProperties::Face> &faces = shape2->mSoftBodyMotionProperties->GetFaces();
272
uint num_triangle_bits = shape2->GetSubShapeIDBits();
273
274
CollideShapeSettings settings(inCollideShapeSettings);
275
if (shape2->mSoftBodyMotionProperties->GetFacesDoubleSided())
276
settings.mBackFaceMode = EBackFaceMode::CollideWithBackFaces;
277
CollideSphereVsTriangles collider(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), settings, ioCollector);
278
for (const SoftBodyMotionProperties::Face &f : faces)
279
{
280
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
281
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
282
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
283
284
collider.Collide(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());
285
}
286
}
287
288
void SoftBodyShape::sCastConvexVsSoftBody(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, [[maybe_unused]] const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
289
{
290
JPH_ASSERT(inShape->GetSubType() == EShapeSubType::SoftBody);
291
const SoftBodyShape *shape = static_cast<const SoftBodyShape *>(inShape);
292
293
const Array<SoftBodyVertex> &vertices = shape->mSoftBodyMotionProperties->GetVertices();
294
const Array<SoftBodyMotionProperties::Face> &faces = shape->mSoftBodyMotionProperties->GetFaces();
295
uint num_triangle_bits = shape->GetSubShapeIDBits();
296
297
ShapeCastSettings settings(inShapeCastSettings);
298
if (shape->mSoftBodyMotionProperties->GetFacesDoubleSided())
299
settings.mBackFaceModeTriangles = EBackFaceMode::CollideWithBackFaces;
300
CastConvexVsTriangles caster(inShapeCast, settings, inScale, inCenterOfMassTransform2, inSubShapeIDCreator1, ioCollector);
301
for (const SoftBodyMotionProperties::Face &f : faces)
302
{
303
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
304
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
305
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
306
307
caster.Cast(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());
308
}
309
}
310
311
void SoftBodyShape::sCastSphereVsSoftBody(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, [[maybe_unused]] const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
312
{
313
JPH_ASSERT(inShape->GetSubType() == EShapeSubType::SoftBody);
314
const SoftBodyShape *shape = static_cast<const SoftBodyShape *>(inShape);
315
316
const Array<SoftBodyVertex> &vertices = shape->mSoftBodyMotionProperties->GetVertices();
317
const Array<SoftBodyMotionProperties::Face> &faces = shape->mSoftBodyMotionProperties->GetFaces();
318
uint num_triangle_bits = shape->GetSubShapeIDBits();
319
320
ShapeCastSettings settings(inShapeCastSettings);
321
if (shape->mSoftBodyMotionProperties->GetFacesDoubleSided())
322
settings.mBackFaceModeTriangles = EBackFaceMode::CollideWithBackFaces;
323
CastSphereVsTriangles caster(inShapeCast, settings, inScale, inCenterOfMassTransform2, inSubShapeIDCreator1, ioCollector);
324
for (const SoftBodyMotionProperties::Face &f : faces)
325
{
326
Vec3 x1 = vertices[f.mVertex[0]].mPosition;
327
Vec3 x2 = vertices[f.mVertex[1]].mPosition;
328
Vec3 x3 = vertices[f.mVertex[2]].mPosition;
329
330
caster.Cast(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());
331
}
332
}
333
334
void SoftBodyShape::sRegister()
335
{
336
ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::SoftBody);
337
f.mConstruct = nullptr; // Not supposed to be constructed by users!
338
f.mColor = Color::sDarkGreen;
339
340
for (EShapeSubType s : sConvexSubShapeTypes)
341
{
342
CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::SoftBody, sCollideConvexVsSoftBody);
343
CollisionDispatch::sRegisterCastShape(s, EShapeSubType::SoftBody, sCastConvexVsSoftBody);
344
345
CollisionDispatch::sRegisterCollideShape(EShapeSubType::SoftBody, s, CollisionDispatch::sReversedCollideShape);
346
CollisionDispatch::sRegisterCastShape(EShapeSubType::SoftBody, s, CollisionDispatch::sReversedCastShape);
347
}
348
349
// Specialized collision functions
350
CollisionDispatch::sRegisterCollideShape(EShapeSubType::Sphere, EShapeSubType::SoftBody, sCollideSphereVsSoftBody);
351
CollisionDispatch::sRegisterCastShape(EShapeSubType::Sphere, EShapeSubType::SoftBody, sCastSphereVsSoftBody);
352
}
353
354
JPH_NAMESPACE_END
355
356