光线跟踪盒交叉点

时间:2012-01-17 23:54:04

标签: c++ vector-graphics raytracing cubes

所以我回来了另一个光线追踪问题。我的代码渲染球体都很好,花花公子,但立方体并没有真正起作用。我正在使用此代码来测试交叉点:http://pastebin.com/qgm6vpdx(这是一个递归函数,t是到交点的距离) 边界框定义为:

Cube* c1 = new Cube;      
c1->Corner1 = Vec3(100, 100, 100);      
c1->Corner2 = Vec3(200, 200, 200);

我已经确认相机不在立方体内。 现在,唯一的问题是整个屏幕显示为绿色(指定给立方体的颜色)

我不认为我正在做正确的立方体交叉点,任何人都可以证明我的代码读了吗?

2 个答案:

答案 0 :(得分:6)

计算光线盒交叉点的最佳算法之一是slab method。我概述了我here的优化实现。

答案 1 :(得分:3)

您可以使代码更短,更易读。例如,将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;
}

这揭示了一个问题。 tNeartFar定义了t值的间隔,其中线与多维数据集相交。您测试的每个坐标(x,y和z)进一步限制了间隔。但是代码tFar = max(tFar, t1)正在扩展间隔。将其更改为tFar = min(tFar, t1)

更基本的是,这限制了您使用轴对齐的长方体,尽管此代码可能稍后用作更复杂形状的快速命中测试。无论如何,一旦这个工作,你可能想让它更通用。

您可以将任何凸多边形定义为一组无限平面,法线朝外。如果点位于所有平面的“内部”,则该点位于多边形内部。

飞机将空间分成两半。将法线指向的一半定义为“外部”,另一半定义为“内部”。如果该点处的平面方程为正,则该点位于平面外,如果该值为负,则位于平面内;如果该值为零,则位于平面上。

要对此进行光线跟踪,请确定光线/平面交点并选择最近的交点。要确定该点是否在面内(请记住,平面是无限的),您可以检查该点是否在所有其他平面内。如果没有,请测试下一个最近的交叉路口,依此类推。

一旦这个工作,很容易将它扩展到一般的交叉点和形状的差异(例如,在其中一个面上有一个半球形凹痕的立方体)。