Skip to content

Commit e060c79

Browse files
committed
Use mini and geometric queries in bvh query kernels
1 parent 52fd46a commit e060c79

File tree

5 files changed

+93
-177
lines changed

5 files changed

+93
-177
lines changed

source/pbat/geometry/DistanceQueries.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ PBAT_HOST_DEVICE typename TMatrixL1::ScalarType AxisAlignedBoundingBoxes(
3434
TMatrixU2 const& U2);
3535

3636
/**
37-
* @brief
37+
* @brief Obtain squared distance between point P and axis-aligned box (L,U)
3838
* @tparam TMatrixP
3939
* @tparam TMatrixL
4040
* @tparam TMatrixU
@@ -64,7 +64,7 @@ PBAT_HOST_DEVICE typename TMatrixP::ScalarType
6464
PointTriangle(TMatrixP const& P, TMatrixA const& A, TMatrixB const& B, TMatrixC const& C);
6565

6666
/**
67-
* @brief
67+
* @brief Obtain squared distance between point P and tetrahedron ABCD
6868
* @tparam TMatrixP
6969
* @tparam TMatrixA
7070
* @tparam TMatrixB
@@ -102,7 +102,7 @@ PBAT_HOST_DEVICE typename TMatrixX::ScalarType
102102
PointPlane(TMatrixX const& X, TMatrixP const& P, TMatrixN const& n);
103103

104104
/**
105-
* @brief Obtains the distance between sphere (X,R) and triangle ABC.
105+
* @brief Obtains the squared distance between sphere (X,R) and triangle ABC.
106106
* @param X
107107
* @param R
108108
* @param A
@@ -153,7 +153,7 @@ PointAxisAlignedBoundingBox(TMatrixP const& P, TMatrixL const& L, TMatrixU const
153153
return 0.;
154154
// Otherwise compute distance to boundary
155155
auto const CP = ClosestPointQueries::PointOnAxisAlignedBoundingBox(P, L, U);
156-
return Norm(P - CP);
156+
return SquaredNorm(P - CP);
157157
}
158158

159159
template <
@@ -165,7 +165,7 @@ PBAT_HOST_DEVICE typename TMatrixP::ScalarType
165165
PointTriangle(TMatrixP const& P, TMatrixA const& A, TMatrixB const& B, TMatrixC const& C)
166166
{
167167
auto const PP = ClosestPointQueries::PointInTriangle(P, A, B, C);
168-
return Norm(P - PP);
168+
return SquaredNorm(P - PP);
169169
}
170170

171171
template <
@@ -214,8 +214,8 @@ PBAT_HOST_DEVICE typename TMatrixX::ScalarType SphereTriangle(
214214
TMatrixB const& B,
215215
TMatrixC const& C)
216216
{
217-
auto const d2c = PointTriangle(X, A, B, C);
218-
return d2c - R;
217+
auto const sd2c = PointTriangle(X, A, B, C);
218+
return sd2c - R * R;
219219
}
220220

221221
} // namespace DistanceQueries

source/pbat/geometry/OverlapQueries.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -553,8 +553,8 @@ PBAT_HOST_DEVICE bool LineSegmentAxisAlignedBoundingBox(
553553
return false;
554554
// Add in an epsilon term to counteract arithmetic errors when segment is
555555
// (near) parallel to a coordinate axis (see text for detail)
556-
common::ForRange<0, kDims>([]<auto dim>() {
557-
ScalarType constexpr eps = 1e-15;
556+
common::ForRange<0, kDims>([&]<auto dim>() {
557+
ScalarType constexpr eps{1e-15};
558558
ad(dim) += eps;
559559
auto i = (dim + 1) % kDims;
560560
auto j = (dim + 2) % kDims;

source/pbat/gpu/geometry/BvhQueryImplKernels.cuh

Lines changed: 53 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include "BvhQueryImpl.cuh"
55
#include "pbat/HostDevice.h"
6+
#include "pbat/geometry/DistanceQueries.h"
7+
#include "pbat/geometry/OverlapQueries.h"
68
#include "pbat/gpu/Aliases.h"
79
#include "pbat/gpu/common/Morton.cuh"
810
#include "pbat/gpu/common/Queue.cuh"
@@ -18,6 +20,8 @@ namespace gpu {
1820
namespace geometry {
1921
namespace BvhQueryImplKernels {
2022

23+
namespace mini = pbat::math::linalg::mini;
24+
2125
struct FComputeAabb
2226
{
2327
PBAT_DEVICE void operator()(int s)
@@ -70,7 +74,6 @@ struct FComputeMortonCode
7074
struct FDetectOverlaps
7175
{
7276
using OverlapType = typename BvhQueryImpl::OverlapType;
73-
using Vector3 = pbat::math::linalg::mini::SMatrix<GpuScalar, 3>;
7477

7578
PBAT_DEVICE bool AreSimplicesTopologicallyAdjacent(GpuIndex si, GpuIndex sj) const
7679
{
@@ -90,32 +93,16 @@ struct FDetectOverlaps
9093
// clang-format on
9194
}
9295

93-
PBAT_DEVICE Vector3 Position(auto v) const
94-
{
95-
Vector3 P;
96-
P(0) = x[0][v];
97-
P(1) = x[1][v];
98-
P(2) = x[2][v];
99-
return P;
100-
}
101-
10296
PBAT_DEVICE bool VertexTetrahedronOverlap(GpuIndex v, GpuIndex t) const
10397
{
104-
Vector3 P = Position(queryInds[0][v]);
105-
Vector3 A = Position(inds[0][t]);
106-
Vector3 B = Position(inds[1][t]);
107-
Vector3 C = Position(inds[2][t]);
108-
Vector3 D = Position(inds[3][t]);
109-
auto const PointOutsidePlane =
110-
[](auto const& p, auto const& a, auto const& b, auto const& c) {
111-
using namespace pbat::math::linalg::mini;
112-
GpuScalar const d = Dot(p - a, Cross(b - a, c - a));
113-
return d > GpuScalar{0};
114-
};
115-
bool const bOverlaps =
116-
not(PointOutsidePlane(P, A, B, D) or PointOutsidePlane(P, B, C, D) or
117-
PointOutsidePlane(P, C, A, D) or PointOutsidePlane(P, A, C, B));
118-
return bOverlaps;
98+
using namespace mini;
99+
SVector<GpuScalar, 3> P = FromBuffers<3, 1>(x, queryInds[0][v]);
100+
SVector<GpuScalar, 3> A = FromBuffers<3, 1>(x, inds[0][t]);
101+
SVector<GpuScalar, 3> B = FromBuffers<3, 1>(x, inds[1][t]);
102+
SVector<GpuScalar, 3> C = FromBuffers<3, 1>(x, inds[2][t]);
103+
SVector<GpuScalar, 3> D = FromBuffers<3, 1>(x, inds[3][t]);
104+
using pbat::geometry::OverlapQueries::PointTetrahedron3D;
105+
return PointTetrahedron3D(P, A, B, C, D);
119106
}
120107

121108
PBAT_DEVICE bool AreSimplicesOverlapping(GpuIndex si, GpuIndex sj) const
@@ -197,140 +184,41 @@ struct FContactPairs
197184
{
198185
using OverlapType = typename BvhQueryImpl::OverlapType;
199186
using NearestNeighbourPairType = typename BvhQueryImpl::NearestNeighbourPairType;
200-
using Vector3 = pbat::math::linalg::mini::SMatrix<GpuScalar, 3>;
201187

202-
PBAT_DEVICE Vector3 Position(auto v) const
188+
PBAT_DEVICE GpuScalar MinDistance(
189+
mini::SVector<GpuScalar, 3> const& X,
190+
mini::SVector<GpuScalar, 3> const& L,
191+
mini::SVector<GpuScalar, 3> const& U) const
203192
{
204-
Vector3 P{};
205-
P(0) = x[0][v];
206-
P(1) = x[1][v];
207-
P(2) = x[2][v];
208-
return P;
209-
}
210-
PBAT_DEVICE Vector3 Lower(auto s) const
211-
{
212-
Vector3 P{};
213-
P(0) = b[0][s];
214-
P(1) = b[1][s];
215-
P(2) = b[2][s];
216-
return P;
217-
}
218-
PBAT_DEVICE Vector3 Upper(auto s) const
219-
{
220-
Vector3 P{};
221-
P(0) = e[0][s];
222-
P(1) = e[1][s];
223-
P(2) = e[2][s];
224-
return P;
225-
}
226-
PBAT_DEVICE GpuScalar MinDistance(Vector3 const& X, Vector3 const& L, Vector3 const& U) const
227-
{
228-
using namespace pbat::math::linalg::mini;
229-
Vector3 const DX = Min(U, Max(L, X)) - X;
193+
using namespace mini;
194+
SVector<GpuScalar, 3> const DX = Min(U, Max(L, X)) - X;
230195
return SquaredNorm(DX);
231196
}
232-
PBAT_DEVICE GpuScalar MinMaxDistance(Vector3 const& X, Vector3 const& L, Vector3 const& U) const
197+
PBAT_DEVICE GpuScalar MinMaxDistance(
198+
mini::SVector<GpuScalar, 3> const& X,
199+
mini::SVector<GpuScalar, 3> const& L,
200+
mini::SVector<GpuScalar, 3> const& U) const
233201
{
234-
using namespace pbat::math::linalg::mini;
235-
Vector3 const DXL = Squared(L - X);
236-
Vector3 const DXU = Squared(U - X);
237-
Vector3 const rm = Min(DXL, DXU);
238-
Vector3 const rM = Max(DXL, DXU);
239-
std::array<GpuScalar, 3> const d{
202+
using namespace mini;
203+
SVector<GpuScalar, 3> DXL = Squared(L - X);
204+
SVector<GpuScalar, 3> DXU = Squared(U - X);
205+
SVector<GpuScalar, 3> rm = Min(DXL, DXU);
206+
SVector<GpuScalar, 3> rM = Max(DXL, DXU);
207+
SVector<GpuScalar, 3> d{
240208
rm(0) + rM(1) + rM(2),
241209
rM(0) + rm(1) + rM(2),
242210
rM(0) + rM(1) + rm(2),
243211
};
244-
return min(d[0], min(d[1], d[2]));
212+
return Min(d);
245213
}
246-
PBAT_DEVICE GpuScalar Distance(Vector3 const& P, GpuIndex s) const
214+
PBAT_DEVICE GpuScalar Distance(mini::SVector<GpuScalar, 3> const& P, GpuIndex s) const
247215
{
248-
using namespace pbat::math::linalg::mini;
249-
SMatrix<GpuScalar, 3, 3> ABC;
250-
auto A = ABC.Col(0);
251-
auto B = ABC.Col(1);
252-
auto C = ABC.Col(2);
253-
A = Position(targetInds[0][s]);
254-
B = Position(targetInds[1][s]);
255-
C = Position(targetInds[2][s]);
256-
257-
/**
258-
* Ericson, Christer. Real-time collision detection. Crc Press, 2004. section 5.1.5
259-
*/
260-
261-
// Check if P in vertex region outside A
262-
Vector3 const AB = B - A;
263-
Vector3 const AC = C - A;
264-
Vector3 const AP = P - A;
265-
GpuScalar const d1 = Dot(AB, AP);
266-
GpuScalar const d2 = Dot(AC, AP);
267-
bool const bIsInVertexRegionOutsideA = d1 <= GpuScalar{0} and d2 <= GpuScalar{0};
268-
if (bIsInVertexRegionOutsideA)
269-
{
270-
// barycentric coordinates (1,0,0)
271-
return SquaredNorm(P - A);
272-
}
273-
274-
// Check if P in vertex region outside B
275-
Vector3 const BP = P - B;
276-
GpuScalar const d3 = Dot(AB, BP);
277-
GpuScalar const d4 = Dot(AC, BP);
278-
bool const bIsInVertexRegionOutsideB = d3 >= GpuScalar{0} and d4 <= d3;
279-
if (bIsInVertexRegionOutsideB)
280-
{
281-
// barycentric coordinates (0,1,0)
282-
return SquaredNorm(P - B);
283-
}
284-
285-
// Check if P in edge region of AB, if so return projection of P onto AB
286-
GpuScalar const vc = d1 * d4 - d3 * d2;
287-
bool const bIsInEdgeRegionOfAB =
288-
vc <= GpuScalar{0} and d1 >= GpuScalar{0} and d3 <= GpuScalar{0};
289-
if (bIsInEdgeRegionOfAB)
290-
{
291-
GpuScalar const v = d1 / (d1 - d3);
292-
// barycentric coordinates (1-v,v,0)
293-
return SquaredNorm(P - ((GpuScalar{1} - v) * A + v * B));
294-
}
295-
296-
// Check if P in vertex region outside C
297-
Vector3 const CP = P - C;
298-
GpuScalar const d5 = Dot(AB, CP);
299-
GpuScalar const d6 = Dot(AC, CP);
300-
bool const bIsInVertexRegionOutsideC = d6 >= GpuScalar{0} and d5 <= d6;
301-
if (bIsInVertexRegionOutsideC)
302-
{
303-
// barycentric coordinates (0,0,1)
304-
return SquaredNorm(P - C);
305-
}
306-
307-
// Check if P in edge region of AC, if so return projection of P onto AC
308-
GpuScalar const vb = d5 * d2 - d1 * d6;
309-
bool const bIsInEdgeRegionOfAC =
310-
(vb <= GpuScalar{0} and d2 >= GpuScalar{0} and d6 <= GpuScalar{0});
311-
if (bIsInEdgeRegionOfAC)
312-
{
313-
GpuScalar const w = d2 / (d2 - d6);
314-
// barycentric coordinates (1-w,0,w)
315-
return SquaredNorm(P - (GpuScalar{1} - w) * A + w * C);
316-
}
317-
// Check if P in edge region of BC, if so return projection of P onto BC
318-
GpuScalar const va = d3 * d6 - d5 * d4;
319-
bool const bIsInEdgeRegionOfBC =
320-
va <= GpuScalar{0} and (d4 - d3) >= GpuScalar{0} and (d5 - d6) >= GpuScalar{0};
321-
if (bIsInEdgeRegionOfBC)
322-
{
323-
GpuScalar const w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
324-
// barycentric coordinates (0,1-w,w)
325-
return SquaredNorm(P - ((GpuScalar{1} - w) * B + w * C));
326-
}
327-
// P inside face region. Compute Q through its barycentric coordinates (u,v,w)
328-
GpuScalar const denom = GpuScalar{1} / (va + vb + vc);
329-
SMatrix<GpuScalar, 3> uvw;
330-
uvw(1) = vb * denom;
331-
uvw(2) = vc * denom;
332-
uvw(0) = GpuScalar{1} - uvw(1) - uvw(2);
333-
return SquaredNorm(P - ABC * uvw);
216+
using namespace mini;
217+
auto A = FromBuffers<3, 1>(x, targetInds[0][s]);
218+
auto B = FromBuffers<3, 1>(x, targetInds[1][s]);
219+
auto C = FromBuffers<3, 1>(x, targetInds[2][s]);
220+
using pbat::geometry::DistanceQueries::PointTriangle;
221+
return PointTriangle(P, A, B, C);
334222
}
335223

