Skip to content

Commit 49166fe

Browse files
committed
Replace VectorMax3d by Vector3d.
The reason behind this is that the performance of VectorMax3d was (at least on Windows) 2x slower. Therefore, now everything internally works with a 3d vector. Convencience Functionality for 2d access was added but might not have optimal performance.
1 parent 786e248 commit 49166fe

File tree

3 files changed

+191
-119
lines changed

3 files changed

+191
-119
lines changed

src/SimpleBVH/BVH.cpp

Lines changed: 78 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,39 @@
66
namespace SimpleBVH {
77

88
void point_segment_squared_distance(
9-
const VectorMax3d& point,
10-
const std::array<VectorMax3d, 2>& f,
11-
VectorMax3d& closest_point,
9+
const Vector3d& point,
10+
const Vector3d& pa,
11+
const Vector3d& pb,
12+
Vector3d& closest_point,
1213
double& dist)
1314
{
14-
const double l2 = (f[0] - f[1]).squaredNorm();
15-
const double t = (point - f[0]).dot(f[1] - f[0]);
15+
const double l2 = (pa - pb).squaredNorm();
16+
const double t = (point - pa).dot(pb - pa);
1617
if (t <= 0.0 || l2 == 0.0) {
17-
closest_point = f[0];
18+
closest_point = pa;
1819
} else if (t > l2) {
19-
closest_point = f[1];
20+
closest_point = pb;
2021
} else {
2122
const double lambda1 = t / l2;
2223
const double lambda0 = 1.0 - lambda1;
23-
closest_point = lambda0 * f[0] + lambda1 * f[1];
24+
closest_point = lambda0 * pa + lambda1 * pb;
2425
}
2526
dist = (point - closest_point).squaredNorm();
2627
}
2728

2829
void point_triangle_squared_distance(
29-
const VectorMax3d& x,
30-
const std::array<VectorMax3d, 3>& f,
31-
VectorMax3d& pt,
30+
const Vector3d& x,
31+
const Vector3d& pa,
32+
const Vector3d& pb,
33+
const Vector3d& pc,
34+
Vector3d& pt,
3235
double& dist)
3336
{
34-
const VectorMax3d& pa = f[0];
35-
const VectorMax3d& pb = f[1];
36-
const VectorMax3d& pc = f[2];
37-
3837
// source: real time collision detection
3938
// check if x in vertex region outside pa
40-
VectorMax3d ab = pb - pa;
41-
VectorMax3d ac = pc - pa;
42-
VectorMax3d ax = x - pa;
39+
Vector3d ab = pb - pa;
40+
Vector3d ac = pc - pa;
41+
Vector3d ax = x - pa;
4342
const double d1 = ab.dot(ax);
4443
const double d2 = ac.dot(ax);
4544
if (d1 <= 0 && d2 <= 0) {
@@ -50,7 +49,7 @@ void point_triangle_squared_distance(
5049
}
5150

5251
// check if x in vertex region outside pb
53-
VectorMax3d bx = x - pb;
52+
Vector3d bx = x - pb;
5453
const double d3 = ab.dot(bx);
5554
const double d4 = ac.dot(bx);
5655
if (d3 >= 0.0f && d4 <= d3) {
@@ -61,7 +60,7 @@ void point_triangle_squared_distance(
6160
}
6261

6362
// check if x in vertex region outside pc
64-
VectorMax3d cx = x - pc;
63+
Vector3d cx = x - pc;
6564
const double d5 = ab.dot(cx);
6665
const double d6 = ac.dot(cx);
6766
if (d6 >= 0.0f && d5 <= d6) {
@@ -113,10 +112,10 @@ void point_triangle_squared_distance(
113112

114113
namespace {
115114
bool box_box_intersection(
116-
const VectorMax3d& min1,
117-
const VectorMax3d& max1,
118-
const VectorMax3d& min2,
119-
const VectorMax3d& max2)
115+
const Vector3d& min1,
116+
const Vector3d& max1,
117+
const Vector3d& min2,
118+
const Vector3d& max2)
120119
{
121120
if (min1.size() == 3) {
122121
if (max1[0] < min2[0] || max1[1] < min2[1] || max1[2] < min2[2])
@@ -134,27 +133,27 @@ namespace {
134133
}
135134

136135
double point_box_center_squared_distance(
137-
const VectorMax3d& p, const std::array<VectorMax3d, 2>& B)
136+
const Vector3d& p, const std::array<Vector3d, 2>& B)
138137
{
139138
return (p - (B[0] + B[1]) / 2).squaredNorm();
140139
}
141140

142141
double inner_point_box_squared_distance(
143-
const VectorMax3d& p, const std::array<VectorMax3d, 2>& B)
142+
const Vector3d& p, const std::array<Vector3d, 2>& B)
144143
{
145144
assert(p.size() == B[0].size());
146145

147-
double result = std::pow(p[0] - B[0][0], 2);
148-
result = std::min(result, std::pow(p[0] - B[1][0], 2));
146+
double result = (p[0] - B[0][0]) * (p[0] - B[0][0]);
147+
result = std::min(result, (p[0] - B[1][0]) * (p[0] - B[1][0]));
149148
for (int c = 1; c < p.size(); ++c) {
150-
result = std::min(result, std::pow(p[c] - B[0][c], 2));
151-
result = std::min(result, std::pow(p[c] - B[1][c], 2));
149+
result = std::min(result, (p[c] - B[0][c]) * (p[c] - B[0][c]));
150+
result = std::min(result, (p[c] - B[1][c]) * (p[c] - B[1][c]));
152151
}
153152
return result;
154153
}
155154

156155
double point_box_signed_squared_distance(
157-
const VectorMax3d& p, const std::array<VectorMax3d, 2>& B)
156+
const Vector3d& p, const std::array<Vector3d, 2>& B)
158157
{
159158
assert(p.size() == B[0].size());
160159

@@ -163,10 +162,10 @@ namespace {
163162
for (int c = 0; c < p.size(); c++) {
164163
if (p[c] < B[0][c]) {
165164
inside = false;
166-
result += std::pow(p[c] - B[0][c], 2);
165+
result += (p[c] - B[0][c]) * (p[c] - B[0][c]);
167166
} else if (p[c] > B[1][c]) {
168167
inside = false;
169-
result += std::pow(p[c] - B[1][c], 2);
168+
result += (p[c] - B[1][c]) * (p[c] - B[1][c]);
170169
}
171170
}
172171
if (inside) {
@@ -177,7 +176,7 @@ namespace {
177176
} // namespace
178177

179178
void BVH::init_boxes_recursive(
180-
const std::vector<std::array<VectorMax3d, 2>>& cornerlist,
179+
const std::vector<std::array<Vector3d, 2>>& cornerlist,
181180
int node_index,
182181
int b,
183182
int e)
@@ -210,8 +209,8 @@ void BVH::init_boxes_recursive(
210209
}
211210

212211
void BVH::box_search_recursive(
213-
const VectorMax3d& bbd0,
214-
const VectorMax3d& bbd1,
212+
const Vector3d& bbd0,
213+
const Vector3d& bbd1,
215214
std::vector<unsigned int>& list,
216215
int n,
217216
int b,
@@ -256,7 +255,7 @@ int BVH::max_node_index(int node_index, int b, int e)
256255
return std::max(max_node_index(childl, b, m), max_node_index(childr, m, e));
257256
}
258257

259-
void BVH::init(const std::vector<std::array<VectorMax3d, 2>>& cornerlist)
258+
void BVH::init(const std::vector<std::array<Vector3d, 2>>& cornerlist)
260259
{
261260
n_corners = cornerlist.size();
262261

@@ -265,16 +264,16 @@ void BVH::init(const std::vector<std::array<VectorMax3d, 2>>& cornerlist)
265264
box_centers.row(i) = (cornerlist[i][0] + cornerlist[i][1]) / 2;
266265
}
267266

268-
const VectorMax3d vmin = box_centers.colwise().minCoeff();
269-
const VectorMax3d vmax = box_centers.colwise().maxCoeff();
270-
const VectorMax3d center = (vmin + vmax) / 2;
267+
const Vector3d vmin = box_centers.colwise().minCoeff();
268+
const Vector3d vmax = box_centers.colwise().maxCoeff();
269+
const Vector3d center = (vmin + vmax) / 2;
271270
for (int i = 0; i < n_corners; i++) {
272271
// make box centered at origin
273272
box_centers.row(i) -= center;
274273
}
275274

276275
// after placing box at origin, vmax and vmin are symetric.
277-
const VectorMax3d scale_point = vmax - center;
276+
const Vector3d scale_point = vmax - center;
278277
const double scale = scale_point.lpNorm<Eigen::Infinity>();
279278
// if the box is too big, resize it
280279
if (scale > 100) {
@@ -307,7 +306,7 @@ void BVH::init(const std::vector<std::array<VectorMax3d, 2>>& cornerlist)
307306
new2old[i] = list[i].order;
308307
}
309308

310-
std::vector<std::array<VectorMax3d, 2>> sorted_cornerlist(n_corners);
309+
std::vector<std::array<Vector3d, 2>> sorted_cornerlist(n_corners);
311310

312311
for (int i = 0; i < n_corners; i++) {
313312
sorted_cornerlist[i] = cornerlist[list[i].order];
@@ -331,24 +330,30 @@ void BVH::init(
331330
assert(F.cols() == 3 || F.cols() == 2);
332331
assert(V.cols() == 3 || V.cols() == 2);
333332

334-
vertices = V;
333+
if (V.cols() == 3) {
334+
vertices = V;
335+
} else {
336+
vertices.resize(V.rows(), 3);
337+
vertices.setZero();
338+
vertices.block(0, 0, V.rows(), V.cols()) = V;
339+
}
335340
faces = F;
336341

337-
std::vector<std::array<VectorMax3d, 2>> cornerlist(F.rows());
342+
std::vector<std::array<Vector3d, 2>> cornerlist(F.rows());
338343
if (F.cols() == 3) {
339344
for (int i = 0; i < F.rows(); i++) {
340345
const Eigen::RowVector3i face = F.row(i);
341-
const VectorMax3d v0 = V.row(face(0));
342-
const VectorMax3d v1 = V.row(face(1));
343-
const VectorMax3d v2 = V.row(face(2));
346+
const Vector3d v0 = V.row(face(0));
347+
const Vector3d v1 = V.row(face(1));
348+
const Vector3d v2 = V.row(face(2));
344349

345350
Eigen::MatrixXd tmp(3, v0.size());
346351
tmp.row(0) = v0.transpose();
347352
tmp.row(1) = v1.transpose();
348353
tmp.row(2) = v2.transpose();
349354

350-
const VectorMax3d min = tmp.colwise().minCoeff().array() - tol;
351-
const VectorMax3d max = tmp.colwise().maxCoeff().array() + tol;
355+
const Vector3d min = tmp.colwise().minCoeff().array() - tol;
356+
const Vector3d max = tmp.colwise().maxCoeff().array() + tol;
352357

353358
cornerlist[i][0] = min.transpose();
354359
cornerlist[i][1] = max.transpose();
@@ -357,15 +362,15 @@ void BVH::init(
357362
} else if (F.cols() == 2) {
358363
for (int i = 0; i < F.rows(); i++) {
359364
const Eigen::RowVector2i face = F.row(i);
360-
const VectorMax3d v0 = V.row(face(0));
361-
const VectorMax3d v1 = V.row(face(1));
365+
const Vector3d v0 = vertices.row(face(0));
366+
const Vector3d v1 = vertices.row(face(1));
362367

363368
Eigen::MatrixXd tmp(2, v0.size());
364369
tmp.row(0) = v0.transpose();
365370
tmp.row(1) = v1.transpose();
366371

367-
const VectorMax3d min = tmp.colwise().minCoeff().array() - tol;
368-
const VectorMax3d max = tmp.colwise().maxCoeff().array() + tol;
372+
const Vector3d min = tmp.colwise().minCoeff().array() - tol;
373+
const Vector3d max = tmp.colwise().maxCoeff().array() + tol;
369374

370375
cornerlist[i][0] = min.transpose();
371376
cornerlist[i][1] = max.transpose();
@@ -376,7 +381,7 @@ void BVH::init(
376381
}
377382

378383
bool BVH::box_intersects_box(
379-
const VectorMax3d& bbd0, const VectorMax3d& bbd1, int index) const
384+
const Vector3d& bbd0, const Vector3d& bbd1, int index) const
380385
{
381386
const auto& bmin = boxlist[index][0];
382387
const auto& bmax = boxlist[index][1];
@@ -385,9 +390,9 @@ bool BVH::box_intersects_box(
385390
}
386391

387392
void BVH::get_nearest_facet_hint(
388-
const VectorMax3d& p,
393+
const Vector3d& p,
389394
int& nearest_f,
390-
VectorMax3d& nearest_point,
395+
Vector3d& nearest_point,
391396
double& sq_dist) const
392397
{
393398
int b = 0;
@@ -413,9 +418,9 @@ void BVH::get_nearest_facet_hint(
413418
}
414419

415420
void BVH::nearest_facet_recursive(
416-
const VectorMax3d& p,
421+
const Vector3d& p,
417422
int& nearest_f,
418-
VectorMax3d& nearest_point,
423+
Vector3d& nearest_point,
419424
double& sq_dist,
420425
int n,
421426
int b,
@@ -426,7 +431,7 @@ void BVH::nearest_facet_recursive(
426431
// If node is a leaf: compute point-facet distance
427432
// and replace current if nearer
428433
if (b + 1 == e) {
429-
VectorMax3d cur_nearest_point;
434+
Vector3d cur_nearest_point;
430435
double cur_sq_dist;
431436
leaf_callback(p, new2old[b], cur_nearest_point, cur_sq_dist);
432437
if (cur_sq_dist < sq_dist) {
@@ -470,10 +475,10 @@ void BVH::nearest_facet_recursive(
470475
}
471476

472477
void BVH::facet_in_envelope_recursive(
473-
const VectorMax3d& p,
478+
const Vector3d& p,
474479
double sq_epsilon,
475480
int& nearest_f,
476-
VectorMax3d& nearest_point,
481+
Vector3d& nearest_point,
477482
double& sq_dist,
478483
int n,
479484
int b,
@@ -488,7 +493,7 @@ void BVH::facet_in_envelope_recursive(
488493
// If node is a leaf: compute point-facet distance
489494
// and replace current if nearer
490495
if (b + 1 == e) {
491-
VectorMax3d cur_nearest_point;
496+
Vector3d cur_nearest_point;
492497
double cur_sq_dist;
493498
leaf_callback(p, new2old[b], cur_nearest_point, cur_sq_dist);
494499
if (cur_sq_dist < sq_dist) {
@@ -532,7 +537,7 @@ void BVH::facet_in_envelope_recursive(
532537
}
533538

534539
void BVH::leaf_callback(
535-
const VectorMax3d& p, int f, VectorMax3d& np, double& sq_d) const
540+
const Vector3d& p, int f, Vector3d& np, double& sq_d) const
536541
{
537542
if (leafCallback) {
538543
leafCallback(p, f, np, sq_d);
@@ -541,21 +546,23 @@ void BVH::leaf_callback(
541546

542547
if (faces.cols() == 2) {
543548
point_segment_squared_distance(
544-
p, { { vertices.row(faces(f, 0)), vertices.row(faces(f, 1)) } }, np,
545-
sq_d);
549+
p, vertices.row(faces(f, 0)), vertices.row(faces(f, 1)), np, sq_d);
546550
return;
547551
} else if (faces.cols() == 3) {
552+
// point_triangle_squared_distance(
553+
// p,
554+
// { { vertices.row(faces(f, 0)), vertices.row(faces(f, 1)),
555+
// vertices.row(faces(f, 2)) } },
556+
// np, sq_d);
548557
point_triangle_squared_distance(
549-
p,
550-
{ { vertices.row(faces(f, 0)), vertices.row(faces(f, 1)),
551-
vertices.row(faces(f, 2)) } },
552-
np, sq_d);
558+
p, vertices.row(faces(f, 0)), vertices.row(faces(f, 1)),
559+
vertices.row(faces(f, 2)), np, sq_d);
553560
return;
554561
}
555562

556563
assert(false);
557564
}
558-
VectorMax3d BVH::point_callback(int f) const
565+
Vector3d BVH::point_callback(int f) const
559566
{
560567
if (getPoint) {
561568
return getPoint(f);
@@ -566,6 +573,6 @@ VectorMax3d BVH::point_callback(int f) const
566573
}
567574

568575
assert(false);
569-
return VectorMax3d(3);
576+
return Vector3d(3);
570577
}
571578
} // namespace SimpleBVH

0 commit comments

Comments
 (0)