GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
* Software License Agreement (BSD License) |
||
3 |
* |
||
4 |
* Copyright (c) 2014-2016, CNRS-LAAS |
||
5 |
* Copyright (c) 2023, Inria |
||
6 |
* Author: Florent Lamiraux |
||
7 |
* All rights reserved. |
||
8 |
* |
||
9 |
* Redistribution and use in source and binary forms, with or without |
||
10 |
* modification, are permitted provided that the following conditions |
||
11 |
* are met: |
||
12 |
* |
||
13 |
* * Redistributions of source code must retain the above copyright |
||
14 |
* notice, this list of conditions and the following disclaimer. |
||
15 |
* * Redistributions in binary form must reproduce the above |
||
16 |
* copyright notice, this list of conditions and the following |
||
17 |
* disclaimer in the documentation and/or other materials provided |
||
18 |
* with the distribution. |
||
19 |
* * Neither the name of CNRS nor the names of its |
||
20 |
* contributors may be used to endorse or promote products derived |
||
21 |
* from this software without specific prior written permission. |
||
22 |
* |
||
23 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
24 |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
25 |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
||
26 |
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
||
27 |
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
||
28 |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
||
29 |
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
30 |
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||
31 |
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
32 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
||
33 |
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
34 |
* POSSIBILITY OF SUCH DAMAGE. |
||
35 |
*/ |
||
36 |
|||
37 |
#include <iostream> |
||
38 |
#include <fstream> |
||
39 |
#include <sstream> |
||
40 |
|||
41 |
#include <chrono> |
||
42 |
|||
43 |
#include <hpp/fcl/narrowphase/narrowphase.h> |
||
44 |
|||
45 |
#include "../src/BV/OBB.h" |
||
46 |
#include <hpp/fcl/internal/shape_shape_func.h> |
||
47 |
#include "utility.h" |
||
48 |
|||
49 |
using namespace hpp::fcl; |
||
50 |
|||
51 |
10 |
void randomOBBs(Vec3f& a, Vec3f& b, FCL_REAL extentNorm) { |
|
52 |
// Extent norm is between 0 and extentNorm on each axis |
||
53 |
// a = (Vec3f::Ones()+Vec3f::Random()) * extentNorm / (2*sqrt(3)); |
||
54 |
// b = (Vec3f::Ones()+Vec3f::Random()) * extentNorm / (2*sqrt(3)); |
||
55 |
|||
56 |
✓✗✓✗ ✓✗✓✗ |
10 |
a = extentNorm * Vec3f::Random().cwiseAbs().normalized(); |
57 |
✓✗✓✗ ✓✗✓✗ |
10 |
b = extentNorm * Vec3f::Random().cwiseAbs().normalized(); |
58 |
10 |
} |
|
59 |
|||
60 |
100 |
void randomTransform(Matrix3f& B, Vec3f& T, const Vec3f& a, const Vec3f& b, |
|
61 |
const FCL_REAL extentNorm) { |
||
62 |
// TODO Should we scale T to a and b norm ? |
||
63 |
(void)a; |
||
64 |
(void)b; |
||
65 |
(void)extentNorm; |
||
66 |
|||
67 |
✓✗✓✗ |
100 |
FCL_REAL N = a.norm() + b.norm(); |
68 |
// A translation of norm N ensures there is no collision. |
||
69 |
// Set translation to be between 0 and 2 * N; |
||
70 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
100 |
T = (Vec3f::Random() / sqrt(3)) * 1.5 * N; |
71 |
// T.setZero(); |
||
72 |
|||
73 |
✓✗ | 100 |
Quaternion3f q; |
74 |
✓✗ | 100 |
q.coeffs().setRandom(); |
75 |
✓✗ | 100 |
q.normalize(); |
76 |
✓✗ | 100 |
B = q; |
77 |
100 |
} |
|
78 |
|||
79 |
#define NB_METHODS 7 |
||
80 |
#define MANUAL_PRODUCT 1 |
||
81 |
|||
82 |
#if MANUAL_PRODUCT |
||
83 |
#define PRODUCT(M33, v3) \ |
||
84 |
(M33.col(0) * v3[0] + M33.col(1) * v3[1] + M33.col(2) * v3[2]) |
||
85 |
#else |
||
86 |
#define PRODUCT(M33, v3) (M33 * v3) |
||
87 |
#endif |
||
88 |
|||
89 |
typedef std::chrono::high_resolution_clock clock_type; |
||
90 |
typedef clock_type::duration duration_type; |
||
91 |
|||
92 |
const char* sep = ",\t"; |
||
93 |
const FCL_REAL eps = 1.5e-7; |
||
94 |
|||
95 |
const Eigen::IOFormat py_fmt(Eigen::FullPrecision, 0, |
||
96 |
", ", // Coeff separator |
||
97 |
",\n", // Row separator |
||
98 |
"(", // row prefix |
||
99 |
",)", // row suffix |
||
100 |
"( ", // mat prefix |
||
101 |
", )" // mat suffix |
||
102 |
); |
||
103 |
|||
104 |
namespace obbDisjoint_impls { |
||
105 |
/// @return true if OBB are disjoint. |
||
106 |
100 |
bool distance(const Matrix3f& B, const Vec3f& T, const Vec3f& a, const Vec3f& b, |
|
107 |
FCL_REAL& distance) { |
||
108 |
✓✗ | 100 |
GJKSolver gjk; |
109 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
200 |
Box ba(2 * a), bb(2 * b); |
110 |
✓✗✓✗ |
100 |
Transform3f tfa, tfb(B, T); |
111 |
|||
112 |
✓✗✓✗ ✓✗ |
100 |
Vec3f p1, p2, normal; |
113 |
✓✗ | 200 |
return gjk.shapeDistance(ba, tfa, bb, tfb, distance, p1, p2, normal); |
114 |
} |
||
115 |
|||
116 |
4100 |
inline FCL_REAL _computeDistanceForCase1(const Vec3f& T, const Vec3f& a, |
|
117 |
const Vec3f& b, const Matrix3f& Bf) { |
||
118 |
✓✗ | 4100 |
Vec3f AABB_corner; |
119 |
/* This seems to be slower |
||
120 |
AABB_corner.noalias() = T.cwiseAbs () - a; |
||
121 |
AABB_corner.noalias() -= PRODUCT(Bf,b); |
||
122 |
/*/ |
||
123 |
#if MANUAL_PRODUCT |
||
124 |
✓✗✓✗ ✓✗✓✗ |
4100 |
AABB_corner.noalias() = T.cwiseAbs() - a; |
125 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
4100 |
AABB_corner.noalias() -= Bf.col(0) * b[0]; |
126 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
4100 |
AABB_corner.noalias() -= Bf.col(1) * b[1]; |
127 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
4100 |
AABB_corner.noalias() -= Bf.col(2) * b[2]; |
128 |
#else |
||
129 |
AABB_corner.noalias() = T.cwiseAbs() - Bf * b - a; |
||
130 |
#endif |
||
131 |
// */ |
||
132 |
✓✗✓✗ ✓✗✓✗ |
4100 |
return AABB_corner.array().max(FCL_REAL(0)).matrix().squaredNorm(); |
133 |
} |
||
134 |
|||
135 |
1435 |
inline FCL_REAL _computeDistanceForCase2(const Matrix3f& B, const Vec3f& T, |
|
136 |
const Vec3f& a, const Vec3f& b, |
||
137 |
const Matrix3f& Bf) { |
||
138 |
/* |
||
139 |
Vec3f AABB_corner(PRODUCT(B.transpose(), T).cwiseAbs() - b); |
||
140 |
AABB_corner.noalias() -= PRODUCT(Bf.transpose(), a); |
||
141 |
return AABB_corner.array().max(FCL_REAL(0)).matrix().squaredNorm (); |
||
142 |
/*/ |
||
143 |
#if MANUAL_PRODUCT |
||
144 |
1435 |
FCL_REAL s, t = 0; |
|
145 |
✓✗✓✗ ✓✗✓✗ |
1435 |
s = std::abs(B.col(0).dot(T)) - Bf.col(0).dot(a) - b[0]; |
146 |
✗✓ | 1435 |
if (s > 0) t += s * s; |
147 |
✓✗✓✗ ✓✗✓✗ |
1435 |
s = std::abs(B.col(1).dot(T)) - Bf.col(1).dot(a) - b[1]; |
148 |
✓✓ | 1435 |
if (s > 0) t += s * s; |
149 |
✓✗✓✗ ✓✗✓✗ |
1435 |
s = std::abs(B.col(2).dot(T)) - Bf.col(2).dot(a) - b[2]; |
150 |
✓✓ | 1435 |
if (s > 0) t += s * s; |
151 |
1435 |
return t; |
|
152 |
#else |
||
153 |
Vec3f AABB_corner((B.transpose() * T).cwiseAbs() - Bf.transpose() * a - b); |
||
154 |
return AABB_corner.array().max(FCL_REAL(0)).matrix().squaredNorm(); |
||
155 |
#endif |
||
156 |
// */ |
||
157 |
} |
||
158 |
|||
159 |
100 |
int separatingAxisId(const Matrix3f& B, const Vec3f& T, const Vec3f& a, |
|
160 |
const Vec3f& b, const FCL_REAL& breakDistance2, |
||
161 |
FCL_REAL& squaredLowerBoundDistance) { |
||
162 |
100 |
int id = 0; |
|
163 |
|||
164 |
✓✗✓✗ |
100 |
Matrix3f Bf(B.cwiseAbs()); |
165 |
|||
166 |
// Corner of b axis aligned bounding box the closest to the origin |
||
167 |
✓✗ | 100 |
squaredLowerBoundDistance = _computeDistanceForCase1(T, a, b, Bf); |
168 |
✓✓ | 100 |
if (squaredLowerBoundDistance > breakDistance2) return id; |
169 |
35 |
++id; |
|
170 |
|||
171 |
// | B^T T| - b - Bf^T a |
||
172 |
✓✗ | 35 |
squaredLowerBoundDistance = _computeDistanceForCase2(B, T, a, b, Bf); |
173 |
✓✓ | 35 |
if (squaredLowerBoundDistance > breakDistance2) return id; |
174 |
31 |
++id; |
|
175 |
|||
176 |
31 |
int ja = 1, ka = 2, jb = 1, kb = 2; |
|
177 |
✓✓ | 120 |
for (int ia = 0; ia < 3; ++ia) { |
178 |
✓✓ | 362 |
for (int ib = 0; ib < 3; ++ib) { |
179 |
✓✗✓✗ ✓✗✓✗ |
273 |
const FCL_REAL s = T[ka] * B(ja, ib) - T[ja] * B(ka, ib); |
180 |
|||
181 |
✓✗✓✗ ✓✗✓✗ |
273 |
const FCL_REAL diff = fabs(s) - (a[ja] * Bf(ka, ib) + a[ka] * Bf(ja, ib) + |
182 |
✓✗✓✗ ✓✗✓✗ |
273 |
b[jb] * Bf(ia, kb) + b[kb] * Bf(ia, jb)); |
183 |
// We need to divide by the norm || Aia x Bib || |
||
184 |
// As ||Aia|| = ||Bib|| = 1, (Aia | Bib)^2 = cosine^2 |
||
185 |
✓✓ | 273 |
if (diff > 0) { |
186 |
✓✗✓✗ |
2 |
FCL_REAL sinus2 = 1 - Bf(ia, ib) * Bf(ia, ib); |
187 |
✓✗ | 2 |
if (sinus2 > 1e-6) { |
188 |
2 |
squaredLowerBoundDistance = diff * diff / sinus2; |
|
189 |
✓✗ | 2 |
if (squaredLowerBoundDistance > breakDistance2) { |
190 |
2 |
return id; |
|
191 |
} |
||
192 |
} |
||
193 |
/* // or |
||
194 |
FCL_REAL sinus2 = 1 - Bf (ia,ib) * Bf (ia,ib); |
||
195 |
squaredLowerBoundDistance = diff * diff; |
||
196 |
if (squaredLowerBoundDistance > breakDistance2 * sinus2) { |
||
197 |
squaredLowerBoundDistance /= sinus2; |
||
198 |
return true; |
||
199 |
} |
||
200 |
// */ |
||
201 |
} |
||
202 |
271 |
++id; |
|
203 |
|||
204 |
271 |
jb = kb; |
|
205 |
271 |
kb = ib; |
|
206 |
} |
||
207 |
89 |
ja = ka; |
|
208 |
89 |
ka = ia; |
|
209 |
} |
||
210 |
|||
211 |
29 |
return id; |
|
212 |
} |
||
213 |
|||
214 |
// ------------------------ 0 -------------------------------------- |
||
215 |
1000 |
bool withRuntimeLoop(const Matrix3f& B, const Vec3f& T, const Vec3f& a, |
|
216 |
const Vec3f& b, const FCL_REAL& breakDistance2, |
||
217 |
FCL_REAL& squaredLowerBoundDistance) { |
||
218 |
✓✗✓✗ |
1000 |
Matrix3f Bf(B.cwiseAbs()); |
219 |
|||
220 |
// Corner of b axis aligned bounding box the closest to the origin |
||
221 |
✓✗ | 1000 |
squaredLowerBoundDistance = _computeDistanceForCase1(T, a, b, Bf); |
222 |
✓✓ | 1000 |
if (squaredLowerBoundDistance > breakDistance2) return true; |
223 |
|||
224 |
// | B^T T| - b - Bf^T a |
||
225 |
✓✗ | 350 |
squaredLowerBoundDistance = _computeDistanceForCase2(B, T, a, b, Bf); |
226 |
✓✓ | 350 |
if (squaredLowerBoundDistance > breakDistance2) return true; |
227 |
|||
228 |
310 |
int ja = 1, ka = 2, jb = 1, kb = 2; |
|
229 |
✓✓ | 1200 |
for (int ia = 0; ia < 3; ++ia) { |
230 |
✓✓ | 3620 |
for (int ib = 0; ib < 3; ++ib) { |
231 |
✓✗✓✗ ✓✗✓✗ |
2730 |
const FCL_REAL s = T[ka] * B(ja, ib) - T[ja] * B(ka, ib); |
232 |
|||
233 |
✓✗✓✗ ✓✗✓✗ |
2730 |
const FCL_REAL diff = fabs(s) - (a[ja] * Bf(ka, ib) + a[ka] * Bf(ja, ib) + |
234 |
✓✗✓✗ ✓✗✓✗ |
2730 |
b[jb] * Bf(ia, kb) + b[kb] * Bf(ia, jb)); |
235 |
// We need to divide by the norm || Aia x Bib || |
||
236 |
// As ||Aia|| = ||Bib|| = 1, (Aia | Bib)^2 = cosine^2 |
||
237 |
✓✓ | 2730 |
if (diff > 0) { |
238 |
✓✗✓✗ |
20 |
FCL_REAL sinus2 = 1 - Bf(ia, ib) * Bf(ia, ib); |
239 |
✓✗ | 20 |
if (sinus2 > 1e-6) { |
240 |
20 |
squaredLowerBoundDistance = diff * diff / sinus2; |
|
241 |
✓✗ | 20 |
if (squaredLowerBoundDistance > breakDistance2) { |
242 |
20 |
return true; |
|
243 |
} |
||
244 |
} |
||
245 |
/* // or |
||
246 |
FCL_REAL sinus2 = 1 - Bf (ia,ib) * Bf (ia,ib); |
||
247 |
squaredLowerBoundDistance = diff * diff; |
||
248 |
if (squaredLowerBoundDistance > breakDistance2 * sinus2) { |
||
249 |
squaredLowerBoundDistance /= sinus2; |
||
250 |
return true; |
||
251 |
} |
||
252 |
// */ |
||
253 |
} |
||
254 |
|||
255 |
2710 |
jb = kb; |
|
256 |
2710 |
kb = ib; |
|
257 |
} |
||
258 |
890 |
ja = ka; |
|
259 |
890 |
ka = ia; |
|
260 |
} |
||
261 |
|||
262 |
290 |
return false; |
|
263 |
} |
||
264 |
|||
265 |
// ------------------------ 1 -------------------------------------- |
||
266 |
1000 |
bool withManualLoopUnrolling_1(const Matrix3f& B, const Vec3f& T, |
|
267 |
const Vec3f& a, const Vec3f& b, |
||
268 |
const FCL_REAL& breakDistance2, |
||
269 |
FCL_REAL& squaredLowerBoundDistance) { |
||
270 |
FCL_REAL t, s; |
||
271 |
FCL_REAL diff; |
||
272 |
|||
273 |
// Matrix3f Bf = abs(B); |
||
274 |
// Bf += reps; |
||
275 |
✓✗✓✗ |
1000 |
Matrix3f Bf(B.cwiseAbs()); |
276 |
|||
277 |
// Corner of b axis aligned bounding box the closest to the origin |
||
278 |
✓✗✓✗ ✓✗✓✗ |
1000 |
Vec3f AABB_corner(T.cwiseAbs() - Bf * b); |
279 |
✓✗✓✗ |
1000 |
Vec3f diff3(AABB_corner - a); |
280 |
✓✗✓✗ ✓✗ |
1000 |
diff3 = diff3.cwiseMax(Vec3f::Zero()); |
281 |
|||
282 |
// for (Vec3f::Index i=0; i<3; ++i) diff3 [i] = std::max (0, diff3 [i]); |
||
283 |
✓✗ | 1000 |
squaredLowerBoundDistance = diff3.squaredNorm(); |
284 |
✓✓ | 1000 |
if (squaredLowerBoundDistance > breakDistance2) return true; |
285 |
|||
286 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
350 |
AABB_corner = (B.transpose() * T).cwiseAbs() - Bf.transpose() * a; |
287 |
// diff3 = | B^T T| - b - Bf^T a |
||
288 |
✓✗✓✗ |
350 |
diff3 = AABB_corner - b; |
289 |
✓✗✓✗ ✓✗ |
350 |
diff3 = diff3.cwiseMax(Vec3f::Zero()); |
290 |
✓✗ | 350 |
squaredLowerBoundDistance = diff3.squaredNorm(); |
291 |
|||
292 |
✓✓ | 350 |
if (squaredLowerBoundDistance > breakDistance2) return true; |
293 |
|||
294 |
// A0 x B0 |
||
295 |
✓✗✓✗ ✓✗✓✗ |
310 |
s = T[2] * B(1, 0) - T[1] * B(2, 0); |
296 |
✓✓ | 310 |
t = ((s < 0.0) ? -s : s); |
297 |
✗✓ | 310 |
assert(t == fabs(s)); |
298 |
|||
299 |
FCL_REAL sinus2; |
||
300 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
310 |
diff = t - (a[1] * Bf(2, 0) + a[2] * Bf(1, 0) + b[1] * Bf(0, 2) + |
301 |
✓✗✓✗ |
310 |
b[2] * Bf(0, 1)); |
302 |
// We need to divide by the norm || A0 x B0 || |
||
303 |
// As ||A0|| = ||B0|| = 1, |
||
304 |
// 2 2 |
||
305 |
// || A0 x B0 || + (A0 | B0) = 1 |
||
306 |
✗✓ | 310 |
if (diff > 0) { |
307 |
sinus2 = 1 - Bf(0, 0) * Bf(0, 0); |
||
308 |
if (sinus2 > 1e-6) { |
||
309 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
310 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
311 |
return true; |
||
312 |
} |
||
313 |
} |
||
314 |
} |
||
315 |
|||
316 |
// A0 x B1 |
||
317 |
✓✗✓✗ ✓✗✓✗ |
310 |
s = T[2] * B(1, 1) - T[1] * B(2, 1); |
318 |
✓✓ | 310 |
t = ((s < 0.0) ? -s : s); |
319 |
✗✓ | 310 |
assert(t == fabs(s)); |
320 |
|||
321 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
310 |
diff = t - (a[1] * Bf(2, 1) + a[2] * Bf(1, 1) + b[0] * Bf(0, 2) + |
322 |
✓✗✓✗ |
310 |
b[2] * Bf(0, 0)); |
323 |
✗✓ | 310 |
if (diff > 0) { |
324 |
sinus2 = 1 - Bf(0, 1) * Bf(0, 1); |
||
325 |
if (sinus2 > 1e-6) { |
||
326 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
327 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
328 |
return true; |
||
329 |
} |
||
330 |
} |
||
331 |
} |
||
332 |
|||
333 |
// A0 x B2 |
||
334 |
✓✗✓✗ ✓✗✓✗ |
310 |
s = T[2] * B(1, 2) - T[1] * B(2, 2); |
335 |
✓✓ | 310 |
t = ((s < 0.0) ? -s : s); |
336 |
✗✓ | 310 |
assert(t == fabs(s)); |
337 |
|||
338 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
310 |
diff = t - (a[1] * Bf(2, 2) + a[2] * Bf(1, 2) + b[0] * Bf(0, 1) + |
339 |
✓✗✓✗ |
310 |
b[1] * Bf(0, 0)); |
340 |
✓✓ | 310 |
if (diff > 0) { |
341 |
✓✗✓✗ |
10 |
sinus2 = 1 - Bf(0, 2) * Bf(0, 2); |
342 |
✓✗ | 10 |
if (sinus2 > 1e-6) { |
343 |
10 |
squaredLowerBoundDistance = diff * diff / sinus2; |
|
344 |
✓✗ | 10 |
if (squaredLowerBoundDistance > breakDistance2) { |
345 |
10 |
return true; |
|
346 |
} |
||
347 |
} |
||
348 |
} |
||
349 |
|||
350 |
// A1 x B0 |
||
351 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[0] * B(2, 0) - T[2] * B(0, 0); |
352 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
353 |
✗✓ | 300 |
assert(t == fabs(s)); |
354 |
|||
355 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(2, 0) + a[2] * Bf(0, 0) + b[1] * Bf(1, 2) + |
356 |
✓✗✓✗ |
300 |
b[2] * Bf(1, 1)); |
357 |
✗✓ | 300 |
if (diff > 0) { |
358 |
sinus2 = 1 - Bf(1, 0) * Bf(1, 0); |
||
359 |
if (sinus2 > 1e-6) { |
||
360 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
361 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
362 |
return true; |
||
363 |
} |
||
364 |
} |
||
365 |
} |
||
366 |
|||
367 |
// A1 x B1 |
||
368 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[0] * B(2, 1) - T[2] * B(0, 1); |
369 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
370 |
✗✓ | 300 |
assert(t == fabs(s)); |
371 |
|||
372 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(2, 1) + a[2] * Bf(0, 1) + b[0] * Bf(1, 2) + |
373 |
✓✗✓✗ |
300 |
b[2] * Bf(1, 0)); |
374 |
✗✓ | 300 |
if (diff > 0) { |
375 |
sinus2 = 1 - Bf(1, 1) * Bf(1, 1); |
||
376 |
if (sinus2 > 1e-6) { |
||
377 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
378 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
379 |
return true; |
||
380 |
} |
||
381 |
} |
||
382 |
} |
||
383 |
|||
384 |
// A1 x B2 |
||
385 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[0] * B(2, 2) - T[2] * B(0, 2); |
386 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
387 |
✗✓ | 300 |
assert(t == fabs(s)); |
388 |
|||
389 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(2, 2) + a[2] * Bf(0, 2) + b[0] * Bf(1, 1) + |
390 |
✓✗✓✗ |
300 |
b[1] * Bf(1, 0)); |
391 |
✗✓ | 300 |
if (diff > 0) { |
392 |
sinus2 = 1 - Bf(1, 2) * Bf(1, 2); |
||
393 |
if (sinus2 > 1e-6) { |
||
394 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
395 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
396 |
return true; |
||
397 |
} |
||
398 |
} |
||
399 |
} |
||
400 |
|||
401 |
// A2 x B0 |
||
402 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[1] * B(0, 0) - T[0] * B(1, 0); |
403 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
404 |
✗✓ | 300 |
assert(t == fabs(s)); |
405 |
|||
406 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(1, 0) + a[1] * Bf(0, 0) + b[1] * Bf(2, 2) + |
407 |
✓✗✓✗ |
300 |
b[2] * Bf(2, 1)); |
408 |
✗✓ | 300 |
if (diff > 0) { |
409 |
sinus2 = 1 - Bf(2, 0) * Bf(2, 0); |
||
410 |
if (sinus2 > 1e-6) { |
||
411 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
412 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
413 |
return true; |
||
414 |
} |
||
415 |
} |
||
416 |
} |
||
417 |
|||
418 |
// A2 x B1 |
||
419 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[1] * B(0, 1) - T[0] * B(1, 1); |
420 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
421 |
✗✓ | 300 |
assert(t == fabs(s)); |
422 |
|||
423 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(1, 1) + a[1] * Bf(0, 1) + b[0] * Bf(2, 2) + |
424 |
✓✗✓✗ |
300 |
b[2] * Bf(2, 0)); |
425 |
✗✓ | 300 |
if (diff > 0) { |
426 |
sinus2 = 1 - Bf(2, 1) * Bf(2, 1); |
||
427 |
if (sinus2 > 1e-6) { |
||
428 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
429 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
430 |
return true; |
||
431 |
} |
||
432 |
} |
||
433 |
} |
||
434 |
|||
435 |
// A2 x B2 |
||
436 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[1] * B(0, 2) - T[0] * B(1, 2); |
437 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
438 |
✗✓ | 300 |
assert(t == fabs(s)); |
439 |
|||
440 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(1, 2) + a[1] * Bf(0, 2) + b[0] * Bf(2, 1) + |
441 |
✓✗✓✗ |
300 |
b[1] * Bf(2, 0)); |
442 |
✓✓ | 300 |
if (diff > 0) { |
443 |
✓✗✓✗ |
10 |
sinus2 = 1 - Bf(2, 2) * Bf(2, 2); |
444 |
✓✗ | 10 |
if (sinus2 > 1e-6) { |
445 |
10 |
squaredLowerBoundDistance = diff * diff / sinus2; |
|
446 |
✓✗ | 10 |
if (squaredLowerBoundDistance > breakDistance2) { |
447 |
10 |
return true; |
|
448 |
} |
||
449 |
} |
||
450 |
} |
||
451 |
|||
452 |
290 |
return false; |
|
453 |
} |
||
454 |
|||
455 |
// ------------------------ 2 -------------------------------------- |
||
456 |
1000 |
bool withManualLoopUnrolling_2(const Matrix3f& B, const Vec3f& T, |
|
457 |
const Vec3f& a, const Vec3f& b, |
||
458 |
const FCL_REAL& breakDistance2, |
||
459 |
FCL_REAL& squaredLowerBoundDistance) { |
||
460 |
✓✗✓✗ |
1000 |
Matrix3f Bf(B.cwiseAbs()); |
461 |
|||
462 |
// Corner of b axis aligned bounding box the closest to the origin |
||
463 |
✓✗ | 1000 |
squaredLowerBoundDistance = _computeDistanceForCase1(T, a, b, Bf); |
464 |
✓✓ | 1000 |
if (squaredLowerBoundDistance > breakDistance2) return true; |
465 |
|||
466 |
✓✗ | 350 |
squaredLowerBoundDistance = _computeDistanceForCase2(B, T, a, b, Bf); |
467 |
✓✓ | 350 |
if (squaredLowerBoundDistance > breakDistance2) return true; |
468 |
|||
469 |
// A0 x B0 |
||
470 |
FCL_REAL t, s; |
||
471 |
✓✗✓✗ ✓✗✓✗ |
310 |
s = T[2] * B(1, 0) - T[1] * B(2, 0); |
472 |
✓✓ | 310 |
t = ((s < 0.0) ? -s : s); |
473 |
✗✓ | 310 |
assert(t == fabs(s)); |
474 |
|||
475 |
FCL_REAL sinus2; |
||
476 |
FCL_REAL diff; |
||
477 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
310 |
diff = t - (a[1] * Bf(2, 0) + a[2] * Bf(1, 0) + b[1] * Bf(0, 2) + |
478 |
✓✗✓✗ |
310 |
b[2] * Bf(0, 1)); |
479 |
// We need to divide by the norm || A0 x B0 || |
||
480 |
// As ||A0|| = ||B0|| = 1, |
||
481 |
// 2 2 |
||
482 |
// || A0 x B0 || + (A0 | B0) = 1 |
||
483 |
✗✓ | 310 |
if (diff > 0) { |
484 |
sinus2 = 1 - Bf(0, 0) * Bf(0, 0); |
||
485 |
if (sinus2 > 1e-6) { |
||
486 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
487 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
488 |
return true; |
||
489 |
} |
||
490 |
} |
||
491 |
} |
||
492 |
|||
493 |
// A0 x B1 |
||
494 |
✓✗✓✗ ✓✗✓✗ |
310 |
s = T[2] * B(1, 1) - T[1] * B(2, 1); |
495 |
✓✓ | 310 |
t = ((s < 0.0) ? -s : s); |
496 |
✗✓ | 310 |
assert(t == fabs(s)); |
497 |
|||
498 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
310 |
diff = t - (a[1] * Bf(2, 1) + a[2] * Bf(1, 1) + b[0] * Bf(0, 2) + |
499 |
✓✗✓✗ |
310 |
b[2] * Bf(0, 0)); |
500 |
✗✓ | 310 |
if (diff > 0) { |
501 |
sinus2 = 1 - Bf(0, 1) * Bf(0, 1); |
||
502 |
if (sinus2 > 1e-6) { |
||
503 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
504 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
505 |
return true; |
||
506 |
} |
||
507 |
} |
||
508 |
} |
||
509 |
|||
510 |
// A0 x B2 |
||
511 |
✓✗✓✗ ✓✗✓✗ |
310 |
s = T[2] * B(1, 2) - T[1] * B(2, 2); |
512 |
✓✓ | 310 |
t = ((s < 0.0) ? -s : s); |
513 |
✗✓ | 310 |
assert(t == fabs(s)); |
514 |
|||
515 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
310 |
diff = t - (a[1] * Bf(2, 2) + a[2] * Bf(1, 2) + b[0] * Bf(0, 1) + |
516 |
✓✗✓✗ |
310 |
b[1] * Bf(0, 0)); |
517 |
✓✓ | 310 |
if (diff > 0) { |
518 |
✓✗✓✗ |
10 |
sinus2 = 1 - Bf(0, 2) * Bf(0, 2); |
519 |
✓✗ | 10 |
if (sinus2 > 1e-6) { |
520 |
10 |
squaredLowerBoundDistance = diff * diff / sinus2; |
|
521 |
✓✗ | 10 |
if (squaredLowerBoundDistance > breakDistance2) { |
522 |
10 |
return true; |
|
523 |
} |
||
524 |
} |
||
525 |
} |
||
526 |
|||
527 |
// A1 x B0 |
||
528 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[0] * B(2, 0) - T[2] * B(0, 0); |
529 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
530 |
✗✓ | 300 |
assert(t == fabs(s)); |
531 |
|||
532 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(2, 0) + a[2] * Bf(0, 0) + b[1] * Bf(1, 2) + |
533 |
✓✗✓✗ |
300 |
b[2] * Bf(1, 1)); |
534 |
✗✓ | 300 |
if (diff > 0) { |
535 |
sinus2 = 1 - Bf(1, 0) * Bf(1, 0); |
||
536 |
if (sinus2 > 1e-6) { |
||
537 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
538 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
539 |
return true; |
||
540 |
} |
||
541 |
} |
||
542 |
} |
||
543 |
|||
544 |
// A1 x B1 |
||
545 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[0] * B(2, 1) - T[2] * B(0, 1); |
546 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
547 |
✗✓ | 300 |
assert(t == fabs(s)); |
548 |
|||
549 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(2, 1) + a[2] * Bf(0, 1) + b[0] * Bf(1, 2) + |
550 |
✓✗✓✗ |
300 |
b[2] * Bf(1, 0)); |
551 |
✗✓ | 300 |
if (diff > 0) { |
552 |
sinus2 = 1 - Bf(1, 1) * Bf(1, 1); |
||
553 |
if (sinus2 > 1e-6) { |
||
554 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
555 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
556 |
return true; |
||
557 |
} |
||
558 |
} |
||
559 |
} |
||
560 |
|||
561 |
// A1 x B2 |
||
562 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[0] * B(2, 2) - T[2] * B(0, 2); |
563 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
564 |
✗✓ | 300 |
assert(t == fabs(s)); |
565 |
|||
566 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(2, 2) + a[2] * Bf(0, 2) + b[0] * Bf(1, 1) + |
567 |
✓✗✓✗ |
300 |
b[1] * Bf(1, 0)); |
568 |
✗✓ | 300 |
if (diff > 0) { |
569 |
sinus2 = 1 - Bf(1, 2) * Bf(1, 2); |
||
570 |
if (sinus2 > 1e-6) { |
||
571 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
572 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
573 |
return true; |
||
574 |
} |
||
575 |
} |
||
576 |
} |
||
577 |
|||
578 |
// A2 x B0 |
||
579 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[1] * B(0, 0) - T[0] * B(1, 0); |
580 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
581 |
✗✓ | 300 |
assert(t == fabs(s)); |
582 |
|||
583 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(1, 0) + a[1] * Bf(0, 0) + b[1] * Bf(2, 2) + |
584 |
✓✗✓✗ |
300 |
b[2] * Bf(2, 1)); |
585 |
✗✓ | 300 |
if (diff > 0) { |
586 |
sinus2 = 1 - Bf(2, 0) * Bf(2, 0); |
||
587 |
if (sinus2 > 1e-6) { |
||
588 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
589 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
590 |
return true; |
||
591 |
} |
||
592 |
} |
||
593 |
} |
||
594 |
|||
595 |
// A2 x B1 |
||
596 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[1] * B(0, 1) - T[0] * B(1, 1); |
597 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
598 |
✗✓ | 300 |
assert(t == fabs(s)); |
599 |
|||
600 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(1, 1) + a[1] * Bf(0, 1) + b[0] * Bf(2, 2) + |
601 |
✓✗✓✗ |
300 |
b[2] * Bf(2, 0)); |
602 |
✗✓ | 300 |
if (diff > 0) { |
603 |
sinus2 = 1 - Bf(2, 1) * Bf(2, 1); |
||
604 |
if (sinus2 > 1e-6) { |
||
605 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
606 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
607 |
return true; |
||
608 |
} |
||
609 |
} |
||
610 |
} |
||
611 |
|||
612 |
// A2 x B2 |
||
613 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[1] * B(0, 2) - T[0] * B(1, 2); |
614 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
615 |
✗✓ | 300 |
assert(t == fabs(s)); |
616 |
|||
617 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(1, 2) + a[1] * Bf(0, 2) + b[0] * Bf(2, 1) + |
618 |
✓✗✓✗ |
300 |
b[1] * Bf(2, 0)); |
619 |
✓✓ | 300 |
if (diff > 0) { |
620 |
✓✗✓✗ |
10 |
sinus2 = 1 - Bf(2, 2) * Bf(2, 2); |
621 |
✓✗ | 10 |
if (sinus2 > 1e-6) { |
622 |
10 |
squaredLowerBoundDistance = diff * diff / sinus2; |
|
623 |
✓✗ | 10 |
if (squaredLowerBoundDistance > breakDistance2) { |
624 |
10 |
return true; |
|
625 |
} |
||
626 |
} |
||
627 |
} |
||
628 |
|||
629 |
290 |
return false; |
|
630 |
} |
||
631 |
|||
632 |
// ------------------------ 3 -------------------------------------- |
||
633 |
template <int ia, int ib, int ja = (ia + 1) % 3, int ka = (ia + 2) % 3, |
||
634 |
int jb = (ib + 1) % 3, int kb = (ib + 2) % 3> |
||
635 |
struct loop_case_1 { |
||
636 |
5460 |
static inline bool run(const Matrix3f& B, const Vec3f& T, const Vec3f& a, |
|
637 |
const Vec3f& b, const Matrix3f& Bf, |
||
638 |
const FCL_REAL& breakDistance2, |
||
639 |
FCL_REAL& squaredLowerBoundDistance) { |
||
640 |
5460 |
const FCL_REAL s = T[ka] * B(ja, ib) - T[ja] * B(ka, ib); |
|
641 |
|||
642 |
5460 |
const FCL_REAL diff = fabs(s) - (a[ja] * Bf(ka, ib) + a[ka] * Bf(ja, ib) + |
|
643 |
5460 |
b[jb] * Bf(ia, kb) + b[kb] * Bf(ia, jb)); |
|
644 |
// We need to divide by the norm || Aia x Bib || |
||
645 |
// As ||Aia|| = ||Bib|| = 1, (Aia | Bib)^2 = cosine^2 |
||
646 |
✓✓ | 5460 |
if (diff > 0) { |
647 |
40 |
FCL_REAL sinus2 = 1 - Bf(ia, ib) * Bf(ia, ib); |
|
648 |
✓✗ | 40 |
if (sinus2 > 1e-6) { |
649 |
40 |
squaredLowerBoundDistance = diff * diff / sinus2; |
|
650 |
✓✗ | 40 |
if (squaredLowerBoundDistance > breakDistance2) { |
651 |
40 |
return true; |
|
652 |
} |
||
653 |
} |
||
654 |
/* // or |
||
655 |
FCL_REAL sinus2 = 1 - Bf (ia,ib) * Bf (ia,ib); |
||
656 |
squaredLowerBoundDistance = diff * diff; |
||
657 |
if (squaredLowerBoundDistance > breakDistance2 * sinus2) { |
||
658 |
squaredLowerBoundDistance /= sinus2; |
||
659 |
return true; |
||
660 |
} |
||
661 |
// */ |
||
662 |
} |
||
663 |
5420 |
return false; |
|
664 |
} |
||
665 |
}; |
||
666 |
|||
667 |
1000 |
bool withTemplateLoopUnrolling_1(const Matrix3f& B, const Vec3f& T, |
|
668 |
const Vec3f& a, const Vec3f& b, |
||
669 |
const FCL_REAL& breakDistance2, |
||
670 |
FCL_REAL& squaredLowerBoundDistance) { |
||
671 |
✓✗✓✗ |
1000 |
Matrix3f Bf(B.cwiseAbs()); |
672 |
|||
673 |
// Corner of b axis aligned bounding box the closest to the origin |
||
674 |
✓✗ | 1000 |
squaredLowerBoundDistance = _computeDistanceForCase1(T, a, b, Bf); |
675 |
✓✓ | 1000 |
if (squaredLowerBoundDistance > breakDistance2) return true; |
676 |
|||
677 |
✓✗ | 350 |
squaredLowerBoundDistance = _computeDistanceForCase2(B, T, a, b, Bf); |
678 |
✓✓ | 350 |
if (squaredLowerBoundDistance > breakDistance2) return true; |
679 |
|||
680 |
// Ai x Bj |
||
681 |
✓✗✗✓ |
310 |
if (loop_case_1<0, 0>::run(B, T, a, b, Bf, breakDistance2, |
682 |
squaredLowerBoundDistance)) |
||
683 |
return true; |
||
684 |
✓✗✗✓ |
310 |
if (loop_case_1<0, 1>::run(B, T, a, b, Bf, breakDistance2, |
685 |
squaredLowerBoundDistance)) |
||
686 |
return true; |
||
687 |
✓✗✓✓ |
310 |
if (loop_case_1<0, 2>::run(B, T, a, b, Bf, breakDistance2, |
688 |
squaredLowerBoundDistance)) |
||
689 |
10 |
return true; |
|
690 |
✓✗✗✓ |
300 |
if (loop_case_1<1, 0>::run(B, T, a, b, Bf, breakDistance2, |
691 |
squaredLowerBoundDistance)) |
||
692 |
return true; |
||
693 |
✓✗✗✓ |
300 |
if (loop_case_1<1, 1>::run(B, T, a, b, Bf, breakDistance2, |
694 |
squaredLowerBoundDistance)) |
||
695 |
return true; |
||
696 |
✓✗✗✓ |
300 |
if (loop_case_1<1, 2>::run(B, T, a, b, Bf, breakDistance2, |
697 |
squaredLowerBoundDistance)) |
||
698 |
return true; |
||
699 |
✓✗✗✓ |
300 |
if (loop_case_1<2, 0>::run(B, T, a, b, Bf, breakDistance2, |
700 |
squaredLowerBoundDistance)) |
||
701 |
return true; |
||
702 |
✓✗✗✓ |
300 |
if (loop_case_1<2, 1>::run(B, T, a, b, Bf, breakDistance2, |
703 |
squaredLowerBoundDistance)) |
||
704 |
return true; |
||
705 |
✓✗✓✓ |
300 |
if (loop_case_1<2, 2>::run(B, T, a, b, Bf, breakDistance2, |
706 |
squaredLowerBoundDistance)) |
||
707 |
10 |
return true; |
|
708 |
|||
709 |
290 |
return false; |
|
710 |
} |
||
711 |
|||
712 |
// ------------------------ 4 -------------------------------------- |
||
713 |
|||
714 |
template <int ib, int jb = (ib + 1) % 3, int kb = (ib + 2) % 3> |
||
715 |
struct loop_case_2 { |
||
716 |
5460 |
static inline bool run(int ia, int ja, int ka, const Matrix3f& B, |
|
717 |
const Vec3f& T, const Vec3f& a, const Vec3f& b, |
||
718 |
const Matrix3f& Bf, const FCL_REAL& breakDistance2, |
||
719 |
FCL_REAL& squaredLowerBoundDistance) { |
||
720 |
5460 |
const FCL_REAL s = T[ka] * B(ja, ib) - T[ja] * B(ka, ib); |
|
721 |
|||
722 |
5460 |
const FCL_REAL diff = fabs(s) - (a[ja] * Bf(ka, ib) + a[ka] * Bf(ja, ib) + |
|
723 |
5460 |
b[jb] * Bf(ia, kb) + b[kb] * Bf(ia, jb)); |
|
724 |
// We need to divide by the norm || Aia x Bib || |
||
725 |
// As ||Aia|| = ||Bib|| = 1, (Aia | Bib)^2 = cosine^2 |
||
726 |
✓✓ | 5460 |
if (diff > 0) { |
727 |
40 |
FCL_REAL sinus2 = 1 - Bf(ia, ib) * Bf(ia, ib); |
|
728 |
✓✗ | 40 |
if (sinus2 > 1e-6) { |
729 |
40 |
squaredLowerBoundDistance = diff * diff / sinus2; |
|
730 |
✓✗ | 40 |
if (squaredLowerBoundDistance > breakDistance2) { |
731 |
40 |
return true; |
|
732 |
} |
||
733 |
} |
||
734 |
/* // or |
||
735 |
FCL_REAL sinus2 = 1 - Bf (ia,ib) * Bf (ia,ib); |
||
736 |
squaredLowerBoundDistance = diff * diff; |
||
737 |
if (squaredLowerBoundDistance > breakDistance2 * sinus2) { |
||
738 |
squaredLowerBoundDistance /= sinus2; |
||
739 |
return true; |
||
740 |
} |
||
741 |
// */ |
||
742 |
} |
||
743 |
5420 |
return false; |
|
744 |
} |
||
745 |
}; |
||
746 |
|||
747 |
1000 |
bool withPartialTemplateLoopUnrolling_1(const Matrix3f& B, const Vec3f& T, |
|
748 |
const Vec3f& a, const Vec3f& b, |
||
749 |
const FCL_REAL& breakDistance2, |
||
750 |
FCL_REAL& squaredLowerBoundDistance) { |
||
751 |
✓✗✓✗ |
1000 |
Matrix3f Bf(B.cwiseAbs()); |
752 |
|||
753 |
// Corner of b axis aligned bounding box the closest to the origin |
||
754 |
✓✗ | 1000 |
squaredLowerBoundDistance = _computeDistanceForCase1(T, a, b, Bf); |
755 |
✓✓ | 1000 |
if (squaredLowerBoundDistance > breakDistance2) return true; |
756 |
|||
757 |
✓✗ | 350 |
squaredLowerBoundDistance = _computeDistanceForCase2(B, T, a, b, Bf); |
758 |
✓✓ | 350 |
if (squaredLowerBoundDistance > breakDistance2) return true; |
759 |
|||
760 |
// Ai x Bj |
||
761 |
310 |
int ja = 1, ka = 2; |
|
762 |
✓✓ | 1200 |
for (int ia = 0; ia < 3; ++ia) { |
763 |
✓✗✗✓ |
910 |
if (loop_case_2<0>::run(ia, ja, ka, B, T, a, b, Bf, breakDistance2, |
764 |
squaredLowerBoundDistance)) |
||
765 |
return true; |
||
766 |
✓✗✗✓ |
910 |
if (loop_case_2<1>::run(ia, ja, ka, B, T, a, b, Bf, breakDistance2, |
767 |
squaredLowerBoundDistance)) |
||
768 |
return true; |
||
769 |
✓✗✓✓ |
910 |
if (loop_case_2<2>::run(ia, ja, ka, B, T, a, b, Bf, breakDistance2, |
770 |
squaredLowerBoundDistance)) |
||
771 |
20 |
return true; |
|
772 |
890 |
ja = ka; |
|
773 |
890 |
ka = ia; |
|
774 |
} |
||
775 |
|||
776 |
290 |
return false; |
|
777 |
} |
||
778 |
|||
779 |
// ------------------------ 5 -------------------------------------- |
||
780 |
1000 |
bool originalWithLowerBound(const Matrix3f& B, const Vec3f& T, const Vec3f& a, |
|
781 |
const Vec3f& b, const FCL_REAL& breakDistance2, |
||
782 |
FCL_REAL& squaredLowerBoundDistance) { |
||
783 |
FCL_REAL t, s; |
||
784 |
FCL_REAL diff; |
||
785 |
|||
786 |
✓✗✓✗ |
1000 |
Matrix3f Bf(B.cwiseAbs()); |
787 |
1000 |
squaredLowerBoundDistance = 0; |
|
788 |
|||
789 |
// if any of these tests are one-sided, then the polyhedra are disjoint |
||
790 |
|||
791 |
// A1 x A2 = A0 |
||
792 |
✓✗✓✓ ✓✗✓✗ |
1000 |
t = ((T[0] < 0.0) ? -T[0] : T[0]); |
793 |
|||
794 |
✓✗✓✗ ✓✗ |
1000 |
diff = t - (a[0] + Bf.row(0).dot(b)); |
795 |
✓✓ | 1000 |
if (diff > 0) { |
796 |
290 |
squaredLowerBoundDistance = diff * diff; |
|
797 |
} |
||
798 |
|||
799 |
// A2 x A0 = A1 |
||
800 |
✓✗✓✓ ✓✗✓✗ |
1000 |
t = ((T[1] < 0.0) ? -T[1] : T[1]); |
801 |
|||
802 |
✓✗✓✗ ✓✗ |
1000 |
diff = t - (a[1] + Bf.row(1).dot(b)); |
803 |
✓✓ | 1000 |
if (diff > 0) { |
804 |
350 |
squaredLowerBoundDistance += diff * diff; |
|
805 |
} |
||
806 |
|||
807 |
// A0 x A1 = A2 |
||
808 |
✓✗✓✓ ✓✗✓✗ |
1000 |
t = ((T[2] < 0.0) ? -T[2] : T[2]); |
809 |
|||
810 |
✓✗✓✗ ✓✗ |
1000 |
diff = t - (a[2] + Bf.row(2).dot(b)); |
811 |
✓✓ | 1000 |
if (diff > 0) { |
812 |
180 |
squaredLowerBoundDistance += diff * diff; |
|
813 |
} |
||
814 |
|||
815 |
✓✓ | 1000 |
if (squaredLowerBoundDistance > breakDistance2) return true; |
816 |
|||
817 |
350 |
squaredLowerBoundDistance = 0; |
|
818 |
|||
819 |
// B1 x B2 = B0 |
||
820 |
✓✗✓✗ |
350 |
s = B.col(0).dot(T); |
821 |
✓✓ | 350 |
t = ((s < 0.0) ? -s : s); |
822 |
|||
823 |
✓✗✓✗ ✓✗ |
350 |
diff = t - (b[0] + Bf.col(0).dot(a)); |
824 |
✗✓ | 350 |
if (diff > 0) { |
825 |
squaredLowerBoundDistance += diff * diff; |
||
826 |
} |
||
827 |
|||
828 |
// B2 x B0 = B1 |
||
829 |
✓✗✓✗ |
350 |
s = B.col(1).dot(T); |
830 |
✓✓ | 350 |
t = ((s < 0.0) ? -s : s); |
831 |
|||
832 |
✓✗✓✗ ✓✗ |
350 |
diff = t - (b[1] + Bf.col(1).dot(a)); |
833 |
✓✓ | 350 |
if (diff > 0) { |
834 |
20 |
squaredLowerBoundDistance += diff * diff; |
|
835 |
} |
||
836 |
|||
837 |
// B0 x B1 = B2 |
||
838 |
✓✗✓✗ |
350 |
s = B.col(2).dot(T); |
839 |
✓✓ | 350 |
t = ((s < 0.0) ? -s : s); |
840 |
|||
841 |
✓✗✓✗ ✓✗ |
350 |
diff = t - (b[2] + Bf.col(2).dot(a)); |
842 |
✓✓ | 350 |
if (diff > 0) { |
843 |
20 |
squaredLowerBoundDistance += diff * diff; |
|
844 |
} |
||
845 |
|||
846 |
✓✓ | 350 |
if (squaredLowerBoundDistance > breakDistance2) return true; |
847 |
|||
848 |
// A0 x B0 |
||
849 |
✓✗✓✗ ✓✗✓✗ |
310 |
s = T[2] * B(1, 0) - T[1] * B(2, 0); |
850 |
✓✓ | 310 |
t = ((s < 0.0) ? -s : s); |
851 |
|||
852 |
FCL_REAL sinus2; |
||
853 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
310 |
diff = t - (a[1] * Bf(2, 0) + a[2] * Bf(1, 0) + b[1] * Bf(0, 2) + |
854 |
✓✗✓✗ |
310 |
b[2] * Bf(0, 1)); |
855 |
// We need to divide by the norm || A0 x B0 || |
||
856 |
// As ||A0|| = ||B0|| = 1, |
||
857 |
// 2 2 |
||
858 |
// || A0 x B0 || + (A0 | B0) = 1 |
||
859 |
✗✓ | 310 |
if (diff > 0) { |
860 |
sinus2 = 1 - Bf(0, 0) * Bf(0, 0); |
||
861 |
if (sinus2 > 1e-6) { |
||
862 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
863 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
864 |
return true; |
||
865 |
} |
||
866 |
} |
||
867 |
} |
||
868 |
|||
869 |
// A0 x B1 |
||
870 |
✓✗✓✗ ✓✗✓✗ |
310 |
s = T[2] * B(1, 1) - T[1] * B(2, 1); |
871 |
✓✓ | 310 |
t = ((s < 0.0) ? -s : s); |
872 |
|||
873 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
310 |
diff = t - (a[1] * Bf(2, 1) + a[2] * Bf(1, 1) + b[0] * Bf(0, 2) + |
874 |
✓✗✓✗ |
310 |
b[2] * Bf(0, 0)); |
875 |
✗✓ | 310 |
if (diff > 0) { |
876 |
sinus2 = 1 - Bf(0, 1) * Bf(0, 1); |
||
877 |
if (sinus2 > 1e-6) { |
||
878 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
879 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
880 |
return true; |
||
881 |
} |
||
882 |
} |
||
883 |
} |
||
884 |
|||
885 |
// A0 x B2 |
||
886 |
✓✗✓✗ ✓✗✓✗ |
310 |
s = T[2] * B(1, 2) - T[1] * B(2, 2); |
887 |
✓✓ | 310 |
t = ((s < 0.0) ? -s : s); |
888 |
|||
889 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
310 |
diff = t - (a[1] * Bf(2, 2) + a[2] * Bf(1, 2) + b[0] * Bf(0, 1) + |
890 |
✓✗✓✗ |
310 |
b[1] * Bf(0, 0)); |
891 |
✓✓ | 310 |
if (diff > 0) { |
892 |
✓✗✓✗ |
10 |
sinus2 = 1 - Bf(0, 2) * Bf(0, 2); |
893 |
✓✗ | 10 |
if (sinus2 > 1e-6) { |
894 |
10 |
squaredLowerBoundDistance = diff * diff / sinus2; |
|
895 |
✓✗ | 10 |
if (squaredLowerBoundDistance > breakDistance2) { |
896 |
10 |
return true; |
|
897 |
} |
||
898 |
} |
||
899 |
} |
||
900 |
|||
901 |
// A1 x B0 |
||
902 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[0] * B(2, 0) - T[2] * B(0, 0); |
903 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
904 |
|||
905 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(2, 0) + a[2] * Bf(0, 0) + b[1] * Bf(1, 2) + |
906 |
✓✗✓✗ |
300 |
b[2] * Bf(1, 1)); |
907 |
✗✓ | 300 |
if (diff > 0) { |
908 |
sinus2 = 1 - Bf(1, 0) * Bf(1, 0); |
||
909 |
if (sinus2 > 1e-6) { |
||
910 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
911 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
912 |
return true; |
||
913 |
} |
||
914 |
} |
||
915 |
} |
||
916 |
|||
917 |
// A1 x B1 |
||
918 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[0] * B(2, 1) - T[2] * B(0, 1); |
919 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
920 |
|||
921 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(2, 1) + a[2] * Bf(0, 1) + b[0] * Bf(1, 2) + |
922 |
✓✗✓✗ |
300 |
b[2] * Bf(1, 0)); |
923 |
✗✓ | 300 |
if (diff > 0) { |
924 |
sinus2 = 1 - Bf(1, 1) * Bf(1, 1); |
||
925 |
if (sinus2 > 1e-6) { |
||
926 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
927 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
928 |
return true; |
||
929 |
} |
||
930 |
} |
||
931 |
} |
||
932 |
|||
933 |
// A1 x B2 |
||
934 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[0] * B(2, 2) - T[2] * B(0, 2); |
935 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
936 |
|||
937 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(2, 2) + a[2] * Bf(0, 2) + b[0] * Bf(1, 1) + |
938 |
✓✗✓✗ |
300 |
b[1] * Bf(1, 0)); |
939 |
✗✓ | 300 |
if (diff > 0) { |
940 |
sinus2 = 1 - Bf(1, 2) * Bf(1, 2); |
||
941 |
if (sinus2 > 1e-6) { |
||
942 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
943 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
944 |
return true; |
||
945 |
} |
||
946 |
} |
||
947 |
} |
||
948 |
|||
949 |
// A2 x B0 |
||
950 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[1] * B(0, 0) - T[0] * B(1, 0); |
951 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
952 |
|||
953 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(1, 0) + a[1] * Bf(0, 0) + b[1] * Bf(2, 2) + |
954 |
✓✗✓✗ |
300 |
b[2] * Bf(2, 1)); |
955 |
✗✓ | 300 |
if (diff > 0) { |
956 |
sinus2 = 1 - Bf(2, 0) * Bf(2, 0); |
||
957 |
if (sinus2 > 1e-6) { |
||
958 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
959 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
960 |
return true; |
||
961 |
} |
||
962 |
} |
||
963 |
} |
||
964 |
|||
965 |
// A2 x B1 |
||
966 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[1] * B(0, 1) - T[0] * B(1, 1); |
967 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
968 |
|||
969 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(1, 1) + a[1] * Bf(0, 1) + b[0] * Bf(2, 2) + |
970 |
✓✗✓✗ |
300 |
b[2] * Bf(2, 0)); |
971 |
✗✓ | 300 |
if (diff > 0) { |
972 |
sinus2 = 1 - Bf(2, 1) * Bf(2, 1); |
||
973 |
if (sinus2 > 1e-6) { |
||
974 |
squaredLowerBoundDistance = diff * diff / sinus2; |
||
975 |
if (squaredLowerBoundDistance > breakDistance2) { |
||
976 |
return true; |
||
977 |
} |
||
978 |
} |
||
979 |
} |
||
980 |
|||
981 |
// A2 x B2 |
||
982 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[1] * B(0, 2) - T[0] * B(1, 2); |
983 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
984 |
|||
985 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
300 |
diff = t - (a[0] * Bf(1, 2) + a[1] * Bf(0, 2) + b[0] * Bf(2, 1) + |
986 |
✓✗✓✗ |
300 |
b[1] * Bf(2, 0)); |
987 |
✓✓ | 300 |
if (diff > 0) { |
988 |
✓✗✓✗ |
10 |
sinus2 = 1 - Bf(2, 2) * Bf(2, 2); |
989 |
✓✗ | 10 |
if (sinus2 > 1e-6) { |
990 |
10 |
squaredLowerBoundDistance = diff * diff / sinus2; |
|
991 |
✓✗ | 10 |
if (squaredLowerBoundDistance > breakDistance2) { |
992 |
10 |
return true; |
|
993 |
} |
||
994 |
} |
||
995 |
} |
||
996 |
|||
997 |
290 |
return false; |
|
998 |
} |
||
999 |
|||
1000 |
// ------------------------ 6 -------------------------------------- |
||
1001 |
1000 |
bool originalWithNoLowerBound(const Matrix3f& B, const Vec3f& T, const Vec3f& a, |
|
1002 |
const Vec3f& b, const FCL_REAL&, |
||
1003 |
FCL_REAL& squaredLowerBoundDistance) { |
||
1004 |
FCL_REAL t, s; |
||
1005 |
1000 |
const FCL_REAL reps = 1e-6; |
|
1006 |
|||
1007 |
1000 |
squaredLowerBoundDistance = 0; |
|
1008 |
|||
1009 |
✓✗✓✗ ✓✗✓✗ |
1000 |
Matrix3f Bf(B.array().abs() + reps); |
1010 |
// Bf += reps; |
||
1011 |
|||
1012 |
// if any of these tests are one-sided, then the polyhedra are disjoint |
||
1013 |
|||
1014 |
// A1 x A2 = A0 |
||
1015 |
✓✗✓✓ ✓✗✓✗ |
1000 |
t = ((T[0] < 0.0) ? -T[0] : T[0]); |
1016 |
|||
1017 |
// if(t > (a[0] + Bf.dotX(b))) |
||
1018 |
✓✗✓✗ ✓✗✓✓ |
1000 |
if (t > (a[0] + Bf.row(0).dot(b))) return true; |
1019 |
|||
1020 |
// B1 x B2 = B0 |
||
1021 |
// s = B.transposeDotX(T); |
||
1022 |
✓✗✓✗ |
710 |
s = B.col(0).dot(T); |
1023 |
✓✓ | 710 |
t = ((s < 0.0) ? -s : s); |
1024 |
|||
1025 |
// if(t > (b[0] + Bf.transposeDotX(a))) |
||
1026 |
✓✗✓✗ ✓✗✓✓ |
710 |
if (t > (b[0] + Bf.col(0).dot(a))) return true; |
1027 |
|||
1028 |
// A2 x A0 = A1 |
||
1029 |
✓✗✓✓ ✓✗✓✗ |
570 |
t = ((T[1] < 0.0) ? -T[1] : T[1]); |
1030 |
|||
1031 |
// if(t > (a[1] + Bf.dotY(b))) |
||
1032 |
✓✗✓✗ ✓✗✓✓ |
570 |
if (t > (a[1] + Bf.row(1).dot(b))) return true; |
1033 |
|||
1034 |
// A0 x A1 = A2 |
||
1035 |
✓✗✓✓ ✓✗✓✗ |
410 |
t = ((T[2] < 0.0) ? -T[2] : T[2]); |
1036 |
|||
1037 |
// if(t > (a[2] + Bf.dotZ(b))) |
||
1038 |
✓✗✓✗ ✓✗✓✓ |
410 |
if (t > (a[2] + Bf.row(2).dot(b))) return true; |
1039 |
|||
1040 |
// B2 x B0 = B1 |
||
1041 |
// s = B.transposeDotY(T); |
||
1042 |
✓✗✓✗ |
350 |
s = B.col(1).dot(T); |
1043 |
✓✓ | 350 |
t = ((s < 0.0) ? -s : s); |
1044 |
|||
1045 |
// if(t > (b[1] + Bf.transposeDotY(a))) |
||
1046 |
✓✗✓✗ ✓✗✓✓ |
350 |
if (t > (b[1] + Bf.col(1).dot(a))) return true; |
1047 |
|||
1048 |
// B0 x B1 = B2 |
||
1049 |
// s = B.transposeDotZ(T); |
||
1050 |
✓✗✓✗ |
330 |
s = B.col(2).dot(T); |
1051 |
✓✓ | 330 |
t = ((s < 0.0) ? -s : s); |
1052 |
|||
1053 |
// if(t > (b[2] + Bf.transposeDotZ(a))) |
||
1054 |
✓✗✓✗ ✓✗✓✓ |
330 |
if (t > (b[2] + Bf.col(2).dot(a))) return true; |
1055 |
|||
1056 |
// A0 x B0 |
||
1057 |
✓✗✓✗ ✓✗✓✗ |
310 |
s = T[2] * B(1, 0) - T[1] * B(2, 0); |
1058 |
✓✓ | 310 |
t = ((s < 0.0) ? -s : s); |
1059 |
|||
1060 |
310 |
if (t > |
|
1061 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
310 |
(a[1] * Bf(2, 0) + a[2] * Bf(1, 0) + b[1] * Bf(0, 2) + b[2] * Bf(0, 1))) |
1062 |
return true; |
||
1063 |
|||
1064 |
// A0 x B1 |
||
1065 |
✓✗✓✗ ✓✗✓✗ |
310 |
s = T[2] * B(1, 1) - T[1] * B(2, 1); |
1066 |
✓✓ | 310 |
t = ((s < 0.0) ? -s : s); |
1067 |
|||
1068 |
310 |
if (t > |
|
1069 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
310 |
(a[1] * Bf(2, 1) + a[2] * Bf(1, 1) + b[0] * Bf(0, 2) + b[2] * Bf(0, 0))) |
1070 |
return true; |
||
1071 |
|||
1072 |
// A0 x B2 |
||
1073 |
✓✗✓✗ ✓✗✓✗ |
310 |
s = T[2] * B(1, 2) - T[1] * B(2, 2); |
1074 |
✓✓ | 310 |
t = ((s < 0.0) ? -s : s); |
1075 |
|||
1076 |
310 |
if (t > |
|
1077 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✓ |
310 |
(a[1] * Bf(2, 2) + a[2] * Bf(1, 2) + b[0] * Bf(0, 1) + b[1] * Bf(0, 0))) |
1078 |
10 |
return true; |
|
1079 |
|||
1080 |
// A1 x B0 |
||
1081 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[0] * B(2, 0) - T[2] * B(0, 0); |
1082 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
1083 |
|||
1084 |
300 |
if (t > |
|
1085 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
300 |
(a[0] * Bf(2, 0) + a[2] * Bf(0, 0) + b[1] * Bf(1, 2) + b[2] * Bf(1, 1))) |
1086 |
return true; |
||
1087 |
|||
1088 |
// A1 x B1 |
||
1089 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[0] * B(2, 1) - T[2] * B(0, 1); |
1090 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
1091 |
|||
1092 |
300 |
if (t > |
|
1093 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
300 |
(a[0] * Bf(2, 1) + a[2] * Bf(0, 1) + b[0] * Bf(1, 2) + b[2] * Bf(1, 0))) |
1094 |
return true; |
||
1095 |
|||
1096 |
// A1 x B2 |
||
1097 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[0] * B(2, 2) - T[2] * B(0, 2); |
1098 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
1099 |
|||
1100 |
300 |
if (t > |
|
1101 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
300 |
(a[0] * Bf(2, 2) + a[2] * Bf(0, 2) + b[0] * Bf(1, 1) + b[1] * Bf(1, 0))) |
1102 |
return true; |
||
1103 |
|||
1104 |
// A2 x B0 |
||
1105 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[1] * B(0, 0) - T[0] * B(1, 0); |
1106 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
1107 |
|||
1108 |
300 |
if (t > |
|
1109 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
300 |
(a[0] * Bf(1, 0) + a[1] * Bf(0, 0) + b[1] * Bf(2, 2) + b[2] * Bf(2, 1))) |
1110 |
return true; |
||
1111 |
|||
1112 |
// A2 x B1 |
||
1113 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[1] * B(0, 1) - T[0] * B(1, 1); |
1114 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
1115 |
|||
1116 |
300 |
if (t > |
|
1117 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✓ |
300 |
(a[0] * Bf(1, 1) + a[1] * Bf(0, 1) + b[0] * Bf(2, 2) + b[2] * Bf(2, 0))) |
1118 |
return true; |
||
1119 |
|||
1120 |
// A2 x B2 |
||
1121 |
✓✗✓✗ ✓✗✓✗ |
300 |
s = T[1] * B(0, 2) - T[0] * B(1, 2); |
1122 |
✓✓ | 300 |
t = ((s < 0.0) ? -s : s); |
1123 |
|||
1124 |
300 |
if (t > |
|
1125 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✓ |
300 |
(a[0] * Bf(1, 2) + a[1] * Bf(0, 2) + b[0] * Bf(2, 1) + b[1] * Bf(2, 0))) |
1126 |
10 |
return true; |
|
1127 |
|||
1128 |
290 |
return false; |
|
1129 |
} |
||
1130 |
} // namespace obbDisjoint_impls |
||
1131 |
|||
1132 |
struct BenchmarkResult { |
||
1133 |
/// The test ID: |
||
1134 |
/// - 0-10 identifies a separating axes. |
||
1135 |
/// - 11 means no separatins axes could be found. (distance should be <= 0) |
||
1136 |
int ifId; |
||
1137 |
FCL_REAL distance; |
||
1138 |
FCL_REAL squaredLowerBoundDistance; |
||
1139 |
duration_type duration[NB_METHODS]; |
||
1140 |
bool failure; |
||
1141 |
|||
1142 |
static std::ostream& headers(std::ostream& os) { |
||
1143 |
const std::string unit = " (us)"; |
||
1144 |
os << "separating axis" << sep << "distance lower bound" << sep |
||
1145 |
<< "distance" << sep << "failure" << sep << "Runtime Loop" << unit << sep |
||
1146 |
<< "Manual Loop Unrolling 1" << unit << sep << "Manual Loop Unrolling 2" |
||
1147 |
<< unit << sep << "Template Unrolling" << unit << sep |
||
1148 |
<< "Partial Template Unrolling" << unit << sep << "Original (LowerBound)" |
||
1149 |
<< unit << sep << "Original (NoLowerBound)" << unit; |
||
1150 |
return os; |
||
1151 |
} |
||
1152 |
|||
1153 |
std::ostream& print(std::ostream& os) const { |
||
1154 |
os << ifId << sep << std::sqrt(squaredLowerBoundDistance) << sep << distance |
||
1155 |
<< sep << failure; |
||
1156 |
for (int i = 0; i < NB_METHODS; ++i) |
||
1157 |
os << sep |
||
1158 |
<< static_cast<double>( |
||
1159 |
std::chrono::duration_cast<std::chrono::nanoseconds>( |
||
1160 |
duration[i]) |
||
1161 |
.count()) * |
||
1162 |
1e-3; |
||
1163 |
return os; |
||
1164 |
} |
||
1165 |
}; |
||
1166 |
|||
1167 |
std::ostream& operator<<(std::ostream& os, const BenchmarkResult& br) { |
||
1168 |
return br.print(os); |
||
1169 |
} |
||
1170 |
|||
1171 |
100 |
BenchmarkResult benchmark_obb_case(const Matrix3f& B, const Vec3f& T, |
|
1172 |
const Vec3f& a, const Vec3f& b, |
||
1173 |
const CollisionRequest& request, |
||
1174 |
std::size_t N) { |
||
1175 |
100 |
const FCL_REAL breakDistance(request.break_distance + |
|
1176 |
100 |
request.security_margin); |
|
1177 |
100 |
const FCL_REAL breakDistance2 = breakDistance * breakDistance; |
|
1178 |
|||
1179 |
BenchmarkResult result; |
||
1180 |
// First determine which axis provide the answer |
||
1181 |
✓✗ | 100 |
result.ifId = obbDisjoint_impls::separatingAxisId( |
1182 |
B, T, a, b, breakDistance2, result.squaredLowerBoundDistance); |
||
1183 |
✓✗ | 100 |
bool disjoint = obbDisjoint_impls::distance(B, T, a, b, result.distance); |
1184 |
✓✗✓✗ |
100 |
assert(0 <= result.ifId && result.ifId <= 11); |
1185 |
|||
1186 |
// Sanity check |
||
1187 |
100 |
result.failure = true; |
|
1188 |
100 |
bool overlap = (result.ifId == 11); |
|
1189 |
100 |
FCL_REAL dist_thr = request.break_distance + request.security_margin; |
|
1190 |
✓✓✗✓ |
100 |
if (!overlap && result.distance <= 0) { |
1191 |
std::cerr << "Failure: negative distance for disjoint OBBs."; |
||
1192 |
✓✓✗✓ |
100 |
} else if (!overlap && result.squaredLowerBoundDistance < 0) { |
1193 |
std::cerr << "Failure: negative distance lower bound."; |
||
1194 |
✓✓✗✓ |
171 |
} else if (!overlap && eps < std::sqrt(result.squaredLowerBoundDistance) - |
1195 |
✗✓ | 71 |
result.distance) { |
1196 |
std::cerr << "Failure: distance is inferior to its lower bound (diff = " |
||
1197 |
<< std::sqrt(result.squaredLowerBoundDistance) - result.distance |
||
1198 |
<< ")."; |
||
1199 |
✗✓✗✗ |
100 |
} else if (overlap != !disjoint && result.distance >= dist_thr - eps) { |
1200 |
std::cerr << "Failure: overlapping test and distance query mismatch."; |
||
1201 |
✓✓✗✓ |
100 |
} else if (overlap && result.distance >= dist_thr - eps) { |
1202 |
std::cerr << "Failure: positive distance for overlapping OBBs."; |
||
1203 |
} else { |
||
1204 |
100 |
result.failure = false; |
|
1205 |
} |
||
1206 |
✗✓ | 100 |
if (result.failure) { |
1207 |
std::cerr << "\nR = " << Quaternion3f(B).coeffs().transpose().format(py_fmt) |
||
1208 |
<< "\nT = " << T.transpose().format(py_fmt) |
||
1209 |
<< "\na = " << a.transpose().format(py_fmt) |
||
1210 |
<< "\nb = " << b.transpose().format(py_fmt) |
||
1211 |
<< "\nresult = " << result << '\n' |
||
1212 |
<< std::endl; |
||
1213 |
} |
||
1214 |
|||
1215 |
// Compute time |
||
1216 |
FCL_REAL tmp; |
||
1217 |
100 |
clock_type::time_point start, end; |
|
1218 |
|||
1219 |
// ------------------------ 0 -------------------------------------- |
||
1220 |
100 |
start = clock_type::now(); |
|
1221 |
✓✓ | 1100 |
for (std::size_t i = 0; i < N; ++i) |
1222 |
✓✗ | 1000 |
obbDisjoint_impls::withRuntimeLoop(B, T, a, b, breakDistance2, tmp); |
1223 |
100 |
end = clock_type::now(); |
|
1224 |
✓✗✓✗ ✓✗ |
100 |
result.duration[0] = (end - start) / N; |
1225 |
|||
1226 |
// ------------------------ 1 -------------------------------------- |
||
1227 |
100 |
start = clock_type::now(); |
|
1228 |
✓✓ | 1100 |
for (std::size_t i = 0; i < N; ++i) |
1229 |
✓✗ | 1000 |
obbDisjoint_impls::withManualLoopUnrolling_1(B, T, a, b, breakDistance2, |
1230 |
tmp); |
||
1231 |
100 |
end = clock_type::now(); |
|
1232 |
✓✗✓✗ ✓✗ |
100 |
result.duration[1] = (end - start) / N; |
1233 |
|||
1234 |
// ------------------------ 2 -------------------------------------- |
||
1235 |
100 |
start = clock_type::now(); |
|
1236 |
✓✓ | 1100 |
for (std::size_t i = 0; i < N; ++i) |
1237 |
✓✗ | 1000 |
obbDisjoint_impls::withManualLoopUnrolling_2(B, T, a, b, breakDistance2, |
1238 |
tmp); |
||
1239 |
100 |
end = clock_type::now(); |
|
1240 |
✓✗✓✗ ✓✗ |
100 |
result.duration[2] = (end - start) / N; |
1241 |
|||
1242 |
// ------------------------ 3 -------------------------------------- |
||
1243 |
100 |
start = clock_type::now(); |
|
1244 |
✓✓ | 1100 |
for (std::size_t i = 0; i < N; ++i) |
1245 |
✓✗ | 1000 |
obbDisjoint_impls::withTemplateLoopUnrolling_1(B, T, a, b, breakDistance2, |
1246 |
tmp); |
||
1247 |
100 |
end = clock_type::now(); |
|
1248 |
✓✗✓✗ ✓✗ |
100 |
result.duration[3] = (end - start) / N; |
1249 |
|||
1250 |
// ------------------------ 4 -------------------------------------- |
||
1251 |
100 |
start = clock_type::now(); |
|
1252 |
✓✓ | 1100 |
for (std::size_t i = 0; i < N; ++i) |
1253 |
✓✗ | 1000 |
obbDisjoint_impls::withPartialTemplateLoopUnrolling_1(B, T, a, b, |
1254 |
breakDistance2, tmp); |
||
1255 |
100 |
end = clock_type::now(); |
|
1256 |
✓✗✓✗ ✓✗ |
100 |
result.duration[4] = (end - start) / N; |
1257 |
|||
1258 |
// ------------------------ 5 -------------------------------------- |
||
1259 |
100 |
start = clock_type::now(); |
|
1260 |
✓✓ | 1100 |
for (std::size_t i = 0; i < N; ++i) |
1261 |
✓✗ | 1000 |
obbDisjoint_impls::originalWithLowerBound(B, T, a, b, breakDistance2, tmp); |
1262 |
100 |
end = clock_type::now(); |
|
1263 |
✓✗✓✗ ✓✗ |
100 |
result.duration[5] = (end - start) / N; |
1264 |
|||
1265 |
// ------------------------ 6 -------------------------------------- |
||
1266 |
100 |
start = clock_type::now(); |
|
1267 |
// The 2 last arguments are unused. |
||
1268 |
✓✓ | 1100 |
for (std::size_t i = 0; i < N; ++i) |
1269 |
✓✗ | 1000 |
obbDisjoint_impls::originalWithNoLowerBound(B, T, a, b, breakDistance2, |
1270 |
tmp); |
||
1271 |
100 |
end = clock_type::now(); |
|
1272 |
✓✗✓✗ ✓✗ |
100 |
result.duration[6] = (end - start) / N; |
1273 |
|||
1274 |
200 |
return result; |
|
1275 |
} |
||
1276 |
|||
1277 |
1 |
std::size_t obb_overlap_and_lower_bound_distance(std::ostream* output) { |
|
1278 |
1 |
std::size_t nbFailure = 0; |
|
1279 |
|||
1280 |
// Create two OBBs axis |
||
1281 |
✓✗✓✗ |
1 |
Vec3f a, b; |
1282 |
✓✗ | 1 |
Matrix3f B; |
1283 |
✓✗ | 1 |
Vec3f T; |
1284 |
✓✗ | 1 |
CollisionRequest request; |
1285 |
|||
1286 |
#ifndef NDEBUG // if debug mode |
||
1287 |
static const size_t nbRandomOBB = 10; |
||
1288 |
static const size_t nbTransformPerOBB = 10; |
||
1289 |
static const size_t nbRunForTimeMeas = 10; |
||
1290 |
#else |
||
1291 |
static const size_t nbRandomOBB = 100; |
||
1292 |
static const size_t nbTransformPerOBB = 100; |
||
1293 |
static const size_t nbRunForTimeMeas = 1000; |
||
1294 |
#endif |
||
1295 |
static const FCL_REAL extentNorm = 1.; |
||
1296 |
|||
1297 |
✗✓✗✗ ✗✗ |
1 |
if (output != NULL) *output << BenchmarkResult::headers << '\n'; |
1298 |
|||
1299 |
BenchmarkResult result; |
||
1300 |
✓✓ | 11 |
for (std::size_t iobb = 0; iobb < nbRandomOBB; ++iobb) { |
1301 |
✓✗ | 10 |
randomOBBs(a, b, extentNorm); |
1302 |
✓✓ | 110 |
for (std::size_t itf = 0; itf < nbTransformPerOBB; ++itf) { |
1303 |
✓✗ | 100 |
randomTransform(B, T, a, b, extentNorm); |
1304 |
✓✗ | 100 |
result = benchmark_obb_case(B, T, a, b, request, nbRunForTimeMeas); |
1305 |
✗✓✗✗ ✗✗ |
100 |
if (output != NULL) *output << result << '\n'; |
1306 |
✗✓ | 100 |
if (result.failure) nbFailure++; |
1307 |
} |
||
1308 |
} |
||
1309 |
1 |
return nbFailure; |
|
1310 |
} |
||
1311 |
|||
1312 |
1 |
int main(int argc, char** argv) { |
|
1313 |
1 |
std::ostream* output = NULL; |
|
1314 |
✗✓✗✗ |
1 |
if (argc > 1 && strcmp(argv[1], "--generate-output") == 0) { |
1315 |
output = &std::cout; |
||
1316 |
} |
||
1317 |
|||
1318 |
std::cout << "The benchmark real time measurements may be noisy and " |
||
1319 |
"will incur extra overhead." |
||
1320 |
"\nUse the following commands to turn ON:" |
||
1321 |
"\n\tsudo cpufreq-set --governor performance" |
||
1322 |
"\nor OFF:" |
||
1323 |
"\n\tsudo cpufreq-set --governor powersave" |
||
1324 |
1 |
"\n"; |
|
1325 |
|||
1326 |
1 |
std::size_t nbFailure = obb_overlap_and_lower_bound_distance(output); |
|
1327 |
✗✓ | 1 |
if (nbFailure > INT_MAX) return INT_MAX; |
1328 |
1 |
return (int)nbFailure; |
|
1329 |
} |
Generated by: GCOVR (Version 4.2) |