336224
struct BoxOrSimplex
@@ -342,14 +230,19 @@ struct FContactPairs
342230
struct BranchAndBound
343231
{
344232
PBAT_DEVICE
345-
BranchAndBound(Vector3 const& X, GpuScalar R, GpuScalar dzero, GpuIndex sv, GpuIndex v)
233+
BranchAndBound(
234+
mini::SVector<GpuScalar, 3> const& X,
235+
GpuScalar R,
236+
GpuScalar dzero,
237+
GpuIndex sv,
238+
GpuIndex v)
346239
: stack{}, nearest{}, X(X), R(R), dzero(dzero), sv(sv), v(v)
347240
{
348241
}
349242

350243
common::Stack<BoxOrSimplex, 64> stack;
351244
common::Queue<GpuIndex, 8> nearest;
352-
Vector3 X;
245+
mini::SVector<GpuScalar, 3> X;
353246
GpuScalar R;
354247
GpuScalar dzero;
355248
GpuIndex sv;
@@ -396,10 +289,14 @@ struct FContactPairs
396289

397290
PBAT_DEVICE void operator()(OverlapType const& o)
398291
{
292+
using namespace mini;
399293
// Branch and bound over BVH
400294
GpuIndex const v = queryInds[0][o.first];
401-
BranchAndBound traversal{Position(v), R, dzero, o.first, v};
402-
Push(traversal, 0, MinDistance(traversal.X, Lower(0), Upper(0)));
295+
BranchAndBound traversal{FromBuffers<3, 1>(x, v), R, dzero, o.first, v};
296+
Push(
297+
traversal,
298+
0,
299+
MinDistance(traversal.X, FromBuffers<3, 1>(b, 0), FromBuffers<3, 1>(e, 0)));
403300
do
404301
{
405302
assert(not traversal.stack.IsFull());
@@ -410,10 +307,10 @@ struct FContactPairs
410307
GpuIndex const lc = child[0][bos.node];
411308
GpuIndex const rc = child[1][bos.node];
412309

413-
Vector3 const LL = Lower(lc);
414-
Vector3 const LU = Upper(lc);
415-
Vector3 const RL = Lower(rc);
416-
Vector3 const RU = Upper(rc);
310+
mini::SVector<GpuScalar, 3> const LL = FromBuffers<3, 1>(b, lc);
311+
mini::SVector<GpuScalar, 3> const LU = FromBuffers<3, 1>(e, lc);
312+
mini::SVector<GpuScalar, 3> const RL = FromBuffers<3, 1>(b, rc);
313+
mini::SVector<GpuScalar, 3> const RU = FromBuffers<3, 1>(e, rc);
417314

418315
GpuScalar Ldmin = MinDistance(traversal.X, LL, LU);
419316
GpuScalar Rdmin = MinDistance(traversal.X, RL, RU);

source/pbat/math/linalg/mini/Matrix.h

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -258,10 +258,9 @@ template <CMatrix TMatrix, class IndexType>
258258
PBAT_HOST_DEVICE void
259259
ToFlatBuffer(TMatrix const& A, typename TMatrix::ScalarType* buf, IndexType bi)
260260
{
261-
using ScalarType = typename TMatrix::ScalarType;
262-
auto constexpr M = TMatrix::kRows;
263-
auto constexpr N = TMatrix::kCols;
264-
FromFlatBuffer<M, N, ScalarType>(buf, bi) = A;
261+
auto constexpr M = TMatrix::kRows;
262+
auto constexpr N = TMatrix::kCols;
263+
FromFlatBuffer<M, N>(buf, bi) = A;
265264
}
266265

267266
template <CMatrix TMatrix, CMatrix TIndexMatrix>
@@ -296,7 +295,7 @@ PBAT_HOST_DEVICE auto FromBuffers(std::array<TScalar*, M> buf, IndexType bi)
296295
using ScalarType = std::remove_const_t<TScalar>;
297296
SMatrix<ScalarType, M, N> A{};
298297
using pbat::common::ForRange;
299-
ForRange<0, M>([&]<auto i>() { A.Row(i) = FromFlatBuffer<1, N, ScalarType>(buf[i], bi); });
298+
ForRange<0, M>([&]<auto i>() { A.Row(i) = FromFlatBuffer<1, N>(buf[i], bi); });
300299
return A;
301300
}
302301

@@ -310,8 +309,7 @@ PBAT_HOST_DEVICE auto FromBuffers(std::array<TScalar*, K> buf, TIndexMatrix cons
310309
using ScalarType = std::remove_cvref_t<TScalar>;
311310
SMatrix<ScalarType, K * M, N> A{};
312311
using pbat::common::ForRange;
313-
ForRange<0, K>(
314-
[&]<auto k>() { A.Slice<M, N>(k * M, 0) = FromFlatBuffer<ScalarType>(buf[k], inds); });
312+
ForRange<0, K>([&]<auto k>() { A.Slice<M, N>(k * M, 0) = FromFlatBuffer(buf[k], inds); });
315313
return A;
316314
}
317315

@@ -321,9 +319,8 @@ ToBuffers(TMatrix const& A, std::array<typename TMatrix::ScalarType*, M> buf, In
321319
{
322320
static_assert(M == TMatrix::kRows, "A must have same rows as number of buffers");
323321
auto constexpr N = TMatrix::kCols;
324-
using ScalarType = typename TMatrix::ScalarType;
325322
using pbat::common::ForRange;
326-
ForRange<0, M>([&]<auto i>() { FromFlatBuffer<1, N, ScalarType>(buf[i], bi) = A.Row(i); });
323+
ForRange<0, M>([&]<auto i>() { FromFlatBuffer<1, N>(buf[i], bi) = A.Row(i); });
327324
}
328325

329326
template <CMatrix TMatrix, CMatrix TIndexMatrix, int K>

0 commit comments

Comments
 (0)