java - 光线追踪三角形

标签 java algorithm 3d intersection raytracing

我正在用java编写一个光线追踪器,并且我能够追踪球体,但我相信我追踪三角形的方式有问题。

这是我理解的基本算法:

  1. 首先确定光线是否与三角形所在的平面相交。
  2. 剪裁所有点,使它们与三角形位于同一平面上(例如,在 xy 平面上)。
  3. 根据沿着新平面向任意方向发出射线时穿过的多边形边的数量,确定潜在的交点是落在三角形内部还是外部。

现在,这是我的实现(特别是第一点):

public Vector getIntersectionVector(Ray ray)
{
    Vector planeIntersectionVector = getPlaneIntersectionVector(ray, getPlaneNormal());
    if (planeIntersectionVector != null)
    {
        if (isIntersectionVectorInsideTriangle(planeIntersectionVector))
        {
            return planeIntersectionVector;
        }
        else
        {
            return null;
        }
    }
    else
    {
        return null;
    }
}

其中 getPlaceIntersectionVector() 是:

private Vector getPlaneIntersectionVector(Ray ray, Vector planeNormal)
{
    double vd = planeNormal.dotProduct(ray.getDirection());
    //(p_n \dot r_d) == 0, parallel. (p_n \dot r_d) > 0 Plane normal pointing away from ray.
    if (vd >= 0)
    {
        return null;
    }
    double distance = planeNormal.distance(0d, 0d, 0d);
    double vo = -(planeNormal.dotProduct(ray.getOrigin()) + distance);
    double intersectionDistance = vo / vd;

    //intersectionDistance <= 0 means the "intersection" is behind the ray, so not a real intersection
    return (intersectionDistance <= 0) ? null : ray.getLocation(intersectionDistance);
} 

它基本上试图模仿这个:
Plane Intersection

还有这个:
Ray intersection

其中t是点沿射线的距离,ro是射线的原点,rd是射线方向,pn 指三角形/平面的平面法线,d 是三角形所在平面到原点的距离(0,0,0)

我做错了吗?当我从图像 (0,0) 中的第一个像素发出光线时,我看到 intersectionDistance (或 t)几乎是1100,直觉上我觉得这似乎是错误的。我认为交点会更近。

相关数据如下: 光线原点 (0,0,1),光线方向大致为 (0.000917, -0.4689, -0.8833)
三角形的顶点为 (-0.2, 0.1, 0.1)(-0.2, -0.5, 0.2)(-0.2, 0.1, -0.3),使平面正常(-1, 0, 0)
根据我的代码,射线与平面 1090 距离相交,正如我之前提到的,这对我来说似乎是错误的。场景在每个方向上都只有 -1.0 到 1.0,这意味着路口距离非常非常远。
我做的平面交叉错了吗?

请告诉我哪里需要澄清,以及您是否需要更多信息。

最佳答案

问题出在这一行:

double distance = planeNormal.distance(0d, 0d, 0d);

平面由法线和平面到原点的距离定义。 vector 距原点的距离就是 vector 的长度,因此您计算的只是平面法线的长度(如果已归一化,则始终为 1.0)。

平面与原点的距离是需要传递到函数中的额外信息,您不能仅根据法线计算它,因为它与法线无关(您可以有很多平面法线在距原点不同距离处指向同一方向)。

所以定义你的函数是这样的:

private Vector getPlaneIntersectionVector(Ray ray, Vector planeNormal, double planeDistance)

并将其命名为这样的:

Vector planeIntersectionVector = getPlaneIntersectionVector(ray, getPlaneNormal(), getPlaneDistance());

然后你可以这样计算vo:

double vo = -(planeNormal.dotProduct(ray.getOrigin()) + planeDistance);

关于java - 光线追踪三角形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40560000/

相关文章:

算法 : explanation about complexity and optimization

java - 我可以配置我的 servlet 容器的线程管理吗?

java - 选中 JTable 中的复选框时的通知

java - 使用 PowerMock- EasyMock 时意外的方法调用

java - Java程序中的无限递归

arrays - 下面代码中函数内部的 (if block) 的作用是什么?

algorithm - 检测三角形和旋转球体之间的 3D 碰撞

boost - 如何读取/转换 stanford bunny .ply-files 的范围图像?

OpenGL 围绕一个点旋转相机

java - 在 spring security 中禁用浏览器身份验证对话框