Skip to content

Commit 428cff7

Browse files
committed
Document CPU BVHs
1 parent 1a0db1d commit 428cff7

File tree

5 files changed

+385
-267
lines changed

5 files changed

+385
-267
lines changed

source/pbat/geometry/TetrahedralAabbHierarchy.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ class TetrahedralAabbHierarchy : public BoundingVolumeHierarchy<
4848
/**
4949
* @brief Construct a TetrahedralAabbHierarchy from a tetrahedral mesh (V,C)
5050
* @param V `|kDims|x|# verts|` vertex positions
51-
* @param C `4x|# tetrahedra|` cell indices into V
52-
* @param maxPointsInLeaf Maximum number of points in a leaf node
51+
* @param C `4x|# tetrahedra|` cell vertex indices into V
52+
* @param maxPointsInLeaf Maximum number of simplices in a leaf node
5353
*/
5454
PBAT_API TetrahedralAabbHierarchy(
5555
Eigen::Ref<MatrixX const> const& V,

source/pbat/geometry/TriangleAabbHierarchy.cpp

Lines changed: 169 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,169 @@
11
#include "TriangleAabbHierarchy.h"
22

3+
namespace pbat::geometry {
4+
5+
TriangleAabbHierarchy3D::TriangleAabbHierarchy3D(
6+
Eigen::Ref<MatrixX const> const& V,
7+
Eigen::Ref<IndexMatrixX const> const& C,
8+
std::size_t maxPointsInLeaf)
9+
: V(V), C(C)
10+
{
11+
PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.TriangleAabbHierarchy3D.Construct");
12+
auto constexpr kRowsC = static_cast<int>(PrimitiveType::RowsAtCompileTime);
13+
if (V.rows() != kDims and C.rows() != kRowsC)
14+
{
15+
std::string const what = fmt::format(
16+
"Expected vertex positions V of dimensions {}x|#verts| and triangle vertex indices "
17+
"C of dimensions {}x|#triangles|, but got V={}x{} and C={}x{}.",
18+
kDims,
19+
kRowsC,
20+
V.rows(),
21+
V.cols(),
22+
C.rows(),
23+
C.cols());
24+
throw std::invalid_argument(what);
25+
}
26+
Construct(static_cast<std::size_t>(C.cols()), maxPointsInLeaf);
27+
}
28+
29+
TriangleAabbHierarchy3D::PrimitiveType TriangleAabbHierarchy3D::Primitive(Index p) const
30+
{
31+
PrimitiveType const inds = C.col(p);
32+
return inds;
33+
}
34+
35+
Vector<TriangleAabbHierarchy3D::kDims>
36+
TriangleAabbHierarchy3D::PrimitiveLocation(PrimitiveType const& primitive) const
37+
{
38+
return V(Eigen::placeholders::all, primitive).rowwise().mean();
39+
}
40+
41+
void TriangleAabbHierarchy3D::Update()
42+
{
43+
PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.TriangleAabbHierarchy3D.Update");
44+
BaseType::Update();
45+
}
46+
47+
IndexMatrixX
48+
TriangleAabbHierarchy3D::OverlappingPrimitives(SelfType const& bvh, std::size_t reserve) const
49+
{
50+
PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.TriangleAabbHierarchy3D.OverlappingPrimitives");
51+
using math::linalg::mini::FromEigen;
52+
return this->OverlappingPrimitivesImpl<SelfType, BoundingVolumeType, PrimitiveType, kDims>(
53+
bvh,
54+
[](BoundingVolumeType const& bv1, BoundingVolumeType const& bv2) -> bool {
55+
return OverlapQueries::AxisAlignedBoundingBoxes(
56+
FromEigen(bv1.min()),
57+
FromEigen(bv1.max()),
58+
FromEigen(bv2.min()),
59+
FromEigen(bv2.max()));
60+
},
61+
[&](PrimitiveType const& p1, PrimitiveType const& p2) -> bool {
62+
auto const V1 = V(Eigen::placeholders::all, p1);
63+
auto const V2 = bvh.V(Eigen::placeholders::all, p2);
64+
return OverlapQueries::Triangles3D(
65+
FromEigen(V1.col(0).head<kDims>()),
66+
FromEigen(V1.col(1).head<kDims>()),
67+
FromEigen(V1.col(2).head<kDims>()),
68+
FromEigen(V2.col(0).head<kDims>()),
69+
FromEigen(V2.col(1).head<kDims>()),
70+
FromEigen(V2.col(2).head<kDims>()));
71+
},
72+
[&](PrimitiveType const& p1, PrimitiveType const& p2) -> bool {
73+
if (this == &bvh)
74+
{
75+
for (auto i : p1)
76+
for (auto j : p2)
77+
if (i == j)
78+
return true;
79+
}
80+
return false;
81+
},
82+
reserve);
83+
}
84+
85+
TriangleAabbHierarchy2D::TriangleAabbHierarchy2D(
86+
Eigen::Ref<MatrixX const> const& V,
87+
Eigen::Ref<IndexMatrixX const> const& C,
88+
std::size_t maxPointsInLeaf)
89+
: V(V), C(C)
90+
{
91+
PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.TriangleAabbHierarchy2D.Construct");
92+
auto constexpr kRowsC = static_cast<int>(PrimitiveType::RowsAtCompileTime);
93+
if (V.rows() != kDims and C.rows() != kRowsC)
94+
{
95+
std::string const what = fmt::format(
96+
"Expected vertex positions V of dimensions {}x|#verts| and triangle vertex indices "
97+
"C of dimensions {}x|#triangles|, but got V={}x{} and C={}x{}.",
98+
kDims,
99+
kRowsC,
100+
V.rows(),
101+
V.cols(),
102+
C.rows(),
103+
C.cols());
104+
throw std::invalid_argument(what);
105+
}
106+
Construct(static_cast<std::size_t>(C.cols()), maxPointsInLeaf);
107+
}
108+
109+
TriangleAabbHierarchy2D::PrimitiveType TriangleAabbHierarchy2D::Primitive(Index p) const
110+
{
111+
PrimitiveType const inds = C.col(p);
112+
return inds;
113+
}
114+
115+
Vector<TriangleAabbHierarchy2D::kDims>
116+
TriangleAabbHierarchy2D::PrimitiveLocation(PrimitiveType const& primitive) const
117+
{
118+
return V(Eigen::placeholders::all, primitive).rowwise().mean();
119+
}
120+
121+
void TriangleAabbHierarchy2D::Update()
122+
{
123+
PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.TriangleAabbHierarchy2D.Update");
124+
BaseType::Update();
125+
}
126+
127+
IndexMatrixX
128+
TriangleAabbHierarchy2D::OverlappingPrimitives(SelfType const& bvh, std::size_t reserve) const
129+
{
130+
PBAT_PROFILE_NAMED_SCOPE("pbat.geometry.TriangleAabbHierarchy2D.OverlappingPrimitives");
131+
using math::linalg::mini::FromEigen;
132+
return this->OverlappingPrimitivesImpl<SelfType, BoundingVolumeType, PrimitiveType, kDims>(
133+
bvh,
134+
[](BoundingVolumeType const& bv1, BoundingVolumeType const& bv2) -> bool {
135+
return OverlapQueries::AxisAlignedBoundingBoxes(
136+
FromEigen(bv1.min()),
137+
FromEigen(bv1.max()),
138+
FromEigen(bv2.min()),
139+
FromEigen(bv2.max()));
140+
},
141+
[&](PrimitiveType const& p1, PrimitiveType const& p2) -> bool {
142+
auto const V1 = V(Eigen::placeholders::all, p1);
143+
auto const V2 = bvh.V(Eigen::placeholders::all, p2);
144+
return OverlapQueries::Triangles2D(
145+
FromEigen(V1.col(0).head<kDims>()),
146+
FromEigen(V1.col(1).head<kDims>()),
147+
FromEigen(V1.col(2).head<kDims>()),
148+
FromEigen(V2.col(0).head<kDims>()),
149+
FromEigen(V2.col(1).head<kDims>()),
150+
FromEigen(V2.col(2).head<kDims>()));
151+
},
152+
[&](PrimitiveType const& p1, PrimitiveType const& p2) -> bool {
153+
if (this == &bvh)
154+
{
155+
for (auto i : p1)
156+
for (auto j : p2)
157+
if (i == j)
158+
return true;
159+
}
160+
return false;
161+
},
162+
reserve);
163+
}
164+
165+
} // namespace pbat::geometry
166+
3167
#include "pbat/Aliases.h"
4168
#include "pbat/math/linalg/mini/Eigen.h"
5169

@@ -23,7 +187,7 @@ TEST_CASE("[geometry] TriangleAabbHierarchy")
23187
// clang-format on
24188
std::size_t constexpr kMaxPointsInLeaf = 1ULL;
25189
auto constexpr kDims = 2;
26-
geometry::TriangleAabbHierarchy<kDims> bvh(V, C, kMaxPointsInLeaf);
190+
geometry::TriangleAabbHierarchy2D bvh(V, C, kMaxPointsInLeaf);
27191
CHECK_EQ(bvh.V.rows(), V.rows());
28192
CHECK_EQ(bvh.V.cols(), V.cols());
29193
CHECK_EQ(bvh.C.rows(), C.rows());
@@ -54,7 +218,7 @@ TEST_CASE("[geometry] TriangleAabbHierarchy")
54218
CHECK_GT(primitiveIdx, Index{-1});
55219
}
56220

