1016 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1016 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
///////////////////////////////////////////////////////////////////////////
 | 
						|
//
 | 
						|
// Copyright (c) 2002-2010, Industrial Light & Magic, a division of Lucas
 | 
						|
// Digital Ltd. LLC
 | 
						|
//
 | 
						|
// All rights reserved.
 | 
						|
//
 | 
						|
// Redistribution and use in source and binary forms, with or without
 | 
						|
// modification, are permitted provided that the following conditions are
 | 
						|
// met:
 | 
						|
// *       Redistributions of source code must retain the above copyright
 | 
						|
// notice, this list of conditions and the following disclaimer.
 | 
						|
// *       Redistributions in binary form must reproduce the above
 | 
						|
// copyright notice, this list of conditions and the following disclaimer
 | 
						|
// in the documentation and/or other materials provided with the
 | 
						|
// distribution.
 | 
						|
// *       Neither the name of Industrial Light & Magic nor the names of
 | 
						|
// its contributors may be used to endorse or promote products derived
 | 
						|
// from this software without specific prior written permission.
 | 
						|
//
 | 
						|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
						|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
						|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
						|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
						|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
						|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
						|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
						|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
						|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
						|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
						|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
						|
//
 | 
						|
///////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#ifndef INCLUDED_IMATHBOXALGO_H
 | 
						|
#define INCLUDED_IMATHBOXALGO_H
 | 
						|
 | 
						|
 | 
						|
//---------------------------------------------------------------------------
 | 
						|
//
 | 
						|
//	This file contains algorithms applied to or in conjunction
 | 
						|
//	with bounding boxes (Imath::Box). These algorithms require
 | 
						|
//	more headers to compile. The assumption made is that these
 | 
						|
//	functions are called much less often than the basic box
 | 
						|
//	functions or these functions require more support classes.
 | 
						|
//
 | 
						|
//	Contains:
 | 
						|
//
 | 
						|
//	T clip<T>(const T& in, const Box<T>& box)
 | 
						|
//
 | 
						|
//	Vec3<T> closestPointOnBox(const Vec3<T>&, const Box<Vec3<T>>& )
 | 
						|
//
 | 
						|
//	Vec3<T> closestPointInBox(const Vec3<T>&, const Box<Vec3<T>>& )
 | 
						|
//
 | 
						|
//	Box< Vec3<S> > transform(const Box<Vec3<S>>&, const Matrix44<T>&)
 | 
						|
//	Box< Vec3<S> > affineTransform(const Box<Vec3<S>>&, const Matrix44<T>&)
 | 
						|
//
 | 
						|
//	void transform(const Box<Vec3<S>>&, const Matrix44<T>&, Box<V3ec3<S>>&)
 | 
						|
//	void affineTransform(const Box<Vec3<S>>&,
 | 
						|
//                           const Matrix44<T>&,
 | 
						|
//                           Box<V3ec3<S>>&)
 | 
						|
//
 | 
						|
//	bool findEntryAndExitPoints(const Line<T> &line,
 | 
						|
//				    const Box< Vec3<T> > &box,
 | 
						|
//				    Vec3<T> &enterPoint,
 | 
						|
//				    Vec3<T> &exitPoint)
 | 
						|
//
 | 
						|
//	bool intersects(const Box<Vec3<T>> &box,
 | 
						|
//			const Line3<T> &ray,
 | 
						|
//			Vec3<T> intersectionPoint)
 | 
						|
//
 | 
						|
//	bool intersects(const Box<Vec3<T>> &box, const Line3<T> &ray)
 | 
						|
//
 | 
						|
//---------------------------------------------------------------------------
 | 
						|
 | 
						|
#include "ImathBox.h"
 | 
						|
#include "ImathMatrix.h"
 | 
						|
#include "ImathLineAlgo.h"
 | 
						|
#include "ImathPlane.h"
 | 
						|
 | 
						|
