HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImathBoxAlgo.h
Go to the documentation of this file.
1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
4 //
5 
6 //
7 // Axis-aligned bounding box utility functions
8 //
9 
10 #ifndef INCLUDED_IMATHBOXALGO_H
11 #define INCLUDED_IMATHBOXALGO_H
12 
13 #include "ImathNamespace.h"
14 
15 #include "ImathBox.h"
16 #include "ImathLineAlgo.h"
17 #include "ImathMatrix.h"
18 #include "ImathPlane.h"
19 
20 IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
21 
22 ///
23 /// Clip the coordinates of a point, `p`, against a `Box<T>`, `box`.
24 /// Return the closest point to `p` that is inside the box.
25 ///
26 
27 template <class T>
28 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
29 clip (const T& p, const Box<T>& box) IMATH_NOEXCEPT
30 {
31  T q;
32 
33  for (int i = 0; i < int (box.min.dimensions ()); i++)
34  {
35  if (p[i] < box.min[i])
36  q[i] = box.min[i];
37  else if (p[i] > box.max[i])
38  q[i] = box.max[i];
39  else
40  q[i] = p[i];
41  }
42 
43  return q;
44 }
45 
46 ///
47 /// Return the point in or on the `Box<T>`, `box`, that is closesest to
48 /// the point, `p`.
49 ///
50 
51 template <class T>
52 IMATH_HOSTDEVICE constexpr inline T
53 closestPointInBox (const T& p, const Box<T>& box) IMATH_NOEXCEPT
54 {
55  return clip (p, box);
56 }
57 
58 ///
59 /// Return the point on the surface of the `Box<T>`, `box`, that is
60 /// closest to point `p`.
61 ///
62 /// If the box is empty, return `p`.
63 ///
64 
65 template <class T>
66 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3<T>
68 {
69  if (box.isEmpty ()) return p;
70 
71  Vec3<T> q = closestPointInBox (p, box);
72 
73  if (q == p)
74  {
75  Vec3<T> d1 = p - box.min;
76  Vec3<T> d2 = box.max - p;
77 
78  Vec3<T> d (
79  (d1.x < d2.x) ? d1.x : d2.x,
80  (d1.y < d2.y) ? d1.y : d2.y,
81  (d1.z < d2.z) ? d1.z : d2.z);
82 
83  if (d.x < d.y && d.x < d.z)
84  {
85  q.x = (d1.x < d2.x) ? box.min.x : box.max.x;
86  }
87  else if (d.y < d.z)
88  {
89  q.y = (d1.y < d2.y) ? box.min.y : box.max.y;
90  }
91  else
92  {
93  q.z = (d1.z < d2.z) ? box.min.z : box.max.z;
94  }
95  }
96 
97  return q;
98 }
99 
100 ///
101 /// Transform a 3D box by a matrix, and compute a new box that
102 /// tightly encloses the transformed box. Return the transformed box.
103 ///
104 /// If `m` is an affine transform, then we use James Arvo's fast
105 /// method as described in "Graphics Gems", Academic Press, 1990,
106 /// pp. 548-550.
107 ///
108 /// A transformed empty box is still empty, and a transformed infinite box
109 /// is still infinite.
110 ///
111 
112 template <class S, class T>
115 {
116  if (box.isEmpty () || box.isInfinite ()) return box;
117 
118  //
119  // If the last column of m is (0 0 0 1) then m is an affine
120  // transform, and we use the fast Graphics Gems trick.
121  //
122 
123  if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1)
124  {
125  Box<Vec3<S>> newBox;
126 
127  for (int i = 0; i < 3; i++)
128  {
129  newBox.min[i] = newBox.max[i] = (S) m[3][i];
130 
131  for (int j = 0; j < 3; j++)
132  {
133  S a, b;
134 
135  a = (S) m[j][i] * box.min[j];
136  b = (S) m[j][i] * box.max[j];
137 
138  if (a < b)
139  {
140  newBox.min[i] += a;
141  newBox.max[i] += b;
142  }
143  else
144  {
145  newBox.min[i] += b;
146  newBox.max[i] += a;
147  }
148  }
149  }
150 
151  return newBox;
152  }
153 
154  //
155  // M is a projection matrix. Do things the naive way:
156  // Transform the eight corners of the box, and find an
157  // axis-parallel box that encloses the transformed corners.
158  //
159 
160  Vec3<S> points[8];
161 
162  points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0];
163  points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0];
164 
165  points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1];
166  points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1];
167 
168  points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2];
169  points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2];
170 
171  Box<Vec3<S>> newBox;
172 
173  for (int i = 0; i < 8; i++)
174  newBox.extendBy (points[i] * m);
175 
176  return newBox;
177 }
178 
179 ///
180 /// Transform a 3D box by a matrix, and compute a new box that
181 /// tightly encloses the transformed box. The transformed box is
182 /// returned in the `result` argument.
183 ///
184 /// If m is an affine transform, then we use James Arvo's fast
185 /// method as described in "Graphics Gems", Academic Press, 1990,
186 /// pp. 548-550.
187 ///
188 /// A transformed empty box is still empty, and a transformed infinite
189 /// box is still infinite
190 ///
191 
192 template <class S, class T>
193 IMATH_HOSTDEVICE void
194 transform (const Box<Vec3<S>>& box, const Matrix44<T>& m, Box<Vec3<S>>& result)
196 {
197  if (box.isEmpty () || box.isInfinite ()) { return; }
198 
199  //
200  // If the last column of m is (0 0 0 1) then m is an affine
201  // transform, and we use the fast Graphics Gems trick.
202  //
203 
204  if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1)
205  {
206  for (int i = 0; i < 3; i++)
207  {
208  result.min[i] = result.max[i] = (S) m[3][i];
209 
210  for (int j = 0; j < 3; j++)
211  {
212  S a, b;
213 
214  a = (S) m[j][i] * box.min[j];
215  b = (S) m[j][i] * box.max[j];
216 
217  if (a < b)
218  {
219  result.min[i] += a;
220  result.max[i] += b;
221  }
222  else
223  {
224  result.min[i] += b;
225  result.max[i] += a;
226  }
227  }
228  }
229 
230  return;
231  }
232 
233  //
234  // M is a projection matrix. Do things the naive way:
235  // Transform the eight corners of the box, and find an
236  // axis-parallel box that encloses the transformed corners.
237  //
238 
239  Vec3<S> points[8];
240 
241  points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0];
242  points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0];
243 
244  points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1];
245  points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1];
246 
247  points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2];
248  points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2];
249 
250  for (int i = 0; i < 8; i++)
251  result.extendBy (points[i] * m);
252 }
253 
254 ///
255 /// Transform a 3D box by a matrix whose rightmost column `(0 0 0 1)`,
256 /// and compute a new box that tightly encloses the transformed
257 /// box. Return the transformed box.
258 ///
259 /// As in the transform() function, use James Arvo's fast method if
260 /// possible.
261 ///
262 /// A transformed empty or infinite box is still empty or infinite.
263 ///
264 
265 template <class S, class T>
268 {
269  if (box.isEmpty () || box.isInfinite ()) return box;
270 
271  Box<Vec3<S>> newBox;
272 
273  for (int i = 0; i < 3; i++)
274  {
275  newBox.min[i] = newBox.max[i] = (S) m[3][i];
276 
277  for (int j = 0; j < 3; j++)
278  {
279  S a, b;
280 
281  a = (S) m[j][i] * box.min[j];
282  b = (S) m[j][i] * box.max[j];
283 
284  if (a < b)
285  {
286  newBox.min[i] += a;
287  newBox.max[i] += b;
288  }
289  else
290  {
291  newBox.min[i] += b;
292  newBox.max[i] += a;
293  }
294  }
295  }
296 
297  return newBox;
298 }
299 
300 ///
301 /// Transform a 3D box by a matrix whose rightmost column is
302 /// `(0 0 0 1)`, and compute a new box that tightly encloses
303 /// the transformed box. Return the transformed box in the `result`
304 /// argument.
305 ///
306 /// As in the transform() function, use James Arvo's fast method if
307 /// possible.
308 ///
309 /// A transformed empty or infinite box is still empty or infinite.
310 ///
311 
312 template <class S, class T>
313 IMATH_HOSTDEVICE void
315  const Box<Vec3<S>>& box,
316  const Matrix44<T>& m,
318 {
319  if (box.isEmpty ())
320  {
321  result.makeEmpty ();
322  return;
323  }
324 
325  if (box.isInfinite ())
326  {
327  result.makeInfinite ();
328  return;
329  }
330 
331  for (int i = 0; i < 3; i++)
332  {
333  result.min[i] = result.max[i] = (S) m[3][i];
334 
335  for (int j = 0; j < 3; j++)
336  {
337  S a, b;
338 
339  a = (S) m[j][i] * box.min[j];
340  b = (S) m[j][i] * box.max[j];
341 
342  if (a < b)
343  {
344  result.min[i] += a;
345  result.max[i] += b;
346  }
347  else
348  {
349  result.min[i] += b;
350  result.max[i] += a;
351  }
352  }
353  }
354 }
355 
356 ///
357 /// Compute the points where a ray, `r`, enters and exits a 3D box, `b`:
358 ///
359 /// Return true if the ray starts inside the box or if the ray starts
360 /// outside and intersects the box, or return false otherwise (that
361 /// is, if the ray does not intersect the box).
362 ///
363 /// The entry and exit points are the points on two of the faces of
364 /// the box when the function returns true (the entry end exit points
365 /// may be on either side of the ray's origin), or undefined if the
366 /// the function returns false.
367 ///
368 
369 template <class T>
370 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
372  const Line3<T>& r, const Box<Vec3<T>>& b, Vec3<T>& entry, Vec3<T>& exit)
374 {
375  if (b.isEmpty ())
376  {
377  //
378  // No ray intersects an empty box
379  //
380 
381  return false;
382  }
383 
384  //
385  // The following description assumes that the ray's origin is outside
386  // the box, but the code below works even if the origin is inside the
387  // box:
388  //
389  // Between one and three "frontfacing" sides of the box are oriented
390  // towards the ray's origin, and between one and three "backfacing"
391  // sides are oriented away from the ray's origin.
392  // We intersect the ray with the planes that contain the sides of the
393  // box, and compare the distances between the ray's origin and the
394  // ray-plane intersections. The ray intersects the box if the most
395  // distant frontfacing intersection is nearer than the nearest
396  // backfacing intersection. If the ray does intersect the box, then
397  // the most distant frontfacing ray-plane intersection is the entry
398  // point and the nearest backfacing ray-plane intersection is the
399  // exit point.
400  //
401 
402  const T TMAX = std::numeric_limits<T>::max ();
403 
404  T tFrontMax = -TMAX;
405  T tBackMin = TMAX;
406 
407  //
408  // Minimum and maximum X sides.
409  //
410 
411  if (r.dir.x >= 0)
412  {
413  T d1 = b.max.x - r.pos.x;
414  T d2 = b.min.x - r.pos.x;
415 
416  if (r.dir.x > 1 ||
417  (abs (d1) < TMAX * r.dir.x && abs (d2) < TMAX * r.dir.x))
418  {
419  T t1 = d1 / r.dir.x;
420  T t2 = d2 / r.dir.x;
421 
422  if (tBackMin > t1)
423  {
424  tBackMin = t1;
425 
426  exit.x = b.max.x;
427  exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
428  exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
429  }
430 
431  if (tFrontMax < t2)
432  {
433  tFrontMax = t2;
434 
435  entry.x = b.min.x;
436  entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
437  entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
438  }
439  }
440  else if (r.pos.x < b.min.x || r.pos.x > b.max.x)
441  {
442  return false;
443  }
444  }
445  else // r.dir.x < 0
446  {
447  T d1 = b.min.x - r.pos.x;
448  T d2 = b.max.x - r.pos.x;
449 
450  if (r.dir.x < -1 ||
451  (abs (d1) < -TMAX * r.dir.x && abs (d2) < -TMAX * r.dir.x))
452  {
453  T t1 = d1 / r.dir.x;
454  T t2 = d2 / r.dir.x;
455 
456  if (tBackMin > t1)
457  {
458  tBackMin = t1;
459 
460  exit.x = b.min.x;
461  exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
462  exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
463  }
464 
465  if (tFrontMax < t2)
466  {
467  tFrontMax = t2;
468 
469  entry.x = b.max.x;
470  entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
471  entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
472  }
473  }
474  else if (r.pos.x < b.min.x || r.pos.x > b.max.x)
475  {
476  return false;
477  }
478  }
479 
480  //
481  // Minimum and maximum Y sides.
482  //
483 
484  if (r.dir.y >= 0)
485  {
486  T d1 = b.max.y - r.pos.y;
487  T d2 = b.min.y - r.pos.y;
488 
489  if (r.dir.y > 1 ||
490  (abs (d1) < TMAX * r.dir.y && abs (d2) < TMAX * r.dir.y))
491  {
492  T t1 = d1 / r.dir.y;
493  T t2 = d2 / r.dir.y;
494 
495  if (tBackMin > t1)
496  {
497  tBackMin = t1;
498 
499  exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
500  exit.y = b.max.y;
501  exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
502  }
503 
504  if (tFrontMax < t2)
505  {
506  tFrontMax = t2;
507 
508  entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
509  entry.y = b.min.y;
510  entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
511  }
512  }
513  else if (r.pos.y < b.min.y || r.pos.y > b.max.y)
514  {
515  return false;
516  }
517  }
518  else // r.dir.y < 0
519  {
520  T d1 = b.min.y - r.pos.y;
521  T d2 = b.max.y - r.pos.y;
522 
523  if (r.dir.y < -1 ||
524  (abs (d1) < -TMAX * r.dir.y && abs (d2) < -TMAX * r.dir.y))
525  {
526  T t1 = d1 / r.dir.y;
527  T t2 = d2 / r.dir.y;
528 
529  if (tBackMin > t1)
530  {
531  tBackMin = t1;
532 
533  exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
534  exit.y = b.min.y;
535  exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
536  }
537 
538  if (tFrontMax < t2)
539  {
540  tFrontMax = t2;
541 
542  entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
543  entry.y = b.max.y;
544  entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
545  }
546  }
547  else if (r.pos.y < b.min.y || r.pos.y > b.max.y)
548  {
549  return false;
550  }
551  }
552 
553  //
554  // Minimum and maximum Z sides.
555  //
556 
557  if (r.dir.z >= 0)
558  {
559  T d1 = b.max.z - r.pos.z;
560  T d2 = b.min.z - r.pos.z;
561 
562  if (r.dir.z > 1 ||
563  (abs (d1) < TMAX * r.dir.z && abs (d2) < TMAX * r.dir.z))
564  {
565  T t1 = d1 / r.dir.z;
566  T t2 = d2 / r.dir.z;
567 
568  if (tBackMin > t1)
569  {
570  tBackMin = t1;
571 
572  exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
573  exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
574  exit.z = b.max.z;
575  }
576 
577  if (tFrontMax < t2)
578  {
579  tFrontMax = t2;
580 
581  entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
582  entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
583  entry.z = b.min.z;
584  }
585  }
586  else if (r.pos.z < b.min.z || r.pos.z > b.max.z)
587  {
588  return false;
589  }
590  }
591  else // r.dir.z < 0
592  {
593  T d1 = b.min.z - r.pos.z;
594  T d2 = b.max.z - r.pos.z;
595 
596  if (r.dir.z < -1 ||
597  (abs (d1) < -TMAX * r.dir.z && abs (d2) < -TMAX * r.dir.z))
598  {
599  T t1 = d1 / r.dir.z;
600  T t2 = d2 / r.dir.z;
601 
602  if (tBackMin > t1)
603  {
604  tBackMin = t1;
605 
606  exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
607  exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
608  exit.z = b.min.z;
609  }
610 
611  if (tFrontMax < t2)
612  {
613  tFrontMax = t2;
614 
615  entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
616  entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
617  entry.z = b.max.z;
618  }
619  }
620  else if (r.pos.z < b.min.z || r.pos.z > b.max.z)
621  {
622  return false;
623  }
624  }
625 
626  return tFrontMax <= tBackMin;
627 }
628 
629 ///
630 /// Intersect a ray, `r`, with a 3D box, `b, and compute the intersection
631 /// point, returned in `ip`.
632 ///
633 /// The intersection point is
634 /// - the ray's origin if the ray starts inside the box
635 /// - a point on one of the faces of the box if the ray
636 /// starts outside the box
637 /// - undefined when intersect() returns false
638 ///
639 /// @return
640 /// - true if the ray starts inside the box or if the
641 /// ray starts outside and intersects the box
642 /// - false if the ray starts outside the box and intersects it,
643 /// but the intersection is behind the ray's origin.
644 /// - false if the ray starts outside and does not intersect it
645 ///
646 
647 template <class T>
648 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
649 intersects (const Box<Vec3<T>>& b, const Line3<T>& r, Vec3<T>& ip)
651 {
652  if (b.isEmpty ())
653  {
654  //
655  // No ray intersects an empty box
656  //
657 
658  return false;
659  }
660 
661  if (b.intersects (r.pos))
662  {
663  //
664  // The ray starts inside the box
665  //
666 
667  ip = r.pos;
668  return true;
669  }
670 
671  //
672  // The ray starts outside the box. Between one and three "frontfacing"
673  // sides of the box are oriented towards the ray, and between one and
674  // three "backfacing" sides are oriented away from the ray.
675  // We intersect the ray with the planes that contain the sides of the
676  // box, and compare the distances between ray's origin and the ray-plane
677  // intersections.
678  // The ray intersects the box if the most distant frontfacing intersection
679  // is nearer than the nearest backfacing intersection. If the ray does
680  // intersect the box, then the most distant frontfacing ray-plane
681  // intersection is the ray-box intersection.
682  //
683 
684  const T TMAX = std::numeric_limits<T>::max ();
685 
686  T tFrontMax = -1;
687  T tBackMin = TMAX;
688 
689  //
690  // Minimum and maximum X sides.
691  //
692 
693  if (r.dir.x > 0)
694  {
695  if (r.pos.x > b.max.x) return false;
696 
697  T d = b.max.x - r.pos.x;
698 
699  if (r.dir.x > 1 || d < TMAX * r.dir.x)
700  {
701  T t = d / r.dir.x;
702 
703  if (tBackMin > t) tBackMin = t;
704  }
705 
706  if (r.pos.x <= b.min.x)
707  {
708  T d = b.min.x - r.pos.x;
709  T t = (r.dir.x > 1 || d < TMAX * r.dir.x) ? d / r.dir.x : TMAX;
710 
711  if (tFrontMax < t)
712  {
713  tFrontMax = t;
714 
715  ip.x = b.min.x;
716  ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
717  ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
718  }
719  }
720  }
721  else if (r.dir.x < 0)
722  {
723  if (r.pos.x < b.min.x) return false;
724 
725  T d = b.min.x - r.pos.x;
726 
727  if (r.dir.x < -1 || d > TMAX * r.dir.x)
728  {
729  T t = d / r.dir.x;
730 
731  if (tBackMin > t) tBackMin = t;
732  }
733 
734  if (r.pos.x >= b.max.x)
735  {
736  T d = b.max.x - r.pos.x;
737  T t = (r.dir.x < -1 || d > TMAX * r.dir.x) ? d / r.dir.x : TMAX;
738 
739  if (tFrontMax < t)
740  {
741  tFrontMax = t;
742 
743  ip.x = b.max.x;
744  ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
745  ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
746  }
747  }
748  }
749  else // r.dir.x == 0
750  {
751  if (r.pos.x < b.min.x || r.pos.x > b.max.x) return false;
752  }
753 
754  //
755  // Minimum and maximum Y sides.
756  //
757 
758  if (r.dir.y > 0)
759  {
760  if (r.pos.y > b.max.y) return false;
761 
762  T d = b.max.y - r.pos.y;
763 
764  if (r.dir.y > 1 || d < TMAX * r.dir.y)
765  {
766  T t = d / r.dir.y;
767 
768  if (tBackMin > t) tBackMin = t;
769  }
770 
771  if (r.pos.y <= b.min.y)
772  {
773  T d = b.min.y - r.pos.y;
774  T t = (r.dir.y > 1 || d < TMAX * r.dir.y) ? d / r.dir.y : TMAX;
775 
776  if (tFrontMax < t)
777  {
778  tFrontMax = t;
779 
780  ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
781  ip.y = b.min.y;
782  ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
783  }
784  }
785  }
786  else if (r.dir.y < 0)
787  {
788  if (r.pos.y < b.min.y) return false;
789 
790  T d = b.min.y - r.pos.y;
791 
792  if (r.dir.y < -1 || d > TMAX * r.dir.y)
793  {
794  T t = d / r.dir.y;
795 
796  if (tBackMin > t) tBackMin = t;
797  }
798 
799  if (r.pos.y >= b.max.y)
800  {
801  T d = b.max.y - r.pos.y;
802  T t = (r.dir.y < -1 || d > TMAX * r.dir.y) ? d / r.dir.y : TMAX;
803 
804  if (tFrontMax < t)
805  {
806  tFrontMax = t;
807 
808  ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
809  ip.y = b.max.y;
810  ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
811  }
812  }
813  }
814  else // r.dir.y == 0
815  {
816  if (r.pos.y < b.min.y || r.pos.y > b.max.y) return false;
817  }
818 
819  //
820  // Minimum and maximum Z sides.
821  //
822 
823  if (r.dir.z > 0)
824  {
825  if (r.pos.z > b.max.z) return false;
826 
827  T d = b.max.z - r.pos.z;
828 
829  if (r.dir.z > 1 || d < TMAX * r.dir.z)
830  {
831  T t = d / r.dir.z;
832 
833  if (tBackMin > t) tBackMin = t;
834  }
835 
836  if (r.pos.z <= b.min.z)
837  {
838  T d = b.min.z - r.pos.z;
839  T t = (r.dir.z > 1 || d < TMAX * r.dir.z) ? d / r.dir.z : TMAX;
840 
841  if (tFrontMax < t)
842  {
843  tFrontMax = t;
844 
845  ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
846  ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
847  ip.z = b.min.z;
848  }
849  }
850  }
851  else if (r.dir.z < 0)
852  {
853  if (r.pos.z < b.min.z) return false;
854 
855  T d = b.min.z - r.pos.z;
856 
857  if (r.dir.z < -1 || d > TMAX * r.dir.z)
858  {
859  T t = d / r.dir.z;
860 
861  if (tBackMin > t) tBackMin = t;
862  }
863 
864  if (r.pos.z >= b.max.z)
865  {
866  T d = b.max.z - r.pos.z;
867  T t = (r.dir.z < -1 || d > TMAX * r.dir.z) ? d / r.dir.z : TMAX;
868 
869  if (tFrontMax < t)
870  {
871  tFrontMax = t;
872 
873  ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
874  ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
875  ip.z = b.max.z;
876  }
877  }
878  }
879  else // r.dir.z == 0
880  {
881  if (r.pos.z < b.min.z || r.pos.z > b.max.z) return false;
882  }
883 
884  return tFrontMax <= tBackMin;
885 }
886 
887 ///
888 /// Return whether the the ray `ray` interects the 3D box `box`.
889 ///
890 
891 template <class T>
892 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
893 intersects (const Box<Vec3<T>>& box, const Line3<T>& ray) IMATH_NOEXCEPT
894 {
895  Vec3<T> ignored;
896  return intersects (box, ray, ignored);
897 }
898 
899 IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
900 
901 #endif // INCLUDED_IMATHBOXALGO_H
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
T z
Definition: ImathVec.h:368
GLdouble GLdouble GLint GLint const GLdouble * points
Definition: glad.h:2676
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool findEntryAndExitPoints(const Line3< T > &r, const Box< Vec3< T >> &b, Vec3< T > &entry, Vec3< T > &exit) IMATH_NOEXCEPT
Definition: ImathBoxAlgo.h:371
#define IMATH_NOEXCEPT
Definition: ImathConfig.h:78
GLenum clamp
Definition: glcorearb.h:1234
Definition: ImathVec.h:40
IMATH_HOSTDEVICE constexpr T closestPointInBox(const T &p, const Box< T > &box) IMATH_NOEXCEPT
Definition: ImathBoxAlgo.h:53
IMATH_HOSTDEVICE void extendBy(const V &point) IMATH_NOEXCEPT
Extend the box to include the given point.
Definition: ImathBox.h:234
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
**But if you need a result
Definition: thread.h:622
GLdouble GLdouble GLdouble q
Definition: glad.h:2445
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3< T > closestPointOnBox(const Vec3< T > &p, const Box< Vec3< T >> &box) IMATH_NOEXCEPT
Definition: ImathBoxAlgo.h:67
#define IMATH_HOSTDEVICE
Definition: ImathConfig.h:108
IMATH_HOSTDEVICE Box< Vec3< S > > transform(const Box< Vec3< S >> &box, const Matrix44< T > &m) IMATH_NOEXCEPT
Definition: ImathBoxAlgo.h:114
V max
The maximum value of the box.
Definition: ImathBox.h:47
T x
Definition: ImathVec.h:368
V min
The minimum value of the box.
Definition: ImathBox.h:44
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
GLdouble t
Definition: glad.h:2397
GLint j
Definition: glad.h:2733
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
if(num_boxed_items<=0)
Definition: UT_RTreeImpl.h:697
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersects(const Box< Vec3< T >> &b, const Line3< T > &r, Vec3< T > &ip) IMATH_NOEXCEPT
Definition: ImathBoxAlgo.h:649
T y
Definition: ImathVec.h:368
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE constexpr T abs(T a) IMATH_NOEXCEPT
Definition: ImathFun.h:26
Definition: ImathBox.h:37
GLboolean r
Definition: glcorearb.h:1222
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T clip(const T &p, const Box< T > &box) IMATH_NOEXCEPT
Definition: ImathBoxAlgo.h:29
IMATH_HOSTDEVICE Box< Vec3< S > > affineTransform(const Box< Vec3< S >> &box, const Matrix44< T > &m) IMATH_NOEXCEPT
Definition: ImathBoxAlgo.h:267