Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Collision/CastConvexVsTriangles.cpp
21461 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/CastConvexVsTriangles.h>
8
#include <Jolt/Physics/Collision/TransformedShape.h>
9
#include <Jolt/Physics/Collision/Shape/ScaleHelpers.h>
10
#include <Jolt/Physics/Collision/ActiveEdges.h>
11
#include <Jolt/Physics/Collision/NarrowPhaseStats.h>
12
#include <Jolt/Geometry/EPAPenetrationDepth.h>
13
14
JPH_NAMESPACE_BEGIN
15
16
CastConvexVsTriangles::CastConvexVsTriangles(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, CastShapeCollector &ioCollector) :
17
mShapeCast(inShapeCast),
18
mShapeCastSettings(inShapeCastSettings),
19
mCenterOfMassTransform2(inCenterOfMassTransform2),
20
mScale(inScale),
21
mSubShapeIDCreator1(inSubShapeIDCreator1),
22
mCollector(ioCollector)
23
{
24
JPH_ASSERT(inShapeCast.mShape->GetType() == EShapeType::Convex);
25
26
// Determine if shape is inside out or not
27
mScaleSign = ScaleHelpers::IsInsideOut(inScale)? -1.0f : 1.0f;
28
}
29
30
void CastConvexVsTriangles::Cast(Vec3Arg inV0, Vec3Arg inV1, Vec3Arg inV2, uint8 inActiveEdges, const SubShapeID &inSubShapeID2)
31
{
32
// Scale triangle
33
Vec3 v0 = mScale * inV0;
34
Vec3 v1 = mScale * inV1;
35
Vec3 v2 = mScale * inV2;
36
37
// Calculate triangle normal
38
Vec3 triangle_normal = mScaleSign * (v1 - v0).Cross(v2 - v0);
39
40
// Backface check
41
bool back_facing = triangle_normal.Dot(mShapeCast.mDirection) > 0.0f;
42
if (mShapeCastSettings.mBackFaceModeTriangles == EBackFaceMode::IgnoreBackFaces && back_facing)
43
return;
44
45
// Create triangle support function
46
TriangleConvexSupport triangle { v0, v1, v2 };
47
48
// Check if we already created the cast shape support function
49
if (mSupport == nullptr)
50
{
51
// Determine if we want to use the actual shape or a shrunken shape with convex radius
52
ConvexShape::ESupportMode support_mode = mShapeCastSettings.mUseShrunkenShapeAndConvexRadius? ConvexShape::ESupportMode::ExcludeConvexRadius : ConvexShape::ESupportMode::Default;
53
54
// Create support function
55
mSupport = static_cast<const ConvexShape *>(mShapeCast.mShape)->GetSupportFunction(support_mode, mSupportBuffer, mShapeCast.mScale);
56
}
57
58
EPAPenetrationDepth epa;
59
float fraction = mCollector.GetEarlyOutFraction();
60
Vec3 contact_point_a, contact_point_b, contact_normal;
61
if (epa.CastShape(mShapeCast.mCenterOfMassStart, mShapeCast.mDirection, mShapeCastSettings.mCollisionTolerance, mShapeCastSettings.mPenetrationTolerance, *mSupport, triangle, mSupport->GetConvexRadius(), 0.0f, mShapeCastSettings.mReturnDeepestPoint, fraction, contact_point_a, contact_point_b, contact_normal))
62
{
63
// Check if we have enabled active edge detection
64
if (mShapeCastSettings.mActiveEdgeMode == EActiveEdgeMode::CollideOnlyWithActive && inActiveEdges != 0b111)
65
{
66
// Convert the active edge velocity hint to local space
67
Vec3 active_edge_movement_direction = mCenterOfMassTransform2.Multiply3x3Transposed(mShapeCastSettings.mActiveEdgeMovementDirection);
68
69
// Update the contact normal to account for active edges
70
// Note that we flip the triangle normal as the penetration axis is pointing towards the triangle instead of away
71
contact_normal = ActiveEdges::FixNormal(v0, v1, v2, back_facing? triangle_normal : -triangle_normal, inActiveEdges, contact_point_b, contact_normal, active_edge_movement_direction);
72
}
73
74
// Convert to world space
75
contact_point_a = mCenterOfMassTransform2 * contact_point_a;
76
contact_point_b = mCenterOfMassTransform2 * contact_point_b;
77
Vec3 contact_normal_world = mCenterOfMassTransform2.Multiply3x3(contact_normal);
78
79
// Its a hit, store the sub shape id's
80
ShapeCastResult result(fraction, contact_point_a, contact_point_b, contact_normal_world, back_facing, mSubShapeIDCreator1.GetID(), inSubShapeID2, TransformedShape::sGetBodyID(mCollector.GetContext()));
81
82
// Early out if this hit is deeper than the collector's early out value
83
if (fraction == 0.0f && -result.mPenetrationDepth >= mCollector.GetEarlyOutFraction())
84
return;
85
86
// Gather faces
87
if (mShapeCastSettings.mCollectFacesMode == ECollectFacesMode::CollectFaces)
88
{
89
// Get supporting face of shape 1
90
Mat44 transform_1_to_2 = mShapeCast.mCenterOfMassStart;
91
transform_1_to_2.SetTranslation(transform_1_to_2.GetTranslation() + fraction * mShapeCast.mDirection);
92
static_cast<const ConvexShape *>(mShapeCast.mShape)->GetSupportingFace(SubShapeID(), transform_1_to_2.Multiply3x3Transposed(-contact_normal), mShapeCast.mScale, mCenterOfMassTransform2 * transform_1_to_2, result.mShape1Face);
93
94
// Get face of the triangle
95
result.mShape2Face.resize(3);
96
result.mShape2Face[0] = mCenterOfMassTransform2 * v0;
97
result.mShape2Face[1] = mCenterOfMassTransform2 * v1;
98
result.mShape2Face[2] = mCenterOfMassTransform2 * v2;
99
100
// When inside out, we need to swap the triangle winding
101
if (mScaleSign < 0.0f)
102
std::swap(result.mShape2Face[1], result.mShape2Face[2]);
103
}
104
105
JPH_IF_TRACK_NARROWPHASE_STATS(TrackNarrowPhaseCollector track;)
106
mCollector.AddHit(result);
107
}
108
}
109
110
JPH_NAMESPACE_END
111
112