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