所以我又回来了另一个光线追踪问题。我的代码使球体都很好,很花花公子,但立方体并没有真正工作。我正在使用以下代码来测试交集:http://pastebin.com/qgm6vpdx(这是一个递归函数,t 是到交点的距离(边界框定义为:
Cube* c1 = new Cube;
c1->Corner1 = Vec3(100, 100, 100);
c1->Corner2 = Vec3(200, 200, 200);
我已经确认相机不在立方体内。现在,唯一的问题是整个屏幕显示为绿色(指定给立方体的颜色(
我认为我做的立方体交叉点不正确,任何人都可以校对阅读我的代码吗?
计算射线盒交集的最佳算法之一是平板方法。 我在这里也概述了我对它的优化实现。
你可以使代码更短,更具可读性。 例如,将int tNear = -2147000000
更改为int tNear = INT_MIN
并更改
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)
。
更根本的是,这会将您限制为轴对齐的长方体,尽管此代码以后作为更复杂的形状的快速命中测试可能很有用。 无论如何,一旦这起作用,您可能希望使其更通用。
您可以将任何凸多边形定义为一组法线朝外的无限平面。 如果点位于所有平面的"内部",则该点位于多边形内部。
平面将空间分成两半。 将法线指向的一半定义为"外部",将另一半定义为"内部"。 然后,如果该点的平面方程为正,则点在平面外部,如果值为负,则在平面内,如果值为零,则在平面内。
要进行光线追踪,您需要确定光线/平面相交并选择最近的相交点。 要确定该点是否在面内(记住,平面是无限的(,请检查该点是否在所有其他平面内。 如果没有,请测试下一个最近的交叉点,依此类推。
一旦它起作用,就很容易将其扩展到一般的交叉点和形状的差异(例如,其中一个面上有半球形缩进的立方体(。