GteIntrOrientedBox3OrientedBox3.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <Mathematics/GteVector3.h>
12 #include <Mathematics/GteFIQuery.h>
13 #include <Mathematics/GteTIQuery.h>
14 
15 // The queries consider the box to be a solid.
16 //
17 // The test-intersection query uses the method of separating axes. The set of
18 // potential separating directions includes the 3 face normals of box0, the 3
19 // face normals of box1, and 9 directions, each of which is the cross product
20 // of an edge of box0 and and an edge of box1.
21 //
22 // The separating axes involving cross products of edges has numerical
23 // robustness problems when the two edges are nearly parallel. The cross
24 // product of the edges is nearly the zero vector, so normalization of the
25 // cross product may produce unit-length directions that are not close to the
26 // true direction. Such a pair of edges occurs when a box0 face normal N0 and
27 // a box1 face normal N1 are nearly parallel. In this case, you may skip the
28 // edge-edge directions, which is equivalent to projecting the boxes onto the
29 // plane with normal N0 and applying a 2D separating axis test. The ability
30 // to do so involves choosing a small nonnegative epsilon . It is used to
31 // determine whether two face normals, one from each box, are nearly parallel:
32 // |Dot(N0,N1)| >= 1 - epsilon. If the input is negative, it is clamped to
33 // zero.
34 //
35 // The pair of integers 'separating', say, (i0,i1), identify the axis that
36 // reported separation; there may be more than one but only one is
37 // reported. If the separating axis is a face normal N[i0] of the aligned
38 // box0 in dimension i0, then (i0,-1) is returned. If the axis is a face
39 // normal box1.Axis[i1], then (-1,i1) is returned. If the axis is a cross
40 // product of edges, Cross(N[i0],box1.Axis[i1]), then (i0,i1) is returned.
41 
42 namespace gte
43 {
44 
45 template <typename Real>
46 class TIQuery<Real, OrientedBox3<Real>, OrientedBox3<Real>>
47 {
48 public:
49  struct Result
50  {
51  // The 'epsilon' value must be nonnegative.
52  Result(Real inEpsilon = (Real)0);
53 
54  bool intersect;
55  Real epsilon;
56  int separating[2];
57  };
58 
59  Result operator()(OrientedBox3<Real> const& box0,
60  OrientedBox3<Real> const& box1);
61 };
62 
63 
64 template <typename Real>
66 Result(Real inEpsilon)
67 {
68  if (inEpsilon >= (Real)0)
69  {
70  epsilon = inEpsilon;
71  }
72  else
73  {
74  epsilon = (Real)0;
75  }
76 }
77 
78 template <typename Real>
81  OrientedBox3<Real> const& box0, OrientedBox3<Real> const& box1)
82 {
83  Result result;
84 
85  // Convenience variables.
86  Vector3<Real> const& C0 = box0.center;
87  Vector3<Real> const* A0 = &box0.axis[0];
88  Vector3<Real> const& E0 = box0.extent;
89  Vector3<Real> const& C1 = box1.center;
90  Vector3<Real> const* A1 = &box1.axis[0];
91  Vector3<Real> const& E1 = box1.extent;
92 
93  const Real cutoff = (Real)1 - result.epsilon;
94  bool existsParallelPair = false;
95 
96  // Compute difference of box centers.
97  Vector3<Real> D = C1 - C0;
98 
99  Real dot01[3][3]; // dot01[i][j] = Dot(A0[i],A1[j]) = A1[j][i]
100  Real absDot01[3][3]; // |dot01[i][j]|
101  Real dotDA0[3]; // Dot(D, A0[i])
102  Real r0, r1, r; // interval radii and distance between centers
103  Real r01; // r0 + r1
104 
105  // Test for separation on the axis C0 + t*A0[0].
106  for (int i = 0; i < 3; ++i)
107  {
108  dot01[0][i] = Dot(A0[0], A1[i]);
109  absDot01[0][i] = std::abs(dot01[0][i]);
110  if (absDot01[0][i] > cutoff)
111  {
112  existsParallelPair = true;
113  }
114  }
115  dotDA0[0] = Dot(D, A0[0]);
116  r = std::abs(dotDA0[0]);
117  r1 = E1[0] * absDot01[0][0] + E1[1] * absDot01[0][1] + E1[2] * absDot01[0][2];
118  r01 = E0[0] + r1;
119  if (r > r01)
120  {
121  result.intersect = false;
122  result.separating[0] = 0;
123  result.separating[1] = -1;
124  return result;
125  }
126 
127  // Test for separation on the axis C0 + t*A0[1].
128  for (int i = 0; i < 3; ++i)
129  {
130  dot01[1][i] = Dot(A0[1], A1[i]);
131  absDot01[1][i] = std::abs(dot01[1][i]);
132  if (absDot01[1][i] > cutoff)
133  {
134  existsParallelPair = true;
135  }
136  }
137  dotDA0[1] = Dot(D, A0[1]);
138  r = std::abs(dotDA0[1]);
139  r1 = E1[0] * absDot01[1][0] + E1[1] * absDot01[1][1] + E1[2] * absDot01[1][2];
140  r01 = E0[1] + r1;
141  if (r > r01)
142  {
143  result.intersect = false;
144  result.separating[0] = 1;
145  result.separating[1] = -1;
146  return result;
147  }
148 
149  // Test for separation on the axis C0 + t*A0[2].
150  for (int i = 0; i < 3; ++i)
151  {
152  dot01[2][i] = Dot(A0[2], A1[i]);
153  absDot01[2][i] = std::abs(dot01[2][i]);
154  if (absDot01[2][i] > cutoff)
155  {
156  existsParallelPair = true;
157  }
158  }
159  dotDA0[2] = Dot(D, A0[2]);
160  r = std::abs(dotDA0[2]);
161  r1 = E1[0] * absDot01[2][0] + E1[1] * absDot01[2][1] + E1[2] * absDot01[2][2];
162  r01 = E0[2] + r1;
163  if (r > r01)
164  {
165  result.intersect = false;
166  result.separating[0] = 2;
167  result.separating[1] = -1;
168  return result;
169  }
170 
171  // Test for separation on the axis C0 + t*A1[0].
172  r = std::abs(Dot(D, A1[0]));
173  r0 = E0[0] * absDot01[0][0] + E0[1] * absDot01[1][0] + E0[2] * absDot01[2][0];
174  r01 = r0 + E1[0];
175  if (r > r01)
176  {
177  result.intersect = false;
178  result.separating[0] = -1;
179  result.separating[1] = 0;
180  return result;
181  }
182 
183  // Test for separation on the axis C0 + t*A1[1].
184  r = std::abs(Dot(D, A1[1]));
185  r0 = E0[0] * absDot01[0][1] + E0[1] * absDot01[1][1] + E0[2] * absDot01[2][1];
186  r01 = r0 + E1[1];
187  if (r > r01)
188  {
189  result.intersect = false;
190  result.separating[0] = -1;
191  result.separating[1] = 1;
192  return result;
193  }
194 
195  // Test for separation on the axis C0 + t*A1[2].
196  r = std::abs(Dot(D, A1[2]));
197  r0 = E0[0] * absDot01[0][2] + E0[1] * absDot01[1][2] + E0[2] * absDot01[2][2];
198  r01 = r0 + E1[2];
199  if (r > r01)
200  {
201  result.intersect = false;
202  result.separating[0] = -1;
203  result.separating[1] = 2;
204  return result;
205  }
206 
207  // At least one pair of box axes was parallel, so the separation is
208  // effectively in 2D. The edge-edge axes do not need to be tested.
209  if (existsParallelPair)
210  {
211  return true;
212  }
213 
214  // Test for separation on the axis C0 + t*A0[0]xA1[0].
215  r = std::abs(dotDA0[2] * dot01[1][0] - dotDA0[1] * dot01[2][0]);
216  r0 = E0[1] * absDot01[2][0] + E0[2] * absDot01[1][0];
217  r1 = E1[1] * absDot01[0][2] + E1[2] * absDot01[0][1];
218  r01 = r0 + r1;
219  if (r > r01)
220  {
221  result.intersect = false;
222  result.separating[0] = 0;
223  result.separating[1] = 0;
224  return result;
225  }
226 
227  // Test for separation on the axis C0 + t*A0[0]xA1[1].
228  r = std::abs(dotDA0[2] * dot01[1][1] - dotDA0[1] * dot01[2][1]);
229  r0 = E0[1] * absDot01[2][1] + E0[2] * absDot01[1][1];
230  r1 = E1[0] * absDot01[0][2] + E1[2] * absDot01[0][0];
231  r01 = r0 + r1;
232  if (r > r01)
233  {
234  result.intersect = false;
235  result.separating[0] = 0;
236  result.separating[1] = 1;
237  return result;
238  }
239 
240  // Test for separation on the axis C0 + t*A0[0]xA1[2].
241  r = std::abs(dotDA0[2] * dot01[1][2] - dotDA0[1] * dot01[2][2]);
242  r0 = E0[1] * absDot01[2][2] + E0[2] * absDot01[1][2];
243  r1 = E1[0] * absDot01[0][1] + E1[1] * absDot01[0][0];
244  r01 = r0 + r1;
245  if (r > r01)
246  {
247  result.intersect = false;
248  result.separating[0] = 0;
249  result.separating[1] = 2;
250  return result;
251  }
252 
253  // Test for separation on the axis C0 + t*A0[1]xA1[0].
254  r = std::abs(dotDA0[0] * dot01[2][0] - dotDA0[2] * dot01[0][0]);
255  r0 = E0[0] * absDot01[2][0] + E0[2] * absDot01[0][0];
256  r1 = E1[1] * absDot01[1][2] + E1[2] * absDot01[1][1];
257  r01 = r0 + r1;
258  if (r > r01)
259  {
260  result.intersect = false;
261  result.separating[0] = 1;
262  result.separating[1] = 0;
263  return result;
264  }
265 
266  // Test for separation on the axis C0 + t*A0[1]xA1[1].
267  r = std::abs(dotDA0[0] * dot01[2][1] - dotDA0[2] * dot01[0][1]);
268  r0 = E0[0] * absDot01[2][1] + E0[2] * absDot01[0][1];
269  r1 = E1[0] * absDot01[1][2] + E1[2] * absDot01[1][0];
270  r01 = r0 + r1;
271  if (r > r01)
272  {
273  result.intersect = false;
274  result.separating[0] = 1;
275  result.separating[1] = 1;
276  return result;
277  }
278 
279  // Test for separation on the axis C0 + t*A0[1]xA1[2].
280  r = std::abs(dotDA0[0] * dot01[2][2] - dotDA0[2] * dot01[0][2]);
281  r0 = E0[0] * absDot01[2][2] + E0[2] * absDot01[0][2];
282  r1 = E1[0] * absDot01[1][1] + E1[1] * absDot01[1][0];
283  r01 = r0 + r1;
284  if (r > r01)
285  {
286  result.intersect = false;
287  result.separating[0] = 1;
288  result.separating[1] = 2;
289  return result;
290  }
291 
292  // Test for separation on the axis C0 + t*A0[2]xA1[0].
293  r = std::abs(dotDA0[1] * dot01[0][0] - dotDA0[0] * dot01[1][0]);
294  r0 = E0[0] * absDot01[1][0] + E0[1] * absDot01[0][0];
295  r1 = E1[1] * absDot01[2][2] + E1[2] * absDot01[2][1];
296  r01 = r0 + r1;
297  if (r > r01)
298  {
299  result.intersect = false;
300  result.separating[0] = 2;
301  result.separating[1] = 0;
302  return result;
303  }
304 
305  // Test for separation on the axis C0 + t*A0[2]xA1[1].
306  r = std::abs(dotDA0[1] * dot01[0][1] - dotDA0[0] * dot01[1][1]);
307  r0 = E0[0] * absDot01[1][1] + E0[1] * absDot01[0][1];
308  r1 = E1[0] * absDot01[2][2] + E1[2] * absDot01[2][0];
309  r01 = r0 + r1;
310  if (r > r01)
311  {
312  result.intersect = false;
313  result.separating[0] = 2;
314  result.separating[1] = 1;
315  return result;
316  }
317 
318  // Test for separation on the axis C0 + t*A0[2]xA1[2].
319  r = std::abs(dotDA0[1] * dot01[0][2] - dotDA0[0] * dot01[1][2]);
320  r0 = E0[0] * absDot01[1][2] + E0[1] * absDot01[0][2];
321  r1 = E1[0] * absDot01[2][1] + E1[1] * absDot01[2][0];
322  r01 = r0 + r1;
323  if (r > r01)
324  {
325  result.intersect = false;
326  result.separating[0] = 2;
327  result.separating[1] = 2;
328  return result;
329  }
330 
331  result.intersect = true;
332  return result;
333 }
334 
335 
336 }
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLboolean r
Definition: glcorearb.h:1217
Result operator()(Type0 const &primitive0, Type1 const &primitive1)
GLuint64EXT * result
Definition: glext.h:10003


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:00