GteIntrOrientedBox3Frustum3.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 
12 #include <Mathematics/GteTIQuery.h>
13 
14 namespace gte
15 {
16 
17 // The method of separating axes is used. The potential separating axes
18 // include the 3 box face normals, the 5 distinct frustum normals (near and
19 // far plane have the same normal), and cross products of normals, one from
20 // the box and one from the frustum.
21 
22 template <typename Real>
23 class TIQuery<Real, OrientedBox3<Real>, Frustum3<Real>>
24 {
25 public:
26  struct Result
27  {
28  bool intersect;
29  };
30 
31  Result operator()(OrientedBox3<Real> const& box,
32  Frustum3<Real> const& frustum);
33 };
34 
35 
36 template <typename Real>
39  OrientedBox3<Real> const& box, Frustum3<Real> const& frustum)
40 {
41  Result result;
42 
43  // Convenience variables.
44  Vector3<Real> const* axis = &box.axis[0];
45  Vector3<Real> const& extent = box.extent;
46 
47  Vector3<Real> diff = box.center - frustum.origin; // C-E
48 
49  Real A[3]; // Dot(R,A[i])
50  Real B[3]; // Dot(U,A[i])
51  Real C[3]; // Dot(D,A[i])
52  Real D[3]; // (Dot(R,C-E),Dot(U,C-E),Dot(D,C-E))
53  Real NA[3]; // dmin*Dot(R,A[i])
54  Real NB[3]; // dmin*Dot(U,A[i])
55  Real NC[3]; // dmin*Dot(D,A[i])
56  Real ND[3]; // dmin*(Dot(R,C-E),Dot(U,C-E),?)
57  Real RC[3]; // rmax*Dot(D,A[i])
58  Real RD[3]; // rmax*(?,?,Dot(D,C-E))
59  Real UC[3]; // umax*Dot(D,A[i])
60  Real UD[3]; // umax*(?,?,Dot(D,C-E))
61  Real NApRC[3]; // dmin*Dot(R,A[i]) + rmax*Dot(D,A[i])
62  Real NAmRC[3]; // dmin*Dot(R,A[i]) - rmax*Dot(D,A[i])
63  Real NBpUC[3]; // dmin*Dot(U,A[i]) + umax*Dot(D,A[i])
64  Real NBmUC[3]; // dmin*Dot(U,A[i]) - umax*Dot(D,A[i])
65  Real RBpUA[3]; // rmax*Dot(U,A[i]) + umax*Dot(R,A[i])
66  Real RBmUA[3]; // rmax*Dot(U,A[i]) - umax*Dot(R,A[i])
67  Real DdD, radius, p, fmin, fmax, MTwoUF, MTwoRF, tmp;
68  int i, j;
69 
70  // M = D
71  D[2] = Dot(diff, frustum.dVector);
72  for (i = 0; i < 3; ++i)
73  {
74  C[i] = Dot(axis[i], frustum.dVector);
75  }
76  radius =
77  extent[0] * std::abs(C[0]) +
78  extent[1] * std::abs(C[1]) +
79  extent[2] * std::abs(C[2]);
80  if (D[2] + radius < frustum.dMin
81  || D[2] - radius > frustum.dMax)
82  {
83  result.intersect = false;
84  return result;
85  }
86 
87  // M = n*R - r*D
88  for (i = 0; i < 3; ++i)
89  {
90  A[i] = Dot(axis[i], frustum.rVector);
91  RC[i] = frustum.rBound*C[i];
92  NA[i] = frustum.dMin*A[i];
93  NAmRC[i] = NA[i] - RC[i];
94  }
95  D[0] = Dot(diff, frustum.rVector);
96  radius =
97  extent[0] * std::abs(NAmRC[0]) +
98  extent[1] * std::abs(NAmRC[1]) +
99  extent[2] * std::abs(NAmRC[2]);
100  ND[0] = frustum.dMin*D[0];
101  RD[2] = frustum.rBound*D[2];
102  DdD = ND[0] - RD[2];
103  MTwoRF = frustum.GetMTwoRF();
104  if (DdD + radius < MTwoRF || DdD > radius)
105  {
106  result.intersect = false;
107  return result;
108  }
109 
110  // M = -n*R - r*D
111  for (i = 0; i < 3; ++i)
112  {
113  NApRC[i] = NA[i] + RC[i];
114  }
115  radius =
116  extent[0] * std::abs(NApRC[0]) +
117  extent[1] * std::abs(NApRC[1]) +
118  extent[2] * std::abs(NApRC[2]);
119  DdD = -(ND[0] + RD[2]);
120  if (DdD + radius < MTwoRF || DdD > radius)
121  {
122  result.intersect = false;
123  return result;
124  }
125 
126  // M = n*U - u*D
127  for (i = 0; i < 3; ++i)
128  {
129  B[i] = Dot(axis[i], frustum.uVector);
130  UC[i] = frustum.uBound*C[i];
131  NB[i] = frustum.dMin*B[i];
132  NBmUC[i] = NB[i] - UC[i];
133  }
134  D[1] = Dot(diff, frustum.uVector);
135  radius =
136  extent[0] * std::abs(NBmUC[0]) +
137  extent[1] * std::abs(NBmUC[1]) +
138  extent[2] * std::abs(NBmUC[2]);
139  ND[1] = frustum.dMin*D[1];
140  UD[2] = frustum.uBound*D[2];
141  DdD = ND[1] - UD[2];
142  MTwoUF = frustum.GetMTwoUF();
143  if (DdD + radius < MTwoUF || DdD > radius)
144  {
145  result.intersect = false;
146  return result;
147  }
148 
149  // M = -n*U - u*D
150  for (i = 0; i < 3; ++i)
151  {
152  NBpUC[i] = NB[i] + UC[i];
153  }
154  radius =
155  extent[0] * std::abs(NBpUC[0]) +
156  extent[1] * std::abs(NBpUC[1]) +
157  extent[2] * std::abs(NBpUC[2]);
158  DdD = -(ND[1] + UD[2]);
159  if (DdD + radius < MTwoUF || DdD > radius)
160  {
161  result.intersect = false;
162  return result;
163  }
164 
165  // M = A[i]
166  for (i = 0; i < 3; ++i)
167  {
168  p = frustum.rBound*std::abs(A[i]) +
169  frustum.uBound*std::abs(B[i]);
170  NC[i] = frustum.dMin*C[i];
171  fmin = NC[i] - p;
172  if (fmin < (Real)0)
173  {
174  fmin *= frustum.GetDRatio();
175  }
176  fmax = NC[i] + p;
177  if (fmax >(Real)0)
178  {
179  fmax *= frustum.GetDRatio();
180  }
181  DdD = A[i] * D[0] + B[i] * D[1] + C[i] * D[2];
182  if (DdD + extent[i] < fmin || DdD - extent[i] > fmax)
183  {
184  result.intersect = false;
185  return result;
186  }
187  }
188 
189  // M = Cross(R,A[i])
190  for (i = 0; i < 3; ++i)
191  {
192  p = frustum.uBound*std::abs(C[i]);
193  fmin = -NB[i] - p;
194  if (fmin < (Real)0)
195  {
196  fmin *= frustum.GetDRatio();
197  }
198  fmax = -NB[i] + p;
199  if (fmax >(Real)0)
200  {
201  fmax *= frustum.GetDRatio();
202  }
203  DdD = C[i] * D[1] - B[i] * D[2];
204  radius =
205  extent[0] * std::abs(B[i] * C[0] - B[0] * C[i]) +
206  extent[1] * std::abs(B[i] * C[1] - B[1] * C[i]) +
207  extent[2] * std::abs(B[i] * C[2] - B[2] * C[i]);
208  if (DdD + radius < fmin || DdD - radius > fmax)
209  {
210  result.intersect = false;
211  return result;
212  }
213  }
214 
215  // M = Cross(U,A[i])
216  for (i = 0; i < 3; ++i)
217  {
218  p = frustum.rBound*std::abs(C[i]);
219  fmin = NA[i] - p;
220  if (fmin < (Real)0)
221  {
222  fmin *= frustum.GetDRatio();
223  }
224  fmax = NA[i] + p;
225  if (fmax >(Real)0)
226  {
227  fmax *= frustum.GetDRatio();
228  }
229  DdD = -C[i] * D[0] + A[i] * D[2];
230  radius =
231  extent[0] * std::abs(A[i] * C[0] - A[0] * C[i]) +
232  extent[1] * std::abs(A[i] * C[1] - A[1] * C[i]) +
233  extent[2] * std::abs(A[i] * C[2] - A[2] * C[i]);
234  if (DdD + radius < fmin || DdD - radius > fmax)
235  {
236  result.intersect = false;
237  return result;
238  }
239  }
240 
241  // M = Cross(n*D+r*R+u*U,A[i])
242  for (i = 0; i < 3; ++i)
243  {
244  Real fRB = frustum.rBound*B[i];
245  Real fUA = frustum.uBound*A[i];
246  RBpUA[i] = fRB + fUA;
247  RBmUA[i] = fRB - fUA;
248  }
249  for (i = 0; i < 3; ++i)
250  {
251  p = frustum.rBound*std::abs(NBmUC[i]) +
252  frustum.uBound*std::abs(NAmRC[i]);
253  tmp = -frustum.dMin*RBmUA[i];
254  fmin = tmp - p;
255  if (fmin < (Real)0)
256  {
257  fmin *= frustum.GetDRatio();
258  }
259  fmax = tmp + p;
260  if (fmax >(Real)0)
261  {
262  fmax *= frustum.GetDRatio();
263  }
264  DdD = D[0] * NBmUC[i] - D[1] * NAmRC[i] - D[2] * RBmUA[i];
265  radius = (Real)0;
266  for (j = 0; j < 3; j++)
267  {
268  radius += extent[j] * std::abs(A[j] * NBmUC[i] -
269  B[j] * NAmRC[i] - C[j] * RBmUA[i]);
270  }
271  if (DdD + radius < fmin || DdD - radius > fmax)
272  {
273  result.intersect = false;
274  return result;
275  }
276  }
277 
278  // M = Cross(n*D+r*R-u*U,A[i])
279  for (i = 0; i < 3; ++i)
280  {
281  p = frustum.rBound*std::abs(NBpUC[i]) +
282  frustum.uBound*std::abs(NAmRC[i]);
283  tmp = -frustum.dMin*RBpUA[i];
284  fmin = tmp - p;
285  if (fmin < (Real)0)
286  {
287  fmin *= frustum.GetDRatio();
288  }
289  fmax = tmp + p;
290  if (fmax >(Real)0)
291  {
292  fmax *= frustum.GetDRatio();
293  }
294  DdD = D[0] * NBpUC[i] - D[1] * NAmRC[i] - D[2] * RBpUA[i];
295  radius = (Real)0;
296  for (j = 0; j < 3; ++j)
297  {
298  radius += extent[j] * std::abs(A[j] * NBpUC[i] -
299  B[j] * NAmRC[i] - C[j] * RBpUA[i]);
300  }
301  if (DdD + radius < fmin || DdD - radius > fmax)
302  {
303  result.intersect = false;
304  return result;
305  }
306  }
307 
308  // M = Cross(n*D-r*R+u*U,A[i])
309  for (i = 0; i < 3; ++i)
310  {
311  p = frustum.rBound*std::abs(NBmUC[i]) +
312  frustum.uBound*std::abs(NApRC[i]);
313  tmp = frustum.dMin*RBpUA[i];
314  fmin = tmp - p;
315  if (fmin < (Real)0)
316  {
317  fmin *= frustum.GetDRatio();
318  }
319  fmax = tmp + p;
320  if (fmax >(Real)0)
321  {
322  fmax *= frustum.GetDRatio();
323  }
324  DdD = D[0] * NBmUC[i] - D[1] * NApRC[i] + D[2] * RBpUA[i];
325  radius = (Real)0;
326  for (j = 0; j < 3; ++j)
327  {
328  radius += extent[j] * std::abs(A[j] * NBmUC[i] -
329  B[j] * NApRC[i] + C[j] * RBpUA[i]);
330  }
331  if (DdD + radius < fmin || DdD - radius > fmax)
332  {
333  result.intersect = false;
334  return result;
335  }
336  }
337 
338  // M = Cross(n*D-r*R-u*U,A[i])
339  for (i = 0; i < 3; ++i)
340  {
341  p = frustum.rBound*std::abs(NBpUC[i]) +
342  frustum.uBound*std::abs(NApRC[i]);
343  tmp = frustum.dMin*RBmUA[i];
344  fmin = tmp - p;
345  if (fmin < (Real)0)
346  {
347  fmin *= frustum.GetDRatio();
348  }
349  fmax = tmp + p;
350  if (fmax >(Real)0)
351  {
352  fmax *= frustum.GetDRatio();
353  }
354  DdD = D[0] * NBpUC[i] - D[1] * NApRC[i] + D[2] * RBmUA[i];
355  radius = (Real)0;
356  for (j = 0; j < 3; ++j)
357  {
358  radius += extent[j] * std::abs(A[j] * NBpUC[i] -
359  B[j] * NApRC[i] + C[j] * RBmUA[i]);
360  }
361  if (DdD + radius < fmin || DdD - radius > fmax)
362  {
363  result.intersect = false;
364  return result;
365  }
366  }
367 
368  result.intersect = true;
369  return result;
370 }
371 
372 
373 }
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
Result operator()(Type0 const &primitive0, Type1 const &primitive1)
GLfloat GLfloat p
Definition: glext.h:11668
GLuint64EXT * result
Definition: glext.h:10003


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