Path: blob/master/3rdparty/openexr/Imath/ImathBoxAlgo.h
16337 views
///////////////////////////////////////////////////////////////////////////1//2// Copyright (c) 2002-2010, Industrial Light & Magic, a division of Lucas3// Digital Ltd. LLC4//5// All rights reserved.6//7// Redistribution and use in source and binary forms, with or without8// modification, are permitted provided that the following conditions are9// met:10// * Redistributions of source code must retain the above copyright11// notice, this list of conditions and the following disclaimer.12// * Redistributions in binary form must reproduce the above13// copyright notice, this list of conditions and the following disclaimer14// in the documentation and/or other materials provided with the15// distribution.16// * Neither the name of Industrial Light & Magic nor the names of17// its contributors may be used to endorse or promote products derived18// from this software without specific prior written permission.19//20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.31//32///////////////////////////////////////////////////////////////////////////33343536#ifndef INCLUDED_IMATHBOXALGO_H37#define INCLUDED_IMATHBOXALGO_H383940//---------------------------------------------------------------------------41//42// This file contains algorithms applied to or in conjunction43// with bounding boxes (Imath::Box). These algorithms require44// more headers to compile. The assumption made is that these45// functions are called much less often than the basic box46// functions or these functions require more support classes.47//48// Contains:49//50// T clip<T>(const T& in, const Box<T>& box)51//52// Vec3<T> closestPointOnBox(const Vec3<T>&, const Box<Vec3<T>>& )53//54// Vec3<T> closestPointInBox(const Vec3<T>&, const Box<Vec3<T>>& )55//56// Box< Vec3<S> > transform(const Box<Vec3<S>>&, const Matrix44<T>&)57// Box< Vec3<S> > affineTransform(const Box<Vec3<S>>&, const Matrix44<T>&)58//59// void transform(const Box<Vec3<S>>&, const Matrix44<T>&, Box<V3ec3<S>>&)60// void affineTransform(const Box<Vec3<S>>&,61// const Matrix44<T>&,62// Box<V3ec3<S>>&)63//64// bool findEntryAndExitPoints(const Line<T> &line,65// const Box< Vec3<T> > &box,66// Vec3<T> &enterPoint,67// Vec3<T> &exitPoint)68//69// bool intersects(const Box<Vec3<T>> &box,70// const Line3<T> &ray,71// Vec3<T> intersectionPoint)72//73// bool intersects(const Box<Vec3<T>> &box, const Line3<T> &ray)74//75//---------------------------------------------------------------------------7677#include "ImathBox.h"78#include "ImathMatrix.h"79#include "ImathLineAlgo.h"80#include "ImathPlane.h"8182namespace Imath {838485template <class T>86inline T87clip (const T &p, const Box<T> &box)88{89//90// Clip the coordinates of a point, p, against a box.91// The result, q, is the closest point to p that is inside the box.92//9394T q;9596for (int i = 0; i < int (box.min.dimensions()); i++)97{98if (p[i] < box.min[i])99q[i] = box.min[i];100else if (p[i] > box.max[i])101q[i] = box.max[i];102else103q[i] = p[i];104}105106return q;107}108109110template <class T>111inline T112closestPointInBox (const T &p, const Box<T> &box)113{114return clip (p, box);115}116117118template <class T>119Vec3<T>120closestPointOnBox (const Vec3<T> &p, const Box< Vec3<T> > &box)121{122//123// Find the point, q, on the surface of124// the box, that is closest to point p.125//126// If the box is empty, return p.127//128129if (box.isEmpty())130return p;131132Vec3<T> q = closestPointInBox (p, box);133134if (q == p)135{136Vec3<T> d1 = p - box.min;137Vec3<T> d2 = box.max - p;138139Vec3<T> d ((d1.x < d2.x)? d1.x: d2.x,140(d1.y < d2.y)? d1.y: d2.y,141(d1.z < d2.z)? d1.z: d2.z);142143if (d.x < d.y && d.x < d.z)144{145q.x = (d1.x < d2.x)? box.min.x: box.max.x;146}147else if (d.y < d.z)148{149q.y = (d1.y < d2.y)? box.min.y: box.max.y;150}151else152{153q.z = (d1.z < d2.z)? box.min.z: box.max.z;154}155}156157return q;158}159160161template <class S, class T>162Box< Vec3<S> >163transform (const Box< Vec3<S> > &box, const Matrix44<T> &m)164{165//166// Transform a 3D box by a matrix, and compute a new box that167// tightly encloses the transformed box.168//169// If m is an affine transform, then we use James Arvo's fast170// method as described in "Graphics Gems", Academic Press, 1990,171// pp. 548-550.172//173174//175// A transformed empty box is still empty, and a transformed infinite box176// is still infinite177//178179if (box.isEmpty() || box.isInfinite())180return box;181182//183// If the last column of m is (0 0 0 1) then m is an affine184// transform, and we use the fast Graphics Gems trick.185//186187if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1)188{189Box< Vec3<S> > newBox;190191for (int i = 0; i < 3; i++)192{193newBox.min[i] = newBox.max[i] = (S) m[3][i];194195for (int j = 0; j < 3; j++)196{197S a, b;198199a = (S) m[j][i] * box.min[j];200b = (S) m[j][i] * box.max[j];201202if (a < b)203{204newBox.min[i] += a;205newBox.max[i] += b;206}207else208{209newBox.min[i] += b;210newBox.max[i] += a;211}212}213}214215return newBox;216}217218//219// M is a projection matrix. Do things the naive way:220// Transform the eight corners of the box, and find an221// axis-parallel box that encloses the transformed corners.222//223224Vec3<S> points[8];225226points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0];227points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0];228229points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1];230points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1];231232points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2];233points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2];234235Box< Vec3<S> > newBox;236237for (int i = 0; i < 8; i++)238newBox.extendBy (points[i] * m);239240return newBox;241}242243template <class S, class T>244void245transform (const Box< Vec3<S> > &box,246const Matrix44<T> &m,247Box< Vec3<S> > &result)248{249//250// Transform a 3D box by a matrix, and compute a new box that251// tightly encloses the transformed box.252//253// If m is an affine transform, then we use James Arvo's fast254// method as described in "Graphics Gems", Academic Press, 1990,255// pp. 548-550.256//257258//259// A transformed empty box is still empty, and a transformed infinite260// box is still infinite261//262263if (box.isEmpty() || box.isInfinite())264{265return;266}267268//269// If the last column of m is (0 0 0 1) then m is an affine270// transform, and we use the fast Graphics Gems trick.271//272273if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1)274{275for (int i = 0; i < 3; i++)276{277result.min[i] = result.max[i] = (S) m[3][i];278279for (int j = 0; j < 3; j++)280{281S a, b;282283a = (S) m[j][i] * box.min[j];284b = (S) m[j][i] * box.max[j];285286if (a < b)287{288result.min[i] += a;289result.max[i] += b;290}291else292{293result.min[i] += b;294result.max[i] += a;295}296}297}298299return;300}301302//303// M is a projection matrix. Do things the naive way:304// Transform the eight corners of the box, and find an305// axis-parallel box that encloses the transformed corners.306//307308Vec3<S> points[8];309310points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0];311points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0];312313points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1];314points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1];315316points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2];317points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2];318319for (int i = 0; i < 8; i++)320result.extendBy (points[i] * m);321}322323324template <class S, class T>325Box< Vec3<S> >326affineTransform (const Box< Vec3<S> > &box, const Matrix44<T> &m)327{328//329// Transform a 3D box by a matrix whose rightmost column330// is (0 0 0 1), and compute a new box that tightly encloses331// the transformed box.332//333// As in the transform() function, above, we use James Arvo's334// fast method.335//336337if (box.isEmpty() || box.isInfinite())338{339//340// A transformed empty or infinite box is still empty or infinite341//342343return box;344}345346Box< Vec3<S> > newBox;347348for (int i = 0; i < 3; i++)349{350newBox.min[i] = newBox.max[i] = (S) m[3][i];351352for (int j = 0; j < 3; j++)353{354S a, b;355356a = (S) m[j][i] * box.min[j];357b = (S) m[j][i] * box.max[j];358359if (a < b)360{361newBox.min[i] += a;362newBox.max[i] += b;363}364else365{366newBox.min[i] += b;367newBox.max[i] += a;368}369}370}371372return newBox;373}374375template <class S, class T>376void377affineTransform (const Box< Vec3<S> > &box,378const Matrix44<T> &m,379Box<Vec3<S> > &result)380{381//382// Transform a 3D box by a matrix whose rightmost column383// is (0 0 0 1), and compute a new box that tightly encloses384// the transformed box.385//386// As in the transform() function, above, we use James Arvo's387// fast method.388//389390if (box.isEmpty())391{392//393// A transformed empty box is still empty394//395result.makeEmpty();396return;397}398399if (box.isInfinite())400{401//402// A transformed infinite box is still infinite403//404result.makeInfinite();405return;406}407408for (int i = 0; i < 3; i++)409{410result.min[i] = result.max[i] = (S) m[3][i];411412for (int j = 0; j < 3; j++)413{414S a, b;415416a = (S) m[j][i] * box.min[j];417b = (S) m[j][i] * box.max[j];418419if (a < b)420{421result.min[i] += a;422result.max[i] += b;423}424else425{426result.min[i] += b;427result.max[i] += a;428}429}430}431}432433434template <class T>435bool436findEntryAndExitPoints (const Line3<T> &r,437const Box<Vec3<T> > &b,438Vec3<T> &entry,439Vec3<T> &exit)440{441//442// Compute the points where a ray, r, enters and exits a box, b:443//444// findEntryAndExitPoints() returns445//446// - true if the ray starts inside the box or if the447// ray starts outside and intersects the box448//449// - false otherwise (that is, if the ray does not450// intersect the box)451//452// The entry and exit points are453//454// - points on two of the faces of the box when455// findEntryAndExitPoints() returns true456// (The entry end exit points may be on either457// side of the ray's origin)458//459// - undefined when findEntryAndExitPoints()460// returns false461//462463if (b.isEmpty())464{465//466// No ray intersects an empty box467//468469return false;470}471472//473// The following description assumes that the ray's origin is outside474// the box, but the code below works even if the origin is inside the475// box:476//477// Between one and three "frontfacing" sides of the box are oriented478// towards the ray's origin, and between one and three "backfacing"479// sides are oriented away from the ray's origin.480// We intersect the ray with the planes that contain the sides of the481// box, and compare the distances between the ray's origin and the482// ray-plane intersections. The ray intersects the box if the most483// distant frontfacing intersection is nearer than the nearest484// backfacing intersection. If the ray does intersect the box, then485// the most distant frontfacing ray-plane intersection is the entry486// point and the nearest backfacing ray-plane intersection is the487// exit point.488//489490const T TMAX = limits<T>::max();491492T tFrontMax = -TMAX;493T tBackMin = TMAX;494495//496// Minimum and maximum X sides.497//498499if (r.dir.x >= 0)500{501T d1 = b.max.x - r.pos.x;502T d2 = b.min.x - r.pos.x;503504if (r.dir.x > 1 ||505(abs (d1) < TMAX * r.dir.x &&506abs (d2) < TMAX * r.dir.x))507{508T t1 = d1 / r.dir.x;509T t2 = d2 / r.dir.x;510511if (tBackMin > t1)512{513tBackMin = t1;514515exit.x = b.max.x;516exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);517exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);518}519520if (tFrontMax < t2)521{522tFrontMax = t2;523524entry.x = b.min.x;525entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);526entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);527}528}529else if (r.pos.x < b.min.x || r.pos.x > b.max.x)530{531return false;532}533}534else // r.dir.x < 0535{536T d1 = b.min.x - r.pos.x;537T d2 = b.max.x - r.pos.x;538539if (r.dir.x < -1 ||540(abs (d1) < -TMAX * r.dir.x &&541abs (d2) < -TMAX * r.dir.x))542{543T t1 = d1 / r.dir.x;544T t2 = d2 / r.dir.x;545546if (tBackMin > t1)547{548tBackMin = t1;549550exit.x = b.min.x;551exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);552exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);553}554555if (tFrontMax < t2)556{557tFrontMax = t2;558559entry.x = b.max.x;560entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);561entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);562}563}564else if (r.pos.x < b.min.x || r.pos.x > b.max.x)565{566return false;567}568}569570//571// Minimum and maximum Y sides.572//573574if (r.dir.y >= 0)575{576T d1 = b.max.y - r.pos.y;577T d2 = b.min.y - r.pos.y;578579if (r.dir.y > 1 ||580(abs (d1) < TMAX * r.dir.y &&581abs (d2) < TMAX * r.dir.y))582{583T t1 = d1 / r.dir.y;584T t2 = d2 / r.dir.y;585586if (tBackMin > t1)587{588tBackMin = t1;589590exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);591exit.y = b.max.y;592exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);593}594595if (tFrontMax < t2)596{597tFrontMax = t2;598599entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);600entry.y = b.min.y;601entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);602}603}604else if (r.pos.y < b.min.y || r.pos.y > b.max.y)605{606return false;607}608}609else // r.dir.y < 0610{611T d1 = b.min.y - r.pos.y;612T d2 = b.max.y - r.pos.y;613614if (r.dir.y < -1 ||615(abs (d1) < -TMAX * r.dir.y &&616abs (d2) < -TMAX * r.dir.y))617{618T t1 = d1 / r.dir.y;619T t2 = d2 / r.dir.y;620621if (tBackMin > t1)622{623tBackMin = t1;624625exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);626exit.y = b.min.y;627exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z);628}629630if (tFrontMax < t2)631{632tFrontMax = t2;633634entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);635entry.y = b.max.y;636entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z);637}638}639else if (r.pos.y < b.min.y || r.pos.y > b.max.y)640{641return false;642}643}644645//646// Minimum and maximum Z sides.647//648649if (r.dir.z >= 0)650{651T d1 = b.max.z - r.pos.z;652T d2 = b.min.z - r.pos.z;653654if (r.dir.z > 1 ||655(abs (d1) < TMAX * r.dir.z &&656abs (d2) < TMAX * r.dir.z))657{658T t1 = d1 / r.dir.z;659T t2 = d2 / r.dir.z;660661if (tBackMin > t1)662{663tBackMin = t1;664665exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);666exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);667exit.z = b.max.z;668}669670if (tFrontMax < t2)671{672tFrontMax = t2;673674entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);675entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);676entry.z = b.min.z;677}678}679else if (r.pos.z < b.min.z || r.pos.z > b.max.z)680{681return false;682}683}684else // r.dir.z < 0685{686T d1 = b.min.z - r.pos.z;687T d2 = b.max.z - r.pos.z;688689if (r.dir.z < -1 ||690(abs (d1) < -TMAX * r.dir.z &&691abs (d2) < -TMAX * r.dir.z))692{693T t1 = d1 / r.dir.z;694T t2 = d2 / r.dir.z;695696if (tBackMin > t1)697{698tBackMin = t1;699700exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x);701exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y);702exit.z = b.min.z;703}704705if (tFrontMax < t2)706{707tFrontMax = t2;708709entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x);710entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y);711entry.z = b.max.z;712}713}714else if (r.pos.z < b.min.z || r.pos.z > b.max.z)715{716return false;717}718}719720return tFrontMax <= tBackMin;721}722723724template<class T>725bool726intersects (const Box< Vec3<T> > &b, const Line3<T> &r, Vec3<T> &ip)727{728//729// Intersect a ray, r, with a box, b, and compute the intersection730// point, ip:731//732// intersect() returns733//734// - true if the ray starts inside the box or if the735// ray starts outside and intersects the box736//737// - false if the ray starts outside the box and intersects it,738// but the intersection is behind the ray's origin.739//740// - false if the ray starts outside and does not intersect it741//742// The intersection point is743//744// - the ray's origin if the ray starts inside the box745//746// - a point on one of the faces of the box if the ray747// starts outside the box748//749// - undefined when intersect() returns false750//751752if (b.isEmpty())753{754//755// No ray intersects an empty box756//757758return false;759}760761if (b.intersects (r.pos))762{763//764// The ray starts inside the box765//766767ip = r.pos;768return true;769}770771//772// The ray starts outside the box. Between one and three "frontfacing"773// sides of the box are oriented towards the ray, and between one and774// three "backfacing" sides are oriented away from the ray.775// We intersect the ray with the planes that contain the sides of the776// box, and compare the distances between ray's origin and the ray-plane777// intersections.778// The ray intersects the box if the most distant frontfacing intersection779// is nearer than the nearest backfacing intersection. If the ray does780// intersect the box, then the most distant frontfacing ray-plane781// intersection is the ray-box intersection.782//783784const T TMAX = limits<T>::max();785786T tFrontMax = -1;787T tBackMin = TMAX;788789//790// Minimum and maximum X sides.791//792793if (r.dir.x > 0)794{795if (r.pos.x > b.max.x)796return false;797798T d = b.max.x - r.pos.x;799800if (r.dir.x > 1 || d < TMAX * r.dir.x)801{802T t = d / r.dir.x;803804if (tBackMin > t)805tBackMin = t;806}807808if (r.pos.x <= b.min.x)809{810T d = b.min.x - r.pos.x;811T t = (r.dir.x > 1 || d < TMAX * r.dir.x)? d / r.dir.x: TMAX;812813if (tFrontMax < t)814{815tFrontMax = t;816817ip.x = b.min.x;818ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);819ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);820}821}822}823else if (r.dir.x < 0)824{825if (r.pos.x < b.min.x)826return false;827828T d = b.min.x - r.pos.x;829830if (r.dir.x < -1 || d > TMAX * r.dir.x)831{832T t = d / r.dir.x;833834if (tBackMin > t)835tBackMin = t;836}837838if (r.pos.x >= b.max.x)839{840T d = b.max.x - r.pos.x;841T t = (r.dir.x < -1 || d > TMAX * r.dir.x)? d / r.dir.x: TMAX;842843if (tFrontMax < t)844{845tFrontMax = t;846847ip.x = b.max.x;848ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);849ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);850}851}852}853else // r.dir.x == 0854{855if (r.pos.x < b.min.x || r.pos.x > b.max.x)856return false;857}858859//860// Minimum and maximum Y sides.861//862863if (r.dir.y > 0)864{865if (r.pos.y > b.max.y)866return false;867868T d = b.max.y - r.pos.y;869870if (r.dir.y > 1 || d < TMAX * r.dir.y)871{872T t = d / r.dir.y;873874if (tBackMin > t)875tBackMin = t;876}877878if (r.pos.y <= b.min.y)879{880T d = b.min.y - r.pos.y;881T t = (r.dir.y > 1 || d < TMAX * r.dir.y)? d / r.dir.y: TMAX;882883if (tFrontMax < t)884{885tFrontMax = t;886887ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);888ip.y = b.min.y;889ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);890}891}892}893else if (r.dir.y < 0)894{895if (r.pos.y < b.min.y)896return false;897898T d = b.min.y - r.pos.y;899900if (r.dir.y < -1 || d > TMAX * r.dir.y)901{902T t = d / r.dir.y;903904if (tBackMin > t)905tBackMin = t;906}907908if (r.pos.y >= b.max.y)909{910T d = b.max.y - r.pos.y;911T t = (r.dir.y < -1 || d > TMAX * r.dir.y)? d / r.dir.y: TMAX;912913if (tFrontMax < t)914{915tFrontMax = t;916917ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);918ip.y = b.max.y;919ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);920}921}922}923else // r.dir.y == 0924{925if (r.pos.y < b.min.y || r.pos.y > b.max.y)926return false;927}928929//930// Minimum and maximum Z sides.931//932933if (r.dir.z > 0)934{935if (r.pos.z > b.max.z)936return false;937938T d = b.max.z - r.pos.z;939940if (r.dir.z > 1 || d < TMAX * r.dir.z)941{942T t = d / r.dir.z;943944if (tBackMin > t)945tBackMin = t;946}947948if (r.pos.z <= b.min.z)949{950T d = b.min.z - r.pos.z;951T t = (r.dir.z > 1 || d < TMAX * r.dir.z)? d / r.dir.z: TMAX;952953if (tFrontMax < t)954{955tFrontMax = t;956957ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);958ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);959ip.z = b.min.z;960}961}962}963else if (r.dir.z < 0)964{965if (r.pos.z < b.min.z)966return false;967968T d = b.min.z - r.pos.z;969970if (r.dir.z < -1 || d > TMAX * r.dir.z)971{972T t = d / r.dir.z;973974if (tBackMin > t)975tBackMin = t;976}977978if (r.pos.z >= b.max.z)979{980T d = b.max.z - r.pos.z;981T t = (r.dir.z < -1 || d > TMAX * r.dir.z)? d / r.dir.z: TMAX;982983if (tFrontMax < t)984{985tFrontMax = t;986987ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);988ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);989ip.z = b.max.z;990}991}992}993else // r.dir.z == 0994{995if (r.pos.z < b.min.z || r.pos.z > b.max.z)996return false;997}998999return tFrontMax <= tBackMin;1000}100110021003template<class T>1004bool1005intersects (const Box< Vec3<T> > &box, const Line3<T> &ray)1006{1007Vec3<T> ignored;1008return intersects (box, ray, ignored);1009}101010111012} // namespace Imath10131014#endif101510161017