您可以使代码更短且更具可读性。比如 change int tNear = -2147000000
toint tNear = INT_MIN
和 change
if(t1 > t2)
{
float temp1 = t1;
t1 = t2;
t2 = temp1;
}
至
if(t1 > t2)
{
// std::swap is built-in
swap(t1, t2);
}
或更好
// Define 'order' yourself
order(t1, t2);
和改变
if(t1 > tNear)
{
tNear = t1;
}
至
// std::max is built in
tNear = max(tNear, t1);
然后您的代码的一部分变为:
if ((ray.dir.x == 0) && (ray.start.x < Min.x) && (ray.start.x > Max.x))
{
//parallel
return false;
}
else
{
float t1 = (Min.x - ray.start.x) / ray.dir.x;
float t2 = (Max.x - ray.start.x) / ray.dir.x;
order(t1, t2);
tNear = max(tNear, t1);
tFar = max(tFar, t1);
if ((tNear > tFar) || (tFar < 0))
return false;
}
这揭示了一个问题。 tNear
并tFar
定义t
线与立方体相交的值区间。您测试的每个坐标(x、y 和 z)进一步限制了区间。然而,代码tFar = max(tFar, t1)
正在扩大区间。将其更改为tFar = min(tFar, t1)
.
更根本的是,这将您限制为轴对齐的长方体,尽管此代码稍后可能会用作更复杂形状的快速命中测试。无论如何,一旦它起作用,您可能希望使其更通用。
您可以将任何凸多边形定义为法线朝外的一组无限平面。如果一个点位于所有平面的“内部”,则该点位于多边形内部。
平面将空间分成两半。将法线指向的一半定义为“外侧”,另一半定义为“内侧”。如果该点的平面方程为正,则该点在平面外,如果值为负,则在平面内,如果值为零,则在平面上。
要进行光线追踪,您需要确定光线/平面的交点并选择最近的一个。要确定该点是否在面内(请记住,平面是无限的),请检查该点是否在所有其他平面内。如果不是,则测试下一个最近的交叉点,依此类推。
一旦这工作起来,就很容易将其扩展到一般的交叉点和形状的差异(例如,在其中一个面上带有半球形凹痕的立方体)。