TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
Convex.cpp
Go to the documentation of this file.
1/*
2 SOLID - Software Library for Interference Detection
3 Copyright (C) 1997-1998 Gino van den Bergen
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 Please send remarks, questions and bug reports to gino@win.tue.nl,
20 or write to:
21 Gino van den Bergen
22 Department of Mathematics and Computing Science
23 Eindhoven University of Technology
24 P.O. Box 513, 5600 MB Eindhoven, The Netherlands
25*/
26
27#ifdef _MSC_VER
28#pragma warning(disable:4786) // identifier was truncated to '255'
29#endif // _MSC_VER
30
31#include "Convex.h"
32#include "BBox.h"
33#include "Transform.h"
34
35Scalar rel_error = 1e-6; // relative error in the computed distance
36Scalar abs_error = 1e-10; // absolute error if the distance is almost zero
37
38BBox Convex::bbox(const Transform& t) const {
39 Point min(t.getOrigin()[X] +
40 dot(t.getBasis()[X], support(-t.getBasis()[X])) - abs_error,
41 t.getOrigin()[Y] +
42 dot(t.getBasis()[Y], support(-t.getBasis()[Y])) - abs_error,
43 t.getOrigin()[Z] +
44 dot(t.getBasis()[Z], support(-t.getBasis()[Z])) - abs_error);
45 Point max(t.getOrigin()[X] +
46 dot(t.getBasis()[X], support(t.getBasis()[X])) + abs_error,
47 t.getOrigin()[Y] +
48 dot(t.getBasis()[Y], support(t.getBasis()[Y])) + abs_error,
49 t.getOrigin()[Z] +
50 dot(t.getBasis()[Z], support(t.getBasis()[Z])) + abs_error);
51 return BBox(min, max);
52}
53
54static Point p[4]; // support points of object A in local coordinates
55static Point q[4]; // support points of object B in local coordinates
56static Vector y[4]; // support points of A - B in world coordinates
57
58static int bits; // identifies current simplex
59static int last; // identifies last found support point
60static int last_bit; // last_bit = 1<<last
61static int all_bits; // all_bits = bits|last_bit
62
63static Scalar det[16][4]; // cached sub-determinants
64
65#ifdef STATISTICS
66int num_iterations = 0;
67int num_irregularities = 0;
68#endif
69
70
71
73 static Scalar dp[4][4];
74
75 for (int i = 0, bit = 1; i < 4; ++i, bit <<=1)
76 if (bits & bit) dp[i][last] = dp[last][i] = dot(y[i], y[last]);
77 dp[last][last] = dot(y[last], y[last]);
78
79 det[last_bit][last] = 1;
80 for (int j = 0, sj = 1; j < 4; ++j, sj <<= 1) {
81 if (bits & sj) {
82 int s2 = sj|last_bit;
83 det[s2][j] = dp[last][last] - dp[last][j];
84 det[s2][last] = dp[j][j] - dp[j][last];
85 for (int k = 0, sk = 1; k < j; ++k, sk <<= 1) {
86 if (bits & sk) {
87 int s3 = sk|s2;
88 det[s3][k] = det[s2][j] * (dp[j][j] - dp[j][k]) +
89 det[s2][last] * (dp[last][j] - dp[last][k]);
90 det[s3][j] = det[sk|last_bit][k] * (dp[k][k] - dp[k][j]) +
91 det[sk|last_bit][last] * (dp[last][k] - dp[last][j]);
92 det[s3][last] = det[sk|sj][k] * (dp[k][k] - dp[k][last]) +
93 det[sk|sj][j] * (dp[j][k] - dp[j][last]);
94 }
95 }
96 }
97 }
98 if (all_bits == 15) {
99 det[15][0] = det[14][1] * (dp[1][1] - dp[1][0]) +
100 det[14][2] * (dp[2][1] - dp[2][0]) +
101 det[14][3] * (dp[3][1] - dp[3][0]);
102 det[15][1] = det[13][0] * (dp[0][0] - dp[0][1]) +
103 det[13][2] * (dp[2][0] - dp[2][1]) +
104 det[13][3] * (dp[3][0] - dp[3][1]);
105 det[15][2] = det[11][0] * (dp[0][0] - dp[0][2]) +
106 det[11][1] * (dp[1][0] - dp[1][2]) +
107 det[11][3] * (dp[3][0] - dp[3][2]);
108 det[15][3] = det[7][0] * (dp[0][0] - dp[0][3]) +
109 det[7][1] * (dp[1][0] - dp[1][3]) +
110 det[7][2] * (dp[2][0] - dp[2][3]);
111 }
112}
113
114inline bool valid(int s) {
115 for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
116 if (all_bits & bit) {
117 if (s & bit) { if (det[s][i] <= 0) return false; }
118 else if (det[s|bit][i] > 0) return false;
119 }
120 }
121 return true;
122}
123
124inline void compute_vector(int bits, Vector& v) {
125 Scalar sum = 0;
126 v.setValue(0, 0, 0);
127 for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
128 if (bits & bit) {
129 sum += det[bits][i];
130 v += y[i] * det[bits][i];
131 }
132 }
133 v *= 1 / sum;
134}
135
136inline void compute_points(int bits, Point& p1, Point& p2) {
137 Scalar sum = 0;
138 p1.setValue(0, 0, 0);
139 p2.setValue(0, 0, 0);
140 for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
141 if (bits & bit) {
142 sum += det[bits][i];
143 p1 += p[i] * det[bits][i];
144 p2 += q[i] * det[bits][i];
145 }
146 }
147 Scalar s = 1 / sum;
148 p1 *= s;
149 p2 *= s;
150}
151
152#ifdef USE_BACKUP_PROCEDURE
153
154inline bool proper(int s) {
155 for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1)
156 if ((s & bit) && det[s][i] <= 0) return false;
157 return true;
158}
159
160#endif
161
162inline bool closest(Vector& v) {
163 compute_det();
164 for (int s = bits; s; --s) {
165 if ((s & bits) == s) {
166 if (valid(s|last_bit)) {
167 bits = s|last_bit;
169 return true;
170 }
171 }
172 }
173 if (valid(last_bit)) {
174 bits = last_bit;
175 v = y[last];
176 return true;
177 }
178 // Original GJK calls the backup procedure at this point.
179
180#ifdef USE_BACKUP_PROCEDURE
181
182 Scalar min_dist2 = INFINITY_;
183 for (int s = all_bits; s; --s) {
184 if ((s & all_bits) == s) {
185 if (proper(s)) {
186 Vector u;
187 compute_vector(s, u);
188 Scalar dist2 = u.length2();
189 if (dist2 < min_dist2) {
190 min_dist2 = dist2;
191 bits = s;
192 v = u;
193 }
194 }
195 }
196 }
197
198#endif
199
200 return false;
201}
202
203// The next function is used for detecting degenerate cases that cause
204// termination problems due to rounding errors.
205
206inline bool degenerate(const Vector& w) {
207 for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1)
208 if ((all_bits & bit) && y[i] == w) return true;
209 return false;
210}
211
212bool intersect(const Convex& a, const Convex& b,
213 const Transform& a2w, const Transform& b2w,
214 Vector& v) {
215 Vector w;
216
217 bits = 0;
218 all_bits = 0;
219
220#ifdef STATISTICS
221 num_iterations = 0;
222#endif
223
224 do {
225 last = 0;
226 last_bit = 1;
227 while (bits & last_bit) { ++last; last_bit <<= 1; }
228 w = a2w(a.support((-v) * a2w.getBasis())) -
229 b2w(b.support(v * b2w.getBasis()));
230 if (dot(v, w) > 0) return false;
231 if (degenerate(w)) {
232#ifdef STATISTICS
233 ++num_irregularities;
234#endif
235 return false;
236 }
237 y[last] = w;
239#ifdef STATISTICS
240 ++num_iterations;
241#endif
242 if (!closest(v)) {
243#ifdef STATISTICS
244 ++num_irregularities;
245#endif
246 return false;
247 }
248 }
249 while (bits < 15 && !approxZero(v));
250 return true;
251}
252
253bool intersect(const Convex& a, const Convex& b, const Transform& b2a,
254 Vector& v) {
255 Vector w;
256
257 bits = 0;
258 all_bits = 0;
259
260#ifdef STATISTICS
261 num_iterations = 0;
262#endif
263
264 do {
265 last = 0;
266 last_bit = 1;
267 while (bits & last_bit) { ++last; last_bit <<= 1; }
268 w = a.support(-v) - b2a(b.support(v * b2a.getBasis()));
269 if (dot(v, w) > 0) return false;
270 if (degenerate(w)) {
271#ifdef STATISTICS
272 ++num_irregularities;
273#endif
274 return false;
275 }
276 y[last] = w;
278#ifdef STATISTICS
279 ++num_iterations;
280#endif
281 if (!closest(v)) {
282#ifdef STATISTICS
283 ++num_irregularities;
284#endif
285 return false;
286 }
287 }
288 while (bits < 15 && !approxZero(v));
289 return true;
290}
291
292
293
294
295
296bool common_point(const Convex& a, const Convex& b,
297 const Transform& a2w, const Transform& b2w,
298 Vector& v, Point& pa, Point& pb) {
299 Vector w;
300
301 bits = 0;
302 all_bits = 0;
303
304#ifdef STATISTICS
305 num_iterations = 0;
306#endif
307
308 do {
309 last = 0;
310 last_bit = 1;
311 while (bits & last_bit) { ++last; last_bit <<= 1; }
312 p[last] = a.support((-v) * a2w.getBasis());
313 q[last] = b.support(v * b2w.getBasis());
314 w = a2w(p[last]) - b2w(q[last]);
315 if (dot(v, w) > 0) return false;
316 if (degenerate(w)) {
317#ifdef STATISTICS
318 ++num_irregularities;
319#endif
320 return false;
321 }
322 y[last] = w;
324#ifdef STATISTICS
325 ++num_iterations;
326#endif
327 if (!closest(v)) {
328#ifdef STATISTICS
329 ++num_irregularities;
330#endif
331 return false;
332 }
333 }
334 while (bits < 15 && !approxZero(v) ) ;
335 compute_points(bits, pa, pb);
336 return true;
337}
338
339bool common_point(const Convex& a, const Convex& b, const Transform& b2a,
340 Vector& v, Point& pa, Point& pb) {
341 Vector w;
342
343 bits = 0;
344 all_bits = 0;
345
346#ifdef STATISTICS
347 num_iterations = 0;
348#endif
349
350 do {
351 last = 0;
352 last_bit = 1;
353 while (bits & last_bit) { ++last; last_bit <<= 1; }
354 p[last] = a.support(-v);
355 q[last] = b.support(v * b2a.getBasis());
356 w = p[last] - b2a(q[last]);
357 if (dot(v, w) > 0) return false;
358 if (degenerate(w)) {
359#ifdef STATISTICS
360 ++num_irregularities;
361#endif
362 return false;
363 }
364 y[last] = w;
366#ifdef STATISTICS
367 ++num_iterations;
368#endif
369 if (!closest(v)) {
370#ifdef STATISTICS
371 ++num_irregularities;
372#endif
373 return false;
374 }
375 }
376 while (bits < 15 && !approxZero(v) );
377 compute_points(bits, pa, pb);
378 return true;
379}
380
381#ifdef STATISTICS
382void catch_me() {}
383#endif
384
385
386void closest_points(const Convex& a, const Convex& b,
387 const Transform& a2w, const Transform& b2w,
388 Point& pa, Point& pb) {
389 static Vector zero(0, 0, 0);
390
391 Vector v = a2w(a.support(zero)) - b2w(b.support(zero));
392 Scalar dist = v.length();
393
394 Vector w;
395
396 bits = 0;
397 all_bits = 0;
398 Scalar mu = 0;
399
400#ifdef STATISTICS
401 num_iterations = 0;
402#endif
403
405 last = 0;
406 last_bit = 1;
407 while (bits & last_bit) { ++last; last_bit <<= 1; }
408 p[last] = a.support((-v) * a2w.getBasis());
409 q[last] = b.support(v * b2w.getBasis());
410 w = a2w(p[last]) - b2w(q[last]);
411 set_max(mu, dot(v, w) / dist);
412 if (dist - mu <= dist * rel_error) break;
413 if (degenerate(w)) {
414#ifdef STATISTICS
415 ++num_irregularities;
416#endif
417 break;
418 }
419 y[last] = w;
421#ifdef STATISTICS
422 ++num_iterations;
423 if (num_iterations > 1000) catch_me();
424#endif
425 if (!closest(v)) {
426#ifdef STATISTICS
427 ++num_irregularities;
428#endif
429 break;
430 }
431 dist = v.length();
432 }
433 compute_points(bits, pa, pb);
434}
435
436
437
Scalar min(Scalar x, Scalar y)
Definition Basic.h:49
const Scalar INFINITY_
Definition Basic.h:41
@ Y
Definition Basic.h:58
@ X
Definition Basic.h:58
@ Z
Definition Basic.h:58
Scalar max(Scalar x, Scalar y)
Definition Basic.h:50
#define Scalar
Definition Basic.h:34
void set_max(Scalar &x, Scalar y)
Definition Basic.h:53
Scalar rel_error
Definition Convex.cpp:35
void compute_points(int bits, Point &p1, Point &p2)
Definition Convex.cpp:136
void compute_det()
Definition Convex.cpp:72
static Point q[4]
Definition Convex.cpp:55
static Point p[4]
Definition Convex.cpp:54
Scalar abs_error
Definition Convex.cpp:36
static int all_bits
Definition Convex.cpp:61
bool closest(Vector &v)
Definition Convex.cpp:162
bool valid(int s)
Definition Convex.cpp:114
static int last
Definition Convex.cpp:59
static Scalar det[16][4]
Definition Convex.cpp:63
void compute_vector(int bits, Vector &v)
Definition Convex.cpp:124
bool common_point(const Convex &a, const Convex &b, const Transform &a2w, const Transform &b2w, Vector &v, Point &pa, Point &pb)
Definition Convex.cpp:296
static Vector y[4]
Definition Convex.cpp:56
void closest_points(const Convex &a, const Convex &b, const Transform &a2w, const Transform &b2w, Point &pa, Point &pb)
Definition Convex.cpp:386
static int bits
Definition Convex.cpp:58
static int last_bit
Definition Convex.cpp:60
bool degenerate(const Vector &w)
Definition Convex.cpp:206
bool intersect(const Convex &a, const Convex &b, const Transform &a2w, const Transform &b2w, Vector &v)
Definition Convex.cpp:212
bool approxZero(const Quaternion &q)
Definition Quaternion.h:195
Scalar dot(const Quaternion &q1, const Quaternion &q2)
Definition Quaternion.h:163
Definition BBox.h:36
virtual Point support(const Vector &v) const =0
virtual BBox bbox(const Transform &t) const
Definition Convex.cpp:38
Definition Point.h:34
const Point & getOrigin() const
Definition Transform.h:54
const Matrix & getBasis() const
Definition Transform.h:53
void setValue(const float v[3])
Definition Tuple3.h:50
Scalar length() const
Definition Vector.h:126
Scalar length2() const
Definition Vector.h:125