namespace Imath {
 | 
						|
 | 
						|
 | 
						|
template <class T>
 | 
						|
inline T
 | 
						|
clip (const T &p, const Box<T> &box)
 | 
						|
{
 | 
						|
    //
 | 
						|
    // Clip the coordinates of a point, p, against a box.
 | 
						|
    // The result, q, is the closest point to p that is inside the box.
 | 
						|
    //
 | 
						|
 | 
						|
    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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
template <class T>
 | 
						|
inline T
 | 
						|
closestPointInBox (const T &p, const Box<T> &box)
 | 
						|
{
 | 
						|
    return clip (p, box);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
template <class T>
 | 
						|
Vec3<T>
 | 
						|
closestPointOnBox (const Vec3<T> &p, const Box< Vec3<T> > &box)
 | 
						|
{
 | 
						|
    //
 | 
						|
    // Find the point, q, on the surface of
 | 
						|
    // the box, that is closest to point p.
 | 
						|
    //
 | 
						|
    // If the box is empty, return p.
 | 
						|
    //
 | 
						|
 | 
						|
    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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
template <class S, class T>
 | 
						|
Box< Vec3<S> >
 | 
						|
transform (const Box< Vec3<S> > &box, const Matrix44<T> &m)
 | 
						|
{
 | 
						|
    //
 | 
						|
    // Transform a 3D box by a matrix, and compute a new box that
 | 
						|
    // tightly encloses 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
 | 
						|
    //
 | 
						|
 | 
						|
    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;
 | 
						|
}
 | 
						|
 | 
						|
template <class S, class T>
 | 
						|
void
 | 
						|
transform (const Box< Vec3<S> > &box,
 | 
						|
           const Matrix44<T>    &m,
 | 
						|
           Box< Vec3<S> >       &result)
 | 
						|
{
 | 
						|
    //
 | 
						|
    // Transform a 3D box by a matrix, and compute a new box that
 | 
						|
    // tightly encloses 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
 | 
						|
    //
 | 
						|
 | 
						|
    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);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
template <class S, class T>
 | 
						|
Box< Vec3<S> >
 | 
						|
affineTransform (const Box< Vec3<S> > &box, const Matrix44<T> &m)
 | 
						|
{
 | 
						|
    //
 | 
						|
    // 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.
 | 
						|
    //
 | 
						|
    // As in the transform() function, above, we use James Arvo's
 | 
						|
    // fast method.
 | 
						|
    //
 | 
						|
 | 
						|
    if (box.isEmpty() || box.isInfinite())
 | 
						|
    {
 | 
						|
    //
 | 
						|
    // A transformed empty or infinite box is still empty or infinite
 | 
						|
    //
 | 
						|
 | 
						|
    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;
 | 
						|
}
 | 
						|
 | 
						|
template <class S, class T>
 | 
						|
void
 | 
						|
affineTransform (const Box< Vec3<S> > &box,
 | 
						|
                 const Matrix44<T>    &m,
 | 
						|
                 Box<Vec3<S> >        &result)
 | 
						|
{
 | 
						|
    //
 | 
						|
    // 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.
 | 
						|
    //
 | 
						|
    // As in the transform() function, above, we use James Arvo's
 | 
						|
    // fast method.
 | 
						|
    //
 | 
						|
 | 
						|
    if (box.isEmpty())
 | 
						|
    {
 | 
						|
    //
 | 
						|
    // A transformed empty box is still empty
 | 
						|
    //
 | 
						|
        result.makeEmpty();
 | 
						|
    return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (box.isInfinite())
 | 
						|
    {
 | 
						|
    //
 | 
						|
    // A transformed infinite box is still infinite
 | 
						|
    //
 | 
						|
        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;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
template <class T>
 | 
						|
bool
 | 
						|
findEntryAndExitPoints (const Line3<T> &r,
 | 
						|
            const Box<Vec3<T> > &b,
 | 
						|
            Vec3<T> &entry,
 | 
						|
            Vec3<T> &exit)
 | 
						|
{
 | 
						|
    //
 | 
						|
    // Compute the points where a ray, r, enters and exits a box, b:
 | 
						|
    //
 | 
						|
    // findEntryAndExitPoints() returns
 | 
						|
    //
 | 
						|
    //     - true if the ray starts inside the box or if the
 | 
						|
    //       ray starts outside and intersects the box
 | 
						|
    //
 | 
						|
    //	   - false otherwise (that is, if the ray does not
 | 
						|
    //       intersect the box)
 | 
						|
    //
 | 
						|
    // The entry and exit points are
 | 
						|
    //
 | 
						|
    //     - points on two of the faces of the box when
 | 
						|
    //       findEntryAndExitPoints() returns true
 | 
						|
    //       (The entry end exit points may be on either
 | 
						|
    //       side of the ray's origin)
 | 
						|
    //
 | 
						|
    //     - undefined when findEntryAndExitPoints()
 | 
						|
    //       returns false
 | 
						|
    //
 | 
						|
 | 
						|
    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 = 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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
template<class T>
 | 
						|
bool
 | 
						|
intersects (const Box< Vec3<T> > &b, const Line3<T> &r, Vec3<T> &ip)
 | 
						|
{
 | 
						|
    //
 | 
						|
    // Intersect a ray, r, with a box, b, and compute the intersection
 | 
						|
    // point, ip:
 | 
						|
    //
 | 
						|
    // intersect() returns
 | 
						|
    //
 | 
						|
    //     - 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
 | 
						|
    //
 | 
						|
    // 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
 | 
						|
    //
 | 
						|
 | 
						|
    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 = 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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
template<class T>
 | 
						|
bool
 | 
						|
intersects (const Box< Vec3<T> > &box, const Line3<T> &ray)
 | 
						|
{
 | 
						|
    Vec3<T> ignored;
 | 
						|
    return intersects (box, ray, ignored);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
} // namespace Imath
 | 
						|
 | 
						|
#endif
 |