Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Collision/CollisionCollectorImpl.h
9912 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/Physics/Collision/CollisionCollector.h>
8
#include <Jolt/Core/QuickSort.h>
9
10
JPH_NAMESPACE_BEGIN
11
12
/// Simple implementation that collects all hits and optionally sorts them on distance
13
template <class CollectorType>
14
class AllHitCollisionCollector : public CollectorType
15
{
16
public:
17
/// Redeclare ResultType
18
using ResultType = typename CollectorType::ResultType;
19
20
// See: CollectorType::Reset
21
virtual void Reset() override
22
{
23
CollectorType::Reset();
24
25
mHits.clear();
26
}
27
28
// See: CollectorType::AddHit
29
virtual void AddHit(const ResultType &inResult) override
30
{
31
mHits.push_back(inResult);
32
}
33
34
/// Order hits on closest first
35
void Sort()
36
{
37
QuickSort(mHits.begin(), mHits.end(), [](const ResultType &inLHS, const ResultType &inRHS) { return inLHS.GetEarlyOutFraction() < inRHS.GetEarlyOutFraction(); });
38
}
39
40
/// Check if any hits were collected
41
inline bool HadHit() const
42
{
43
return !mHits.empty();
44
}
45
46
Array<ResultType> mHits;
47
};
48
49
/// Simple implementation that collects the closest / deepest hit
50
template <class CollectorType>
51
class ClosestHitCollisionCollector : public CollectorType
52
{
53
public:
54
/// Redeclare ResultType
55
using ResultType = typename CollectorType::ResultType;
56
57
// See: CollectorType::Reset
58
virtual void Reset() override
59
{
60
CollectorType::Reset();
61
62
mHadHit = false;
63
}
64
65
// See: CollectorType::AddHit
66
virtual void AddHit(const ResultType &inResult) override
67
{
68
float early_out = inResult.GetEarlyOutFraction();
69
if (!mHadHit || early_out < mHit.GetEarlyOutFraction())
70
{
71
// Update early out fraction
72
CollectorType::UpdateEarlyOutFraction(early_out);
73
74
// Store hit
75
mHit = inResult;
76
mHadHit = true;
77
}
78
}
79
80
/// Check if this collector has had a hit
81
inline bool HadHit() const
82
{
83
return mHadHit;
84
}
85
86
ResultType mHit;
87
88
private:
89
bool mHadHit = false;
90
};
91
92
/// Implementation that collects the closest / deepest hit for each body and optionally sorts them on distance
93
template <class CollectorType>
94
class ClosestHitPerBodyCollisionCollector : public CollectorType
95
{
96
public:
97
/// Redeclare ResultType
98
using ResultType = typename CollectorType::ResultType;
99
100
// See: CollectorType::Reset
101
virtual void Reset() override
102
{
103
CollectorType::Reset();
104
105
mHits.clear();
106
mHadHit = false;
107
}
108
109
// See: CollectorType::OnBody
110
virtual void OnBody(const Body &inBody) override
111
{
112
// Store the early out fraction so we can restore it after we've collected all hits for this body
113
mPreviousEarlyOutFraction = CollectorType::GetEarlyOutFraction();
114
}
115
116
// See: CollectorType::AddHit
117
virtual void AddHit(const ResultType &inResult) override
118
{
119
float early_out = inResult.GetEarlyOutFraction();
120
if (!mHadHit || early_out < CollectorType::GetEarlyOutFraction())
121
{
122
// Update early out fraction to avoid spending work on collecting further hits for this body
123
CollectorType::UpdateEarlyOutFraction(early_out);
124
125
if (!mHadHit)
126
{
127
// First time we have a hit we append it to the array
128
mHits.push_back(inResult);
129
mHadHit = true;
130
}
131
else
132
{
133
// Closer hits will override the previous one
134
mHits.back() = inResult;
135
}
136
}
137
}
138
139
// See: CollectorType::OnBodyEnd
140
virtual void OnBodyEnd() override
141
{
142
if (mHadHit)
143
{
144
// Reset the early out fraction to the configured value so that we will continue
145
// to collect hits at any distance for other bodies
146
JPH_ASSERT(mPreviousEarlyOutFraction != -FLT_MAX); // Check that we got a call to OnBody
147
CollectorType::ResetEarlyOutFraction(mPreviousEarlyOutFraction);
148
mHadHit = false;
149
}
150
151
// For asserting purposes we reset the stored early out fraction so we can detect that OnBody was called
152
JPH_IF_ENABLE_ASSERTS(mPreviousEarlyOutFraction = -FLT_MAX;)
153
}
154
155
/// Order hits on closest first
156
void Sort()
157
{
158
QuickSort(mHits.begin(), mHits.end(), [](const ResultType &inLHS, const ResultType &inRHS) { return inLHS.GetEarlyOutFraction() < inRHS.GetEarlyOutFraction(); });
159
}
160
161
/// Check if any hits were collected
162
inline bool HadHit() const
163
{
164
return !mHits.empty();
165
}
166
167
Array<ResultType> mHits;
168
169
private:
170
// Store early out fraction that was initially configured for the collector
171
float mPreviousEarlyOutFraction = -FLT_MAX;
172
173
// Flag to indicate if we have a hit for the current body
174
bool mHadHit = false;
175
};
176
177
/// Simple implementation that collects any hit
178
template <class CollectorType>
179
class AnyHitCollisionCollector : public CollectorType
180
{
181
public:
182
/// Redeclare ResultType
183
using ResultType = typename CollectorType::ResultType;
184
185
// See: CollectorType::Reset
186
virtual void Reset() override
187
{
188
CollectorType::Reset();
189
190
mHadHit = false;
191
}
192
193
// See: CollectorType::AddHit
194
virtual void AddHit(const ResultType &inResult) override
195
{
196
// Test that the collector is not collecting more hits after forcing an early out
197
JPH_ASSERT(!mHadHit);
198
199
// Abort any further testing
200
CollectorType::ForceEarlyOut();
201
202
// Store hit
203
mHit = inResult;
204
mHadHit = true;
205
}
206
207
/// Check if this collector has had a hit
208
inline bool HadHit() const
209
{
210
return mHadHit;
211
}
212
213
ResultType mHit;
214
215
private:
216
bool mHadHit = false;
217
};
218
219
JPH_NAMESPACE_END
220
221