📄 imathboxalgo.h
字号:
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, 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>>& )
//
// void transform(Box<Vec3<T>>&, const Matrix44<T>&)
//
// 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& in, const Box<T>& box)
{
//
// Clip a point so that it lies inside the given bbox
//
T out;
for (int i=0; i<(int)box.min.dimensions(); i++)
{
if (in[i] < box.min[i]) out[i] = box.min[i];
else if (in[i] > box.max[i]) out[i] = box.max[i];
else out[i] = in[i];
}
return out;
}
//
// Return p if p is inside the box.
//
template <class T>
Vec3<T>
closestPointInBox(const Vec3<T>& p, const Box< Vec3<T> >& box )
{
Imath::V3f b;
if (p.x < box.min.x)
b.x = box.min.x;
else if (p.x > box.max.x)
b.x = box.max.x;
else
b.x = p.x;
if (p.y < box.min.y)
b.y = box.min.y;
else if (p.y > box.max.y)
b.y = box.max.y;
else
b.y = p.y;
if (p.z < box.min.z)
b.z = box.min.z;
else if (p.z > box.max.z)
b.z = box.max.z;
else
b.z = p.z;
return b;
}
template <class T>
Vec3<T> closestPointOnBox(const Vec3<T>& pt, const Box< Vec3<T> >& box )
{
//
// This sucker is specialized to work with a Vec3f and a box
// made of Vec3fs.
//
Vec3<T> result;
// trivial cases first
if (box.isEmpty())
return pt;
else if (pt == box.center())
{
// middle of z side
result[0] = (box.max[0] + box.min[0])/2.0;
result[1] = (box.max[1] + box.min[1])/2.0;
result[2] = box.max[2];
}
else
{
// Find the closest point on a unit box (from -1 to 1),
// then scale up.
// Find the vector from center to the point, then scale
// to a unit box.
Vec3<T> vec = pt - box.center();
T sizeX = box.max[0]-box.min[0];
T sizeY = box.max[1]-box.min[1];
T sizeZ = box.max[2]-box.min[2];
T halfX = sizeX/2.0;
T halfY = sizeY/2.0;
T halfZ = sizeZ/2.0;
if (halfX > 0.0)
vec[0] /= halfX;
if (halfY > 0.0)
vec[1] /= halfY;
if (halfZ > 0.0)
vec[2] /= halfZ;
// Side to snap side that has greatest magnitude in the vector.
Vec3<T> mag;
mag[0] = fabs(vec[0]);
mag[1] = fabs(vec[1]);
mag[2] = fabs(vec[2]);
result = mag;
// Check if beyond corners
if (result[0] > 1.0)
result[0] = 1.0;
if (result[1] > 1.0)
result[1] = 1.0;
if (result[2] > 1.0)
result[2] = 1.0;
// snap to appropriate side
if ((mag[0] > mag[1]) && (mag[0] > mag[2]))
{
result[0] = 1.0;
}
else if ((mag[1] > mag[0]) && (mag[1] > mag[2]))
{
result[1] = 1.0;
}
else if ((mag[2] > mag[0]) && (mag[2] > mag[1]))
{
result[2] = 1.0;
}
else if ((mag[0] == mag[1]) && (mag[0] == mag[2]))
{
// corner
result = Vec3<T>(1,1,1);
}
else if (mag[0] == mag[1])
{
// edge parallel with z
result[0] = 1.0;
result[1] = 1.0;
}
else if (mag[0] == mag[2])
{
// edge parallel with y
result[0] = 1.0;
result[2] = 1.0;
}
else if (mag[1] == mag[2])
{
// edge parallel with x
result[1] = 1.0;
result[2] = 1.0;
}
// Now make everything point the right way
for (int i=0; i < 3; i++)
{
if (vec[i] < 0.0)
result[i] = -result[i];
}
// scale back up and move to center
result[0] *= halfX;
result[1] *= halfY;
result[2] *= halfZ;
result += box.center();
}
return result;
}
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
//
if (box.isEmpty())
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++)
{
float 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 T>
Box< Vec3<T> >
affineTransform(const Box< Vec3<T> > &bbox, const Matrix44<T> &M)
{
float min0, max0, min1, max1, min2, max2, a, b;
float min0new, max0new, min1new, max1new, min2new, max2new;
min0 = bbox.min[0];
max0 = bbox.max[0];
min1 = bbox.min[1];
max1 = bbox.max[1];
min2 = bbox.min[2];
max2 = bbox.max[2];
min0new = max0new = M[3][0];
a = M[0][0] * min0;
b = M[0][0] * max0;
if (a < b) {
min0new += a;
max0new += b;
} else {
min0new += b;
max0new += a;
}
a = M[1][0] * min1;
b = M[1][0] * max1;
if (a < b) {
min0new += a;
max0new += b;
} else {
min0new += b;
max0new += a;
}
a = M[2][0] * min2;
b = M[2][0] * max2;
if (a < b) {
min0new += a;
max0new += b;
} else {
min0new += b;
max0new += a;
}
min1new = max1new = M[3][1];
a = M[0][1] * min0;
b = M[0][1] * max0;
if (a < b) {
min1new += a;
max1new += b;
} else {
min1new += b;
max1new += a;
}
a = M[1][1] * min1;
b = M[1][1] * max1;
if (a < b) {
min1new += a;
max1new += b;
} else {
min1new += b;
max1new += a;
}
a = M[2][1] * min2;
b = M[2][1] * max2;
if (a < b) {
min1new += a;
max1new += b;
} else {
min1new += b;
max1new += a;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -