光线跟踪器,计算查看光线(Java)

光线跟踪器,计算查看光线(Java),java,Java,在学校,我最近开始创建自己的光线跟踪器。然而,我遇到了一个障碍,要么计算查看光线,要么检查三角形和光线之间的交点。据我所知,计算似乎是正确的,因为我把我的相机放在原点,让它朝向它正前方的一个物体的-z轴,允许用手进行简单的矢量数学。一切似乎都正常,但屏幕上什么也没画出来 我将发布我正在使用的代码来计算观察光线 public Ray generateRay(float nX, float nY , Point2f coordinates) { // Compute l, r, b and

在学校,我最近开始创建自己的光线跟踪器。然而,我遇到了一个障碍,要么计算查看光线,要么检查三角形和光线之间的交点。据我所知,计算似乎是正确的,因为我把我的相机放在原点,让它朝向它正前方的一个物体的-z轴,允许用手进行简单的矢量数学。一切似乎都正常,但屏幕上什么也没画出来

我将发布我正在使用的代码来计算观察光线

public Ray generateRay(float nX, float nY , Point2f coordinates)
{
    // Compute l, r, b and t.
    Vector3f temp = VectorHelper.multiply(u, nX/2.0f);
    float r = temp.x + Position.x;
    temp = VectorHelper.multiply(u, -nX/2.0f);
    float l = temp.x + Position.x;
    temp = VectorHelper.multiply(v, nY/2.0f);
    float t = temp.y + Position.y;
    temp = VectorHelper.multiply(v, -nY/2.0f);
    float b = temp.y + Position.y;

    // Compute the u and v coordinates.
    float uCo = (l + (r - l) * (coordinates.x + 0.5f)/nX);
    float vCo = (b + (t - b) * (coordinates.y + 0.5f)/nY);

    // Compute the ray's direction.
    Vector3f rayDirection = VectorHelper.multiply(w, -FocalLength);
    temp = VectorHelper.add(VectorHelper.multiply(u, uCo), VectorHelper.multiply(v, vCo));
    rayDirection = VectorHelper.add(rayDirection, temp);
    rayDirection = VectorHelper.add(rayDirection, Position);
    rayDirection = VectorHelper.normalize(VectorHelper.add(rayDirection, temp));

    // Create and return the ray.
    return new Ray(Position, rayDirection);
}
下面的代码是我用来计算交叉点的代码。它使用Cramer法则来求解矩阵方程

public static Point3f rayTriangleIntersection(
        Ray ray, Point3f vertexA, Point3f vertexB, Point3f vertexC)
{
    // Solve the linear system formed by the ray and the parametric surface
    // formed by the points of the triangle.
    // | a d g |   | B |   | j |
    // | b e h | * | Y | = | k |
    // | c f i | * | t | = | l |
    // The following uses Cramer's rule to that effect.
    float a = vertexA.x - vertexB.x; float d = vertexA.x - vertexC.x; float g = ray.getDirection().x;
    float b = vertexA.y - vertexB.y; float e = vertexA.y - vertexC.y; float h = ray.getDirection().y;
    float c = vertexA.z - vertexB.z; float f = vertexA.z - vertexC.z; float i = ray.getDirection().z;

    float j = vertexA.x - ray.getOrigin().x;
    float k = vertexA.y - ray.getOrigin().y;
    float l = vertexA.z - ray.getOrigin().z;

    // Compute some subterms in advance.
    float eihf = (e * i) - (h * f);
    float gfdi = (g * f) - (d * i);
    float dheg = (d * h) - (e * g);
    float akjb = (a * k) - (j * b);
    float jcal = (j * c) - (a * l);
    float blkc = (b * l) - (k * c);
    // Compute common division number.
    float m = (a * eihf) + (b * gfdi) + (c * dheg);

    // Compute unknown t and check whether the point is within the given
    // depth interval.
    float t = -((f * akjb) + (e * jcal) + (d * blkc)) / m;
    if (t < 0)
        return null;

    // Compute unknown gamma and check whether the point intersects the
    // triangle.
    float gamma = ((i * akjb) + (h * jcal) + (g * blkc)) / m;
    if (gamma < 0 || gamma > 1)
        return null;

    // Compute unknown beta and check whether the point intersects the
    // triangle.
    float beta = ((j * eihf) + (k * gfdi) + (l * dheg)) / m;
    if (beta < 0 || beta > (1 - gamma))
        return null;

    // Else, compute the intersection point and return it.
    Point3f result = new Point3f();
    result.x = ray.getOrigin().x + t * ray.getDirection().x;
    result.y = ray.getOrigin().y + t * ray.getDirection().y;
    result.z = ray.getOrigin().z + t * ray.getDirection().z;
    return result;
}
公共静态点3f光线三角形相交(
光线、点3F顶点A、点3F顶点B、点3F顶点EXC)
{
//求解光线与参数曲面构成的线性系统
//由三角形的点组成。
//| a d g | | B | | j|
//| b e h |*| Y |=| k|
//| c f i |*| t |=| l|
//下面使用克拉姆规则来达到这个效果。
浮点a=vertexA.x-vertexB.x;浮点d=vertexA.x-vertexC.x;浮点g=ray.getDirection().x;
float b=vertexA.y-vertexB.y;float e=vertexA.y-vertexC.y;float h=ray.getDirection().y;
float c=vertexA.z-vertexB.z;float f=vertexA.z-vertexC.z;float i=ray.getDirection().z;
float j=vertexA.x-ray.getOrigin().x;
float k=vertexA.y-ray.getOrigin().y;
float l=vertexA.z-ray.getOrigin().z;
//提前计算一些子项。
浮动eihf=(e*i)-(h*f);
浮点数gfdi=(g*f)-(d*i);
浮动dheg=(d*h)-(e*g);
浮动akjb=(a*k)-(j*b);
浮点数jcal=(j*c)-(a*l);
浮动blkc=(b*l)-(k*c);
//计算公共除法数。
浮动m=(a*eihf)+(b*gfdi)+(c*dheg);
//计算未知t并检查该点是否在给定范围内
//深度间隔。
浮点数t=-((f*akjb)+(e*jcal)+(d*blkc))/m;
if(t<0)
返回null;
//计算未知gamma并检查该点是否与
//三角形。
浮点伽马=((i*akjb)+(h*jcal)+(g*blkc))/m;
如果(伽马<0 | |伽马>1)
返回null;
//计算未知β并检查该点是否与
//三角形。
浮动β=((j*eihf)+(k*gfdi)+(l*dheg))/m;
if(β<0 | |β>(1-γ))
返回null;
//否则,计算交点并返回它。
Point3f结果=新的Point3f();
result.x=ray.getOrigin().x+t*ray.getDirection().x;
result.y=ray.getOrigin().y+t*ray.getDirection().y;
result.z=ray.getOrigin().z+t*ray.getDirection().z;
返回结果;
}
我的问题很简单。我做错了什么?我已经仔细查看并调试了这段代码,但无法挑出错误,谷歌提供的只是我正在使用的书中已有的理论。此外,代码仍然相当粗糙,因为我只是专注于在清理之前让它工作

提前感谢,


凯文

很难说到底出了什么问题。特别是因为您没有使用描述性变量名(nX、nY等是什么?)

以下是一些提示:

  • 首先确保它不是显示代码中的错误。假交叉点以证明当你击中某个物体时,你得到了可见的输出,例如,使屏幕右下角的所有光线击中一个轴对齐的平面或类似的物体,以便你可以轻松地验证坐标
  • 首先尝试光线/球体相交。这比光线/三角形相交更容易
  • 考虑使用向量/矩阵运算,而不是手动计算所有组件。在许多乱七八糟的字母行中很容易出错
  • 如果存在缩放问题(例如,对象太小),请再次检查世界坐标和屏幕坐标之间的转换。世界坐标将在小的双倍数字范围内(例如0.2…5.0),而屏幕坐标应该是根据您的视图大小(例如0…1024)确定的像素位置。您应该在世界坐标中完成大部分数学运算,仅在渲染代码的开始和结束时从/到屏幕坐标进行转换
  • 在调试器中逐步执行顶层光线跟踪代码,并确保为每个屏幕坐标(尤其是屏幕的角点)在合理的方向上生成光线
  • 检查相机方向是否指向目标对象。让它朝着完全相反的方向看是很容易犯的错误
应起作用的示例设置:

  • 摄像机位置[0 0 4]
  • 对象位置[0]
  • 摄影机方向[0-1](如果希望它朝向原点,请注意负号!)
  • 上方向向量[0.75 0]
  • 右向量[+/-1 0]
那么你的光线方向应该是这样的(对于像素[screenX,screenY]):

光线=方向+(2*(屏幕X/屏幕宽度)-1)*右侧+(1-2*(屏幕Y/屏幕高度))*向上

光线=规格化(光线)


对我来说没有什么是错的。。。但是,如果一切似乎都在调试模式下签出,那么可能是您在显示步骤中做错了什么?我会尝试将光线跟踪器代码放在一边,并尝试使用相同的显示代码打印一个测试用例,并确保它正常工作。我一直在尝试一些调试工作,例如第一个建议,但我会尝试一些更硬的代码。我将看一看光线-球体相交,它听起来确实很简单,如果它起作用的话,我至少知道这两个函数中的哪一个没有起到应有的作用。谢谢你的帮助!多亏了你(米凯拉)和杜伦的建议,我找到了错误所在,我几乎不好意思承认这很简单。虽然在报告中有一些小错误