TORCS  1.3.9
The Open Racing Car Simulator
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 
35 Scalar rel_error = 1e-6; // relative error in the computed distance
36 Scalar abs_error = 1e-10; // absolute error if the distance is almost zero
37 
38 BBox 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 
54 static Point p[4]; // support points of object A in local coordinates
55 static Point q[4]; // support points of object B in local coordinates
56 static Vector y[4]; // support points of A - B in world coordinates
57 
58 static int bits; // identifies current simplex
59 static int last; // identifies last found support point
60 static int last_bit; // last_bit = 1<<last
61 static int all_bits; // all_bits = bits|last_bit
62 
63 static Scalar det[16][4]; // cached sub-determinants
64 
65 #ifdef STATISTICS
66 int num_iterations = 0;
67 int num_irregularities = 0;
68 #endif
69 
70 
71 
72 void compute_det() {
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 
114 inline 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 
124 inline 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 
136 inline 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 
154 inline 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 
162 inline 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;
168  compute_vector(bits, v);
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 
206 inline 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 
212 bool 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 
253 bool 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 
296 bool 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 
339 bool 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
382 void catch_me() {}
383 #endif
384 
385 
386 void 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 
404  while (bits < 15 && dist > abs_error) {
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 abs_error
Definition: Convex.cpp:36
void closest_points(const Convex &a, const Convex &b, const Transform &a2w, const Transform &b2w, Point &pa, Point &pb)
Definition: Convex.cpp:386
static Point q[4]
Definition: Convex.cpp:55
Scalar max(Scalar x, Scalar y)
Definition: Basic.h:50
const Matrix & getBasis() const
Definition: Transform.h:53
const Point & getOrigin() const
Definition: Transform.h:54
Definition: Convex.h:39
virtual Point support(const Vector &v) const =0
const Scalar INFINITY_
Definition: Basic.h:41
void setValue(const float v[3])
Definition: Tuple3.h:50
Scalar dot(const Quaternion &q1, const Quaternion &q2)
Definition: Quaternion.h:163
Scalar length() const
Definition: Vector.h:126
Definition: Basic.h:58
static int last_bit
Definition: Convex.cpp:60
Scalar rel_error
Definition: Convex.cpp:35
Definition: Basic.h:58
void compute_vector(int bits, Vector &v)
Definition: Convex.cpp:124
bool valid(int s)
Definition: Convex.cpp:114
bool approxZero(const Quaternion &q)
Definition: Quaternion.h:195
Scalar length2() const
Definition: Vector.h:125
bool degenerate(const Vector &w)
Definition: Convex.cpp:206
static Point p[4]
Definition: Convex.cpp:54
Definition: Basic.h:58
Definition: BBox.h:36
static int all_bits
Definition: Convex.cpp:61
void set_max(Scalar &x, Scalar y)
Definition: Basic.h:53
virtual BBox bbox(const Transform &t) const
Definition: Convex.cpp:38
static int bits
Definition: Convex.cpp:58
static int last
Definition: Convex.cpp:59
Scalar min(Scalar x, Scalar y)
Definition: Basic.h:49
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
#define Scalar
Definition: Basic.h:34
Definition: Vector.h:32
void compute_det()
Definition: Convex.cpp:72
void compute_points(int bits, Point &p1, Point &p2)
Definition: Convex.cpp:136
Definition: Point.h:34
bool intersect(const Convex &a, const Convex &b, const Transform &a2w, const Transform &b2w, Vector &v)
Definition: Convex.cpp:212
bool closest(Vector &v)
Definition: Convex.cpp:162
static Scalar det[16][4]
Definition: Convex.cpp:63