| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908 |
- //
- // SPDX-License-Identifier: BSD-3-Clause
- // Copyright Contributors to the OpenEXR Project.
- //
- //
- // Axis-aligned bounding box utility functions
- //
- #ifndef INCLUDED_IMATHBOXALGO_H
- #define INCLUDED_IMATHBOXALGO_H
- #include "ImathNamespace.h"
- #include "ImathBox.h"
- #include "ImathLineAlgo.h"
- #include "ImathMatrix.h"
- #include "ImathPlane.h"
- IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
- ///
- /// Clip the coordinates of a point, `p`, against a `Box<T>`, `box`.
- /// Return the closest point to `p` that is inside the box.
- ///
- template <class T>
- IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
- clip (const T& p, const Box<T>& box) IMATH_NOEXCEPT
- {
- T q;
- for (int i = 0; i < int (box.min.dimensions()); i++)
- {
- if (p[i] < box.min[i])
- q[i] = box.min[i];
- else if (p[i] > box.max[i])
- q[i] = box.max[i];
- else
- q[i] = p[i];
- }
- return q;
- }
- ///
- /// Return the point in or on the `Box<T>`, `box`, that is closesest to
- /// the point, `p`.
- ///
- template <class T>
- IMATH_HOSTDEVICE constexpr inline T
- closestPointInBox (const T& p, const Box<T>& box) IMATH_NOEXCEPT
- {
- return clip (p, box);
- }
- ///
- /// Return the point on the surface of the `Box<T>`, `box`, that is
- /// closest to point `p`.
- ///
- /// If the box is empty, return `p`.
- ///
- template <class T>
- IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3<T>
- closestPointOnBox (const Vec3<T>& p, const Box<Vec3<T>>& box) IMATH_NOEXCEPT
- {
- if (box.isEmpty())
- return p;
- Vec3<T> q = closestPointInBox (p, box);
- if (q == p)
- {
- Vec3<T> d1 = p - box.min;
- Vec3<T> d2 = box.max - p;
- Vec3<T> d ((d1.x < d2.x) ? d1.x : d2.x,
- (d1.y < d2.y) ? d1.y : d2.y,
- (d1.z < d2.z) ? d1.z : d2.z);
- if (d.x < d.y && d.x < d.z)
- {
- q.x = (d1.x < d2.x) ? box.min.x : box.max.x;
- }
- else if (d.y < d.z)
- {
- q.y = (d1.y < d2.y) ? box.min.y : box.max.y;
- }
- else
- {
- q.z = (d1.z < d2.z) ? box.min.z : box.max.z;
- }
- }
- return q;
- }
- ///
- /// Transform a 3D box by a matrix, and compute a new box that
- /// tightly encloses the transformed box. Return the transformed box.
- ///
- /// If `m` is an affine transform, then we use James Arvo's fast
- /// method as described in "Graphics Gems", Academic Press, 1990,
- /// pp. 548-550.
- ///
- /// A transformed empty box is still empty, and a transformed infinite box
- /// is still infinite.
- ///
- template <class S, class T>
- IMATH_HOSTDEVICE Box<Vec3<S>>
- transform (const Box<Vec3<S>>& box, const Matrix44<T>& m) IMATH_NOEXCEPT
- {
- if (box.isEmpty() || box.isInfinite())
- return box;
- //
- // If the last column of m is (0 0 0 1) then m is an affine
- // transform, and we use the fast Graphics Gems trick.
- //
- if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1)
- {
- Box<Vec3<S>> newBox;
- for (int i = 0; i < 3; i++)
- {
- newBox.min[i] = newBox.max[i] = (S) m[3][i];
- for (int j = 0; j < 3; j++)
- {
- S a, b;
- a = (S) m[j][i] * box.min[j];
- b = (S) m[j][i] * box.max[j];
- if (a < b)
- {
- newBox.min[i] += a;
- newBox.max[i] += b;
- }
- else
- {
- newBox.min[i] += b;
- newBox.max[i] += a;
- }
- }
- }
- return newBox;
- }
- //
- // M is a projection matrix. Do things the naive way:
- // Transform the eight corners of the box, and find an
- // axis-parallel box that encloses the transformed corners.
- //
- Vec3<S> points[8];
- points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0];
- points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0];
- points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1];
- points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1];
- points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2];
- points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2];
- Box<Vec3<S>> newBox;
- for (int i = 0; i < 8; i++)
- newBox.extendBy (points[i] * m);
- return newBox;
- }
- ///
- /// Transform a 3D box by a matrix, and compute a new box that
- /// tightly encloses the transformed box. The transformed box is
- /// returned in the `result` argument.
- ///
- /// If m is an affine transform, then we use James Arvo's fast
- /// method as described in "Graphics Gems", Academic Press, 1990,
- /// pp. 548-550.
- ///
- /// A transformed empty box is still empty, and a transformed infinite
- /// box is still infinite
- ///
- template <class S, class T>
- IMATH_HOSTDEVICE void
- transform (const Box<Vec3<S>>& box, const Matrix44<T>& m, Box<Vec3<S>>& result) IMATH_NOEXCEPT
- {
- if (box.isEmpty() || box.isInfinite())
- {
- return;
- }
- //
- // If the last column of m is (0 0 0 1) then m is an affine
- // transform, and we use the fast Graphics Gems trick.
- //
- if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1)
- {
- for (int i = 0; i < 3; i++)
- {
- result.min[i] = result.max[i] = (S) m[3][i];
- for (int j = 0; j < 3; j++)
- {
- S a, b;
- a = (S) m[j][i] * box.min[j];
- b = (S) m[j][i] * box.max[j];
- if (a < b)
- {
- result.min[i] += a;
- result.max[i] += b;
- }
- else
- {
- result.min[i] += b;
- result.max[i] += a;
- }
- }
- }
- return;
- }
- //
- // M is a projection matrix. Do things the naive way:
- // Transform the eight corners of the box, and find an
- // axis-parallel box that encloses the transformed corners.
- //
- Vec3<S> points[8];
- points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0];
- points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0];
- points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1];
- points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1];
- points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2];
- points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2];
- for (int i = 0; i < 8; i++)
- result.extendBy (points[i] * m);
- }
- ///
- /// Transform a 3D box by a matrix whose rightmost column `(0 0 0 1)`,
- /// and compute a new box that tightly encloses the transformed
- /// box. Return the transformed box.
- ///
- /// As in the transform() function, use James Arvo's fast method if
- /// possible.
- ///
- /// A transformed empty or infinite box is still empty or infinite.
- ///
- template <class S, class T>
- IMATH_HOSTDEVICE Box<Vec3<S>>
- affineTransform (const Box<Vec3<S>>& box, const Matrix44<T>& m) IMATH_NOEXCEPT
- {
- if (box.isEmpty() || box.isInfinite())
- return box;
- Box<Vec3<S>> newBox;
- for (int i = 0; i < 3; i++)
- {
- newBox.min[i] = newBox.max[i] = (S) m[3][i];
- for (int j = 0; j < 3; j++)
- {
- S a, b;
- a = (S) m[j][i] * box.min[j];
- b = (S) m[j][i] * box.max[j];
- if (a < b)
- {
- newBox.min[i] += a;
- newBox.max[i] += b;
- }
- else
- {
- newBox.min[i] += b;
- newBox.max[i] += a;
- }
- }
- }
- return newBox;
- }
- ///
- /// Transform a 3D box by a matrix whose rightmost column is
- /// `(0 0 0 1)`, and compute a new box that tightly encloses
- /// the transformed box. Return the transformed box in the `result`
- /// argument.
- ///
- /// As in the transform() function, use James Arvo's fast method if
- /// possible.
- ///
- /// A transformed empty or infinite box is still empty or infinite.
- ///
- template <class S, class T>
- IMATH_HOSTDEVICE void
- affineTransform (const Box<Vec3<S>>& box, const Matrix44<T>& m, Box<Vec3<S>>& result) IMATH_NOEXCEPT
- {
- if (box.isEmpty())
- {
- result.makeEmpty();
- return;
- }
- if (box.isInfinite())
- {
- result.makeInfinite();
- return;
- }
- for (int i = 0; i < 3; i++)
- {
- result.min[i] = result.max[i] = (S) m[3][i];
- for (int j = 0; j < 3; j++)
- {
- S a, b;
- a = (S) m[j][i] * box.min[j];
- b = (S) m[j][i] * box.max[j];
- if (a < b)
- {
- result.min[i] += a;
- result.max[i] += b;
- }
- else
- {
- result.min[i] += b;
- result.max[i] += a;
- }
- }
- }
- }
- ///
- /// Compute the points where a ray, `r`, enters and exits a 3D box, `b`:
- ///
- /// Return true if the ray starts inside the box or if the ray starts
- /// outside and intersects the box, or return false otherwise (that
- /// is, if the ray does not intersect the box).
- ///
- /// The entry and exit points are the points on two of the faces of
- /// the box when the function returns true (the entry end exit points
- /// may be on either side of the ray's origin), or undefined if the
- /// the function returns false.
- ///
- template <class T>
- IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
- findEntryAndExitPoints (const Line3<T>& r, const Box<Vec3<T>>& b, Vec3<T>& entry, Vec3<T>& exit) IMATH_NOEXCEPT
- {
- if (b.isEmpty())
- {
- //
- // No ray intersects an empty box
- //
- return false;
- }
- //
- // The following description assumes that the ray's origin is outside
- // the box, but the code below works even if the origin is inside the
- // box:
- //
- // Between one and three "frontfacing" sides of the box are oriented
- // towards the ray's origin, and between one and three "backfacing"
- // sides are oriented away from the ray's origin.
- // We intersect the ray with the planes that contain the sides of the
- // box, and compare the distances between the ray's origin and the
- // ray-plane intersections. The ray intersects the box if the most
- // distant frontfacing intersection is nearer than the nearest
- // backfacing intersection. If the ray does intersect the box, then
- // the most distant frontfacing ray-plane intersection is the entry
- // point and the nearest backfacing ray-plane intersection is the
- // exit point.
- //
- const T TMAX = std::numeric_limits<T>::max();
- T tFrontMax = -TMAX;
- T tBackMin = TMAX;
- //
- // Minimum and maximum X sides.
- //
- if (r.dir.x >= 0)
- {
- T d1 = b.max.x - r.pos.x;
- T d2 = b.min.x - r.pos.x;
- if (r.dir.x > 1 || (abs (d1) < TMAX * r.dir.x && abs (d2) < TMAX * r.dir.x))
- {
- T t1 = d1 / r.dir.x;
- T t2 = d2 / r.dir.x;
- if (tBackMin > t1)
- {
- tBackMin = t1;
- exit.x = b.max.x;
- exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
- exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
- }
- if (tFrontMax < t2)
- {
- tFrontMax = t2;
- entry.x = b.min.x;
- entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
- entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
- }
- }
- else if (r.pos.x < b.min.x || r.pos.x > b.max.x)
- {
- return false;
- }
- }
- else // r.dir.x < 0
- {
- T d1 = b.min.x - r.pos.x;
- T d2 = b.max.x - r.pos.x;
- if (r.dir.x < -1 || (abs (d1) < -TMAX * r.dir.x && abs (d2) < -TMAX * r.dir.x))
- {
- T t1 = d1 / r.dir.x;
- T t2 = d2 / r.dir.x;
- if (tBackMin > t1)
- {
- tBackMin = t1;
- exit.x = b.min.x;
- exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
- exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
- }
- if (tFrontMax < t2)
- {
- tFrontMax = t2;
- entry.x = b.max.x;
- entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
- entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
- }
- }
- else if (r.pos.x < b.min.x || r.pos.x > b.max.x)
- {
- return false;
- }
- }
- //
- // Minimum and maximum Y sides.
- //
- if (r.dir.y >= 0)
- {
- T d1 = b.max.y - r.pos.y;
- T d2 = b.min.y - r.pos.y;
- if (r.dir.y > 1 || (abs (d1) < TMAX * r.dir.y && abs (d2) < TMAX * r.dir.y))
- {
- T t1 = d1 / r.dir.y;
- T t2 = d2 / r.dir.y;
- if (tBackMin > t1)
- {
- tBackMin = t1;
- exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
- exit.y = b.max.y;
- exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
- }
- if (tFrontMax < t2)
- {
- tFrontMax = t2;
- entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
- entry.y = b.min.y;
- entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
- }
- }
- else if (r.pos.y < b.min.y || r.pos.y > b.max.y)
- {
- return false;
- }
- }
- else // r.dir.y < 0
- {
- T d1 = b.min.y - r.pos.y;
- T d2 = b.max.y - r.pos.y;
- if (r.dir.y < -1 || (abs (d1) < -TMAX * r.dir.y && abs (d2) < -TMAX * r.dir.y))
- {
- T t1 = d1 / r.dir.y;
- T t2 = d2 / r.dir.y;
- if (tBackMin > t1)
- {
- tBackMin = t1;
- exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
- exit.y = b.min.y;
- exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);
- }
- if (tFrontMax < t2)
- {
- tFrontMax = t2;
- entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
- entry.y = b.max.y;
- entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);
- }
- }
- else if (r.pos.y < b.min.y || r.pos.y > b.max.y)
- {
- return false;
- }
- }
- //
- // Minimum and maximum Z sides.
- //
- if (r.dir.z >= 0)
- {
- T d1 = b.max.z - r.pos.z;
- T d2 = b.min.z - r.pos.z;
- if (r.dir.z > 1 || (abs (d1) < TMAX * r.dir.z && abs (d2) < TMAX * r.dir.z))
- {
- T t1 = d1 / r.dir.z;
- T t2 = d2 / r.dir.z;
- if (tBackMin > t1)
- {
- tBackMin = t1;
- exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
- exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
- exit.z = b.max.z;
- }
- if (tFrontMax < t2)
- {
- tFrontMax = t2;
- entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
- entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
- entry.z = b.min.z;
- }
- }
- else if (r.pos.z < b.min.z || r.pos.z > b.max.z)
- {
- return false;
- }
- }
- else // r.dir.z < 0
- {
- T d1 = b.min.z - r.pos.z;
- T d2 = b.max.z - r.pos.z;
- if (r.dir.z < -1 || (abs (d1) < -TMAX * r.dir.z && abs (d2) < -TMAX * r.dir.z))
- {
- T t1 = d1 / r.dir.z;
- T t2 = d2 / r.dir.z;
- if (tBackMin > t1)
- {
- tBackMin = t1;
- exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);
- exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);
- exit.z = b.min.z;
- }
- if (tFrontMax < t2)
- {
- tFrontMax = t2;
- entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);
- entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);
- entry.z = b.max.z;
- }
- }
- else if (r.pos.z < b.min.z || r.pos.z > b.max.z)
- {
- return false;
- }
- }
- return tFrontMax <= tBackMin;
- }
- ///
- /// Intersect a ray, `r`, with a 3D box, `b, and compute the intersection
- /// point, returned in `ip`.
- ///
- /// The intersection point is
- /// - the ray's origin if the ray starts inside the box
- /// - a point on one of the faces of the box if the ray
- /// starts outside the box
- /// - undefined when intersect() returns false
- ///
- /// @return
- /// - true if the ray starts inside the box or if the
- /// ray starts outside and intersects the box
- /// - false if the ray starts outside the box and intersects it,
- /// but the intersection is behind the ray's origin.
- /// - false if the ray starts outside and does not intersect it
- ///
- template <class T>
- IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
- intersects (const Box<Vec3<T>>& b, const Line3<T>& r, Vec3<T>& ip) IMATH_NOEXCEPT
- {
- if (b.isEmpty())
- {
- //
- // No ray intersects an empty box
- //
- return false;
- }
- if (b.intersects (r.pos))
- {
- //
- // The ray starts inside the box
- //
- ip = r.pos;
- return true;
- }
- //
- // The ray starts outside the box. Between one and three "frontfacing"
- // sides of the box are oriented towards the ray, and between one and
- // three "backfacing" sides are oriented away from the ray.
- // We intersect the ray with the planes that contain the sides of the
- // box, and compare the distances between ray's origin and the ray-plane
- // intersections.
- // The ray intersects the box if the most distant frontfacing intersection
- // is nearer than the nearest backfacing intersection. If the ray does
- // intersect the box, then the most distant frontfacing ray-plane
- // intersection is the ray-box intersection.
- //
- const T TMAX = std::numeric_limits<T>::max();
- T tFrontMax = -1;
- T tBackMin = TMAX;
- //
- // Minimum and maximum X sides.
- //
- if (r.dir.x > 0)
- {
- if (r.pos.x > b.max.x)
- return false;
- T d = b.max.x - r.pos.x;
- if (r.dir.x > 1 || d < TMAX * r.dir.x)
- {
- T t = d / r.dir.x;
- if (tBackMin > t)
- tBackMin = t;
- }
- if (r.pos.x <= b.min.x)
- {
- T d = b.min.x - r.pos.x;
- T t = (r.dir.x > 1 || d < TMAX * r.dir.x) ? d / r.dir.x : TMAX;
- if (tFrontMax < t)
- {
- tFrontMax = t;
- ip.x = b.min.x;
- ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
- ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
- }
- }
- }
- else if (r.dir.x < 0)
- {
- if (r.pos.x < b.min.x)
- return false;
- T d = b.min.x - r.pos.x;
- if (r.dir.x < -1 || d > TMAX * r.dir.x)
- {
- T t = d / r.dir.x;
- if (tBackMin > t)
- tBackMin = t;
- }
- if (r.pos.x >= b.max.x)
- {
- T d = b.max.x - r.pos.x;
- T t = (r.dir.x < -1 || d > TMAX * r.dir.x) ? d / r.dir.x : TMAX;
- if (tFrontMax < t)
- {
- tFrontMax = t;
- ip.x = b.max.x;
- ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
- ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
- }
- }
- }
- else // r.dir.x == 0
- {
- if (r.pos.x < b.min.x || r.pos.x > b.max.x)
- return false;
- }
- //
- // Minimum and maximum Y sides.
- //
- if (r.dir.y > 0)
- {
- if (r.pos.y > b.max.y)
- return false;
- T d = b.max.y - r.pos.y;
- if (r.dir.y > 1 || d < TMAX * r.dir.y)
- {
- T t = d / r.dir.y;
- if (tBackMin > t)
- tBackMin = t;
- }
- if (r.pos.y <= b.min.y)
- {
- T d = b.min.y - r.pos.y;
- T t = (r.dir.y > 1 || d < TMAX * r.dir.y) ? d / r.dir.y : TMAX;
- if (tFrontMax < t)
- {
- tFrontMax = t;
- ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
- ip.y = b.min.y;
- ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
- }
- }
- }
- else if (r.dir.y < 0)
- {
- if (r.pos.y < b.min.y)
- return false;
- T d = b.min.y - r.pos.y;
- if (r.dir.y < -1 || d > TMAX * r.dir.y)
- {
- T t = d / r.dir.y;
- if (tBackMin > t)
- tBackMin = t;
- }
- if (r.pos.y >= b.max.y)
- {
- T d = b.max.y - r.pos.y;
- T t = (r.dir.y < -1 || d > TMAX * r.dir.y) ? d / r.dir.y : TMAX;
- if (tFrontMax < t)
- {
- tFrontMax = t;
- ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
- ip.y = b.max.y;
- ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
- }
- }
- }
- else // r.dir.y == 0
- {
- if (r.pos.y < b.min.y || r.pos.y > b.max.y)
- return false;
- }
- //
- // Minimum and maximum Z sides.
- //
- if (r.dir.z > 0)
- {
- if (r.pos.z > b.max.z)
- return false;
- T d = b.max.z - r.pos.z;
- if (r.dir.z > 1 || d < TMAX * r.dir.z)
- {
- T t = d / r.dir.z;
- if (tBackMin > t)
- tBackMin = t;
- }
- if (r.pos.z <= b.min.z)
- {
- T d = b.min.z - r.pos.z;
- T t = (r.dir.z > 1 || d < TMAX * r.dir.z) ? d / r.dir.z : TMAX;
- if (tFrontMax < t)
- {
- tFrontMax = t;
- ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
- ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
- ip.z = b.min.z;
- }
- }
- }
- else if (r.dir.z < 0)
- {
- if (r.pos.z < b.min.z)
- return false;
- T d = b.min.z - r.pos.z;
- if (r.dir.z < -1 || d > TMAX * r.dir.z)
- {
- T t = d / r.dir.z;
- if (tBackMin > t)
- tBackMin = t;
- }
- if (r.pos.z >= b.max.z)
- {
- T d = b.max.z - r.pos.z;
- T t = (r.dir.z < -1 || d > TMAX * r.dir.z) ? d / r.dir.z : TMAX;
- if (tFrontMax < t)
- {
- tFrontMax = t;
- ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
- ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
- ip.z = b.max.z;
- }
- }
- }
- else // r.dir.z == 0
- {
- if (r.pos.z < b.min.z || r.pos.z > b.max.z)
- return false;
- }
- return tFrontMax <= tBackMin;
- }
- ///
- /// Return whether the the ray `ray` interects the 3D box `box`.
- ///
- template <class T>
- IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
- intersects (const Box<Vec3<T>>& box, const Line3<T>& ray) IMATH_NOEXCEPT
- {
- Vec3<T> ignored;
- return intersects (box, ray, ignored);
- }
- IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
- #endif // INCLUDED_IMATHBOXALGO_H
|