57-
geometry::TriangleAabbHierarchy<kDims> const otherBvh{bvh};
221+
geometry::TriangleAabbHierarchy2D const otherBvh{bvh};
58222
IndexMatrix<2, Eigen::Dynamic> const overlappingP = bvh.OverlappingPrimitives(otherBvh);
59223
auto const nPrimitives = static_cast<std::size_t>(C.cols());
60224
std::vector<std::size_t> overlapCounts(nPrimitives, 0ULL);
@@ -73,7 +237,7 @@ TEST_CASE("[geometry] TriangleAabbHierarchy")
73237
CHECK_EQ(nSelfOverlappingPrimitives, 0);
74238

75239
// If points haven't changed, update should preserve the same volumes.
76-
std::vector<geometry::TriangleAabbHierarchy<kDims>::BoundingVolumeType> const bvsExpected =
240+
std::vector<geometry::TriangleAabbHierarchy2D::BoundingVolumeType> const bvsExpected =
77241
bvh.GetBoundingVolumes();
78242
bvh.Update();
79243
auto const nBvs = bvh.GetBoundingVolumes().size();
@@ -109,7 +273,7 @@ TEST_CASE("[geometry] TriangleAabbHierarchy")
109273

110274
std::size_t constexpr kMaxPointsInLeaf = 1ULL;
111275
auto constexpr kDims = 3;
112-
geometry::TriangleAabbHierarchy<kDims> bvh(V, C, kMaxPointsInLeaf);
276+
geometry::TriangleAabbHierarchy3D bvh(V, C, kMaxPointsInLeaf);
113277
CHECK_EQ(bvh.V.rows(), V.rows());
114278
CHECK_EQ(bvh.V.cols(), V.cols());
115279
CHECK_EQ(bvh.C.rows(), C.rows());
@@ -154,7 +318,7 @@ TEST_CASE("[geometry] TriangleAabbHierarchy")
154318
CHECK_EQ(nSelfOverlappingPrimitives, 0);
155319

156320
// If points haven't changed, update should preserve the same volumes.
157-
std::vector<geometry::TriangleAabbHierarchy<kDims>::BoundingVolumeType> const bvsExpected =
321+
std::vector<geometry::TriangleAabbHierarchy3D::BoundingVolumeType> const bvsExpected =
158322
bvh.GetBoundingVolumes();
159323
bvh.Update();
160324
auto const nBvs = bvh.GetBoundingVolumes().size();

0 commit comments

Comments
 (0)