Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/RotatedTranslatedShape.cpp
9913 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#include <Jolt/Jolt.h>
6
7
#include <Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h>
8
#include <Jolt/Physics/Collision/CollisionDispatch.h>
9
#include <Jolt/Physics/Collision/RayCast.h>
10
#include <Jolt/Physics/Collision/ShapeCast.h>
11
#include <Jolt/Physics/Collision/TransformedShape.h>
12
#include <Jolt/Core/StreamIn.h>
13
#include <Jolt/Core/StreamOut.h>
14
#include <Jolt/ObjectStream/TypeDeclarations.h>
15
16
JPH_NAMESPACE_BEGIN
17
18
JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(RotatedTranslatedShapeSettings)
19
{
20
JPH_ADD_BASE_CLASS(RotatedTranslatedShapeSettings, DecoratedShapeSettings)
21
22
JPH_ADD_ATTRIBUTE(RotatedTranslatedShapeSettings, mPosition)
23
JPH_ADD_ATTRIBUTE(RotatedTranslatedShapeSettings, mRotation)
24
}
25
26
ShapeSettings::ShapeResult RotatedTranslatedShapeSettings::Create() const
27
{
28
if (mCachedResult.IsEmpty())
29
Ref<Shape> shape = new RotatedTranslatedShape(*this, mCachedResult);
30
return mCachedResult;
31
}
32
33
RotatedTranslatedShape::RotatedTranslatedShape(const RotatedTranslatedShapeSettings &inSettings, ShapeResult &outResult) :
34
DecoratedShape(EShapeSubType::RotatedTranslated, inSettings, outResult)
35
{
36
if (outResult.HasError())
37
return;
38
39
// Calculate center of mass position
40
mCenterOfMass = inSettings.mPosition + inSettings.mRotation * mInnerShape->GetCenterOfMass();
41
42
// Store rotation (position is always zero because we center around the center of mass)
43
mRotation = inSettings.mRotation;
44
mIsRotationIdentity = mRotation.IsClose(Quat::sIdentity());
45
46
outResult.Set(this);
47
}
48
49
RotatedTranslatedShape::RotatedTranslatedShape(Vec3Arg inPosition, QuatArg inRotation, const Shape *inShape) :
50
DecoratedShape(EShapeSubType::RotatedTranslated, inShape)
51
{
52
// Calculate center of mass position
53
mCenterOfMass = inPosition + inRotation * mInnerShape->GetCenterOfMass();
54
55
// Store rotation (position is always zero because we center around the center of mass)
56
mRotation = inRotation;
57
mIsRotationIdentity = mRotation.IsClose(Quat::sIdentity());
58
}
59
60
MassProperties RotatedTranslatedShape::GetMassProperties() const
61
{
62
// Rotate inertia of child into place
63
MassProperties p = mInnerShape->GetMassProperties();
64
p.Rotate(Mat44::sRotation(mRotation));
65
return p;
66
}
67
68
AABox RotatedTranslatedShape::GetLocalBounds() const
69
{
70
return mInnerShape->GetLocalBounds().Transformed(Mat44::sRotation(mRotation));
71
}
72
73
AABox RotatedTranslatedShape::GetWorldSpaceBounds(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale) const
74
{
75
Mat44 transform = inCenterOfMassTransform * Mat44::sRotation(mRotation);
76
return mInnerShape->GetWorldSpaceBounds(transform, TransformScale(inScale));
77
}
78
79
TransformedShape RotatedTranslatedShape::GetSubShapeTransformedShape(const SubShapeID &inSubShapeID, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale, SubShapeID &outRemainder) const
80
{
81
// We don't use any bits in the sub shape ID
82
outRemainder = inSubShapeID;
83
84
TransformedShape ts(RVec3(inPositionCOM), inRotation * mRotation, mInnerShape, BodyID());
85
ts.SetShapeScale(TransformScale(inScale));
86
return ts;
87
}
88
89
Vec3 RotatedTranslatedShape::GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const
90
{
91
// Transform surface position to local space and pass call on
92
Mat44 transform = Mat44::sRotation(mRotation.Conjugated());
93
Vec3 normal = mInnerShape->GetSurfaceNormal(inSubShapeID, transform * inLocalSurfacePosition);
94
95
// Transform normal to this shape's space
96
return transform.Multiply3x3Transposed(normal);
97
}
98
99
void RotatedTranslatedShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
100
{
101
Mat44 transform = Mat44::sRotation(mRotation);
102
mInnerShape->GetSupportingFace(inSubShapeID, transform.Multiply3x3Transposed(inDirection), TransformScale(inScale), inCenterOfMassTransform * transform, outVertices);
103
}
104
105
void RotatedTranslatedShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy JPH_IF_DEBUG_RENDERER(, RVec3Arg inBaseOffset)) const
106
{
107
// Get center of mass transform of child
108
Mat44 transform = inCenterOfMassTransform * Mat44::sRotation(mRotation);
109
110
// Recurse to child
111
mInnerShape->GetSubmergedVolume(transform, TransformScale(inScale), inSurface, outTotalVolume, outSubmergedVolume, outCenterOfBuoyancy JPH_IF_DEBUG_RENDERER(, inBaseOffset));
112
}
113
114
#ifdef JPH_DEBUG_RENDERER
115
void RotatedTranslatedShape::Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const
116
{
117
mInnerShape->Draw(inRenderer, inCenterOfMassTransform * Mat44::sRotation(mRotation), TransformScale(inScale), inColor, inUseMaterialColors, inDrawWireframe);
118
}
119
120
void RotatedTranslatedShape::DrawGetSupportFunction(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inDrawSupportDirection) const
121
{
122
mInnerShape->DrawGetSupportFunction(inRenderer, inCenterOfMassTransform * Mat44::sRotation(mRotation), TransformScale(inScale), inColor, inDrawSupportDirection);
123
}
124
125
void RotatedTranslatedShape::DrawGetSupportingFace(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale) const
126
{
127
mInnerShape->DrawGetSupportingFace(inRenderer, inCenterOfMassTransform * Mat44::sRotation(mRotation), TransformScale(inScale));
128
}
129
#endif // JPH_DEBUG_RENDERER
130
131
bool RotatedTranslatedShape::CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const
132
{
133
// Transform the ray
134
Mat44 transform = Mat44::sRotation(mRotation.Conjugated());
135
RayCast ray = inRay.Transformed(transform);
136
137
return mInnerShape->CastRay(ray, inSubShapeIDCreator, ioHit);
138
}
139
140
void RotatedTranslatedShape::CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter) const
141
{
142
// Test shape filter
143
if (!inShapeFilter.ShouldCollide(this, inSubShapeIDCreator.GetID()))
144
return;
145
146
// Transform the ray
147
Mat44 transform = Mat44::sRotation(mRotation.Conjugated());
148
RayCast ray = inRay.Transformed(transform);
149
150
return mInnerShape->CastRay(ray, inRayCastSettings, inSubShapeIDCreator, ioCollector, inShapeFilter);
151
}
152
153
void RotatedTranslatedShape::CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter) const
154
{
155
// Test shape filter
156
if (!inShapeFilter.ShouldCollide(this, inSubShapeIDCreator.GetID()))
157
return;
158
159
// Transform the point
160
Mat44 transform = Mat44::sRotation(mRotation.Conjugated());
161
mInnerShape->CollidePoint(transform * inPoint, inSubShapeIDCreator, ioCollector, inShapeFilter);
162
}
163
164
void RotatedTranslatedShape::CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const CollideSoftBodyVertexIterator &inVertices, uint inNumVertices, int inCollidingShapeIndex) const
165
{
166
mInnerShape->CollideSoftBodyVertices(inCenterOfMassTransform * Mat44::sRotation(mRotation), inScale, inVertices, inNumVertices, inCollidingShapeIndex);
167
}
168
169
void RotatedTranslatedShape::CollectTransformedShapes(const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale, const SubShapeIDCreator &inSubShapeIDCreator, TransformedShapeCollector &ioCollector, const ShapeFilter &inShapeFilter) const
170
{
171
// Test shape filter
172
if (!inShapeFilter.ShouldCollide(this, inSubShapeIDCreator.GetID()))
173
return;
174
175
mInnerShape->CollectTransformedShapes(inBox, inPositionCOM, inRotation * mRotation, TransformScale(inScale), inSubShapeIDCreator, ioCollector, inShapeFilter);
176
}
177
178
void RotatedTranslatedShape::TransformShape(Mat44Arg inCenterOfMassTransform, TransformedShapeCollector &ioCollector) const
179
{
180
mInnerShape->TransformShape(inCenterOfMassTransform * Mat44::sRotation(mRotation), ioCollector);
181
}
182
183
void RotatedTranslatedShape::sCollideRotatedTranslatedVsShape(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, const ShapeFilter &inShapeFilter)
184
{
185
JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::RotatedTranslated);
186
const RotatedTranslatedShape *shape1 = static_cast<const RotatedTranslatedShape *>(inShape1);
187
188
// Get world transform of 1
189
Mat44 transform1 = inCenterOfMassTransform1 * Mat44::sRotation(shape1->mRotation);
190
191
CollisionDispatch::sCollideShapeVsShape(shape1->mInnerShape, inShape2, shape1->TransformScale(inScale1), inScale2, transform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector, inShapeFilter);
192
}
193
194
void RotatedTranslatedShape::sCollideShapeVsRotatedTranslated(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, const ShapeFilter &inShapeFilter)
195
{
196
JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::RotatedTranslated);
197
const RotatedTranslatedShape *shape2 = static_cast<const RotatedTranslatedShape *>(inShape2);
198
199
// Get world transform of 2
200
Mat44 transform2 = inCenterOfMassTransform2 * Mat44::sRotation(shape2->mRotation);
201
202
CollisionDispatch::sCollideShapeVsShape(inShape1, shape2->mInnerShape, inScale1, shape2->TransformScale(inScale2), inCenterOfMassTransform1, transform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector, inShapeFilter);
203
}
204
205
void RotatedTranslatedShape::sCollideRotatedTranslatedVsRotatedTranslated(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, const ShapeFilter &inShapeFilter)
206
{
207
JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::RotatedTranslated);
208
const RotatedTranslatedShape *shape1 = static_cast<const RotatedTranslatedShape *>(inShape1);
209
JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::RotatedTranslated);
210
const RotatedTranslatedShape *shape2 = static_cast<const RotatedTranslatedShape *>(inShape2);
211
212
// Get world transform of 1 and 2
213
Mat44 transform1 = inCenterOfMassTransform1 * Mat44::sRotation(shape1->mRotation);
214
Mat44 transform2 = inCenterOfMassTransform2 * Mat44::sRotation(shape2->mRotation);
215
216
CollisionDispatch::sCollideShapeVsShape(shape1->mInnerShape, shape2->mInnerShape, shape1->TransformScale(inScale1), shape2->TransformScale(inScale2), transform1, transform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector, inShapeFilter);
217
}
218
219
void RotatedTranslatedShape::sCastRotatedTranslatedVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
220
{
221
// Fetch rotated translated shape from cast shape
222
JPH_ASSERT(inShapeCast.mShape->GetSubType() == EShapeSubType::RotatedTranslated);
223
const RotatedTranslatedShape *shape1 = static_cast<const RotatedTranslatedShape *>(inShapeCast.mShape);
224
225
// Transform the shape cast and update the shape
226
Mat44 transform = inShapeCast.mCenterOfMassStart * Mat44::sRotation(shape1->mRotation);
227
Vec3 scale = shape1->TransformScale(inShapeCast.mScale);
228
ShapeCast shape_cast(shape1->mInnerShape, scale, transform, inShapeCast.mDirection);
229
230
CollisionDispatch::sCastShapeVsShapeLocalSpace(shape_cast, inShapeCastSettings, inShape, inScale, inShapeFilter, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);
231
}
232
233
void RotatedTranslatedShape::sCastShapeVsRotatedTranslated(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
234
{
235
JPH_ASSERT(inShape->GetSubType() == EShapeSubType::RotatedTranslated);
236
const RotatedTranslatedShape *shape = static_cast<const RotatedTranslatedShape *>(inShape);
237
238
// Determine the local transform
239
Mat44 local_transform = Mat44::sRotation(shape->mRotation);
240
241
// Transform the shape cast
242
ShapeCast shape_cast = inShapeCast.PostTransformed(local_transform.Transposed3x3());
243
244
CollisionDispatch::sCastShapeVsShapeLocalSpace(shape_cast, inShapeCastSettings, shape->mInnerShape, shape->TransformScale(inScale), inShapeFilter, inCenterOfMassTransform2 * local_transform, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);
245
}
246
247
void RotatedTranslatedShape::sCastRotatedTranslatedVsRotatedTranslated(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)
248
{
249
JPH_ASSERT(inShapeCast.mShape->GetSubType() == EShapeSubType::RotatedTranslated);
250
const RotatedTranslatedShape *shape1 = static_cast<const RotatedTranslatedShape *>(inShapeCast.mShape);
251
JPH_ASSERT(inShape->GetSubType() == EShapeSubType::RotatedTranslated);
252
const RotatedTranslatedShape *shape2 = static_cast<const RotatedTranslatedShape *>(inShape);
253
254
// Determine the local transform of shape 2
255
Mat44 local_transform2 = Mat44::sRotation(shape2->mRotation);
256
Mat44 local_transform2_transposed = local_transform2.Transposed3x3();
257
258
// Transform the shape cast and update the shape
259
Mat44 transform = (local_transform2_transposed * inShapeCast.mCenterOfMassStart) * Mat44::sRotation(shape1->mRotation);
260
Vec3 scale = shape1->TransformScale(inShapeCast.mScale);
261
ShapeCast shape_cast(shape1->mInnerShape, scale, transform, local_transform2_transposed.Multiply3x3(inShapeCast.mDirection));
262
263
CollisionDispatch::sCastShapeVsShapeLocalSpace(shape_cast, inShapeCastSettings, shape2->mInnerShape, shape2->TransformScale(inScale), inShapeFilter, inCenterOfMassTransform2 * local_transform2, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);
264
}
265
266
void RotatedTranslatedShape::SaveBinaryState(StreamOut &inStream) const
267
{
268
DecoratedShape::SaveBinaryState(inStream);
269
270
inStream.Write(mCenterOfMass);
271
inStream.Write(mRotation);
272
}
273
274
void RotatedTranslatedShape::RestoreBinaryState(StreamIn &inStream)
275
{
276
DecoratedShape::RestoreBinaryState(inStream);
277
278
inStream.Read(mCenterOfMass);
279
inStream.Read(mRotation);
280
mIsRotationIdentity = mRotation.IsClose(Quat::sIdentity());
281
}
282
283
bool RotatedTranslatedShape::IsValidScale(Vec3Arg inScale) const
284
{
285
if (!Shape::IsValidScale(inScale))
286
return false;
287
288
if (mIsRotationIdentity || ScaleHelpers::IsUniformScale(inScale))
289
return mInnerShape->IsValidScale(inScale);
290
291
if (!ScaleHelpers::CanScaleBeRotated(mRotation, inScale))
292
return false;
293
294
return mInnerShape->IsValidScale(ScaleHelpers::RotateScale(mRotation, inScale));
295
}
296
297
Vec3 RotatedTranslatedShape::MakeScaleValid(Vec3Arg inScale) const
298
{
299
Vec3 scale = ScaleHelpers::MakeNonZeroScale(inScale);
300
301
if (mIsRotationIdentity || ScaleHelpers::IsUniformScale(scale))
302
return mInnerShape->MakeScaleValid(scale);
303
304
if (ScaleHelpers::CanScaleBeRotated(mRotation, scale))
305
return ScaleHelpers::RotateScale(mRotation.Conjugated(), mInnerShape->MakeScaleValid(ScaleHelpers::RotateScale(mRotation, scale)));
306
307
Vec3 abs_uniform_scale = ScaleHelpers::MakeUniformScale(scale.Abs());
308
Vec3 uniform_scale = scale.GetSign() * abs_uniform_scale;
309
if (ScaleHelpers::CanScaleBeRotated(mRotation, uniform_scale))
310
return uniform_scale;
311
312
return Sign(scale.GetX()) * abs_uniform_scale;
313
}
314
315
void RotatedTranslatedShape::sRegister()
316
{
317
ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::RotatedTranslated);
318
f.mConstruct = []() -> Shape * { return new RotatedTranslatedShape; };
319
f.mColor = Color::sBlue;
320
321
for (EShapeSubType s : sAllSubShapeTypes)
322
{
323
CollisionDispatch::sRegisterCollideShape(EShapeSubType::RotatedTranslated, s, sCollideRotatedTranslatedVsShape);
324
CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::RotatedTranslated, sCollideShapeVsRotatedTranslated);
325
CollisionDispatch::sRegisterCastShape(EShapeSubType::RotatedTranslated, s, sCastRotatedTranslatedVsShape);
326
CollisionDispatch::sRegisterCastShape(s, EShapeSubType::RotatedTranslated, sCastShapeVsRotatedTranslated);
327
}
328
329
CollisionDispatch::sRegisterCollideShape(EShapeSubType::RotatedTranslated, EShapeSubType::RotatedTranslated, sCollideRotatedTranslatedVsRotatedTranslated);
330
CollisionDispatch::sRegisterCastShape(EShapeSubType::RotatedTranslated, EShapeSubType::RotatedTranslated, sCastRotatedTranslatedVsRotatedTranslated);
331
}
332
333
JPH_NAMESPACE_END
334
335