Skip to content

Commit 453dced

Browse files
author
Teseo Schneider
committed
added fucntions for tri and default lambdas
1 parent 52517ab commit 453dced

File tree

3 files changed

+119
-12
lines changed

3 files changed

+119
-12
lines changed

src/SimpleBVH/BVH.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,92 @@ void point_segment_squared_distance(
2525
dist = (point - closest_point).squaredNorm();
2626
}
2727

28+
void point_triangle_squared_distance(
29+
const VectorMax3d& x,
30+
const std::array<VectorMax3d, 3>& f,
31+
VectorMax3d& pt,
32+
double& dist)
33+
{
34+
const VectorMax3d& pa = f[0];
35+
const VectorMax3d& pb = f[1];
36+
const VectorMax3d& pc = f[2];
37+
38+
// source: real time collision detection
39+
// check if x in vertex region outside pa
40+
VectorMax3d ab = pb - pa;
41+
VectorMax3d ac = pc - pa;
42+
VectorMax3d ax = x - pa;
43+
const double d1 = ab.dot(ax);
44+
const double d2 = ac.dot(ax);
45+
if (d1 <= 0 && d2 <= 0) {
46+
// barycentric coordinates (1, 0, 0)
47+
pt = pa;
48+
dist = (x - pt).norm();
49+
return;
50+
}
51+
52+
// check if x in vertex region outside pb
53+
VectorMax3d bx = x - pb;
54+
const double d3 = ab.dot(bx);
55+
const double d4 = ac.dot(bx);
56+
if (d3 >= 0.0f && d4 <= d3) {
57+
// barycentric coordinates (0, 1, 0)
58+
pt = pb;
59+
dist = (x - pt).norm();
60+
return;
61+
}
62+
63+
// check if x in vertex region outside pc
64+
VectorMax3d cx = x - pc;
65+
const double d5 = ab.dot(cx);
66+
const double d6 = ac.dot(cx);
67+
if (d6 >= 0.0f && d5 <= d6) {
68+
// barycentric coordinates (0, 0, 1)
69+
pt = pc;
70+
dist = (x - pt).norm();
71+
return;
72+
}
73+
74+
// check if x in edge region of ab, if so return projection of x onto ab
75+
const double vc = d1 * d4 - d3 * d2;
76+
if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) {
77+
// barycentric coordinates (1 - v, v, 0)
78+
const double v = d1 / (d1 - d3);
79+
pt = pa + ab * v;
80+
dist = (x - pt).norm();
81+
return;
82+
}
83+
84+
// check if x in edge region of ac, if so return projection of x onto ac
85+
const double vb = d5 * d2 - d1 * d6;
86+
if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) {
87+
// barycentric coordinates (1 - w, 0, w)
88+
const double w = d2 / (d2 - d6);
89+
pt = pa + ac * w;
90+
dist = (x - pt).norm();
91+
return;
92+
}
93+
94+
// check if x in edge region of bc, if so return projection of x onto bc
95+
const double va = d3 * d6 - d5 * d4;
96+
if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) {
97+
// barycentric coordinates (0, 1 - w, w)
98+
const double w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
99+
pt = pb + (pc - pb) * w;
100+
dist = (x - pt).norm();
101+
return;
102+
}
103+
104+
// x inside face region. Compute pt through its barycentric coordinates (u,
105+
// v, w)
106+
const double denom = 1 / (va + vb + vc);
107+
const double v = vb * denom;
108+
const double w = vc * denom;
109+
110+
pt = pa + ab * v + ac * w; //= u*a + v*b + w*c, u = va*denom = 1.0f - v - w
111+
dist = (x - pt).norm();
112+
}
113+
28114
namespace {
29115
bool box_box_intersection(
30116
const VectorMax3d& min1,
@@ -245,6 +331,9 @@ void BVH::init(
245331
assert(F.cols() == 3 || F.cols() == 2);
246332
assert(V.cols() == 3 || V.cols() == 2);
247333

334+
vertices = V;
335+
faces = F;
336+
248337
std::vector<std::array<VectorMax3d, 2>> cornerlist(F.rows());
249338
if (F.cols() == 3) {
250339
for (int i = 0; i < F.rows(); i++) {
@@ -264,6 +353,18 @@ void BVH::init(
264353
cornerlist[i][0] = min.transpose();
265354
cornerlist[i][1] = max.transpose();
266355
}
356+
357+
set_leaf_distance_callback(
358+
[&](const VectorMax3d& p, int f, VectorMax3d& cp, double& dist) {
359+
point_triangle_squared_distance(
360+
p,
361+
{ { vertices.row(faces(f, 0)), vertices.row(faces(f, 1)),
362+
vertices.row(faces(f, 2)) } },
363+
cp, dist);
364+
});
365+
set_get_point_callback(
366+
[&](int f) { return vertices.row(faces(f, 0)); });
367+
267368
} else if (F.cols() == 2) {
268369
for (int i = 0; i < F.rows(); i++) {
269370
const Eigen::RowVector2i face = F.row(i);
@@ -280,6 +381,15 @@ void BVH::init(
280381
cornerlist[i][0] = min.transpose();
281382
cornerlist[i][1] = max.transpose();
282383
}
384+
385+
set_leaf_distance_callback([&](const VectorMax3d& p, int f,
386+
VectorMax3d& cp, double& dist) {
387+
point_segment_squared_distance(
388+
p, { { vertices.row(faces(f, 0)), vertices.row(faces(f, 1)) } },
389+
cp, dist);
390+
});
391+
set_get_point_callback(
392+
[&](int f) { return vertices.row(faces(f, 0)); });
283393
}
284394

285395
init(cornerlist);

src/SimpleBVH/BVH.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ void point_segment_squared_distance(
2020
VectorMax3d& closest_point,
2121
double& dist);
2222

23+
void point_triangle_squared_distance(
24+
const VectorMax3d& point,
25+
const std::array<VectorMax3d, 3>& f,
26+
VectorMax3d& closest_point,
27+
double& dist);
28+
2329
class BVH {
2430
public:
2531
void init(const std::vector<std::array<VectorMax3d, 2>>& cornerlist);
@@ -124,5 +130,8 @@ class BVH {
124130
size_t n_corners = -1;
125131
LeafCallback leafCallback;
126132
GetPointCallback getPoint;
133+
134+
Eigen::MatrixXd vertices;
135+
Eigen::MatrixXi faces;
127136
};
128137
} // namespace SimpleBVH

tests/tests.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,6 @@ TEST_CASE("test_distance", "[tests]")
5858
VectorMax3d nearest_point;
5959
double sq_dist;
6060
bvh.init(pts, edges, 1e-10);
61-
bvh.set_leaf_distance_callback([&](const VectorMax3d& p, int f,
62-
VectorMax3d& cp, double& dist) {
63-
point_segment_squared_distance(
64-
p, { { pts.row(edges(f, 0)), pts.row(edges(f, 1)) } }, cp, dist);
65-
});
66-
bvh.set_get_point_callback([&](int f) { return pts.row(edges(f, 0)); });
6761
bvh.nearest_facet(Eigen::Vector3d(-1, -1, -1), nearest_point, sq_dist);
6862

6963
CHECK(pts.row(0) == nearest_point.transpose());
@@ -94,12 +88,6 @@ TEST_CASE("test_distance_2d", "[tests]")
9488
VectorMax3d nearest_point;
9589
double sq_dist;
9690
bvh.init(pts, edges, 1e-10);
97-
bvh.set_leaf_distance_callback([&](const VectorMax3d& p, int f,
98-
VectorMax3d& cp, double& dist) {
99-
point_segment_squared_distance(
100-
p, { { pts.row(edges(f, 0)), pts.row(edges(f, 1)) } }, cp, dist);
101-
});
102-
bvh.set_get_point_callback([&](int f) { return pts.row(edges(f, 0)); });
10391
bvh.nearest_facet(Eigen::Vector2d(-1, -1), nearest_point, sq_dist);
10492

10593
CHECK(pts.row(0) == nearest_point.transpose());

0 commit comments

Comments
 (0)