光线追踪三角形 [英] Ray-tracing triangles

查看:28
本文介绍了光线追踪三角形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用 Java 编写光线跟踪器,并且能够跟踪球体,但我相信我跟踪三角形的方式有问题.

I am writing a raytracer in java, and I was able to get tracing of spheres working, but I believe I have something wrong with how I am tracing triangles.

这是我理解的基本算法:

Here is the basic algorithm, as I understand it:

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

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

Now, here is my implementation of that (specifically the first point):

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);
} 

基本上试图模仿这个:

Which basically tries to mimic this:

还有这个:

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

Where t is the distance along the ray that the point hits, ro is the origin of the ray, rd is the direction of the ray, pn refers to the plane normal of the triangle/plane, and d is the distance from the plane that the triangle is on to the origin (0,0,0)

我做错了吗?当我从图像 (0,0) 的第一个像素发出光线时,我看到 intersectionDistance(或 t)几乎是 1100,这在我看来是错误的.我认为交叉点会更近.

Am I doing that wrong? When I send out the ray from the first pixel in the image (0,0), I am seeing that the intersectionDistance (or t) is almost 1100, which intuitively seems wrong to me. I would think that the intersection point would be much closer.

以下是相关数据:Ray origin (0,0,1),Ray Direction大致为(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,这意味着距离非常远.
我做的平面交叉错了吗?

Here is the relevant data: Ray origin (0,0,1), Ray Direction is roughly (0.000917, -0.4689, -0.8833).
Triangle has vertices as (-0.2, 0.1, 0.1), (-0.2, -0.5, 0.2), (-0.2, 0.1, -0.3), which makes the plane normal (-1, 0, 0).
According to my code, the Ray intersects the plane 1090 distance away, which as I mentioned before, seems wrong to me. The scene is only -1.0 to 1.0 in every direction, which means the intersection is very very far in the distance.
Am I doing the plane intersection wrong?

如果您需要更多信息,请告诉我在哪里澄清要点.

Please let me know where to clarify points, and if you need any more information.

推荐答案

问题是这一行:

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

平面由法线和平面到原点的距离定义.向量到原点的距离是向量的长度,所以你在那里计算的只是平面法线的长度(如果它已经被归一化,它总是1.0).

A plane is defined by a normal and a distance from the plane to the origin. The distance of a vector from the origin is the length of a vector, so what you are calculating there is just the length of the plane normal (which will always be 1.0 if it has been normalized).

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

The distance of the plane from the origin is an extra piece of information that needs to be passed into your function, you can't just calculate it from the normal because it's independent of it (you can can have lots of planes with normals pointing in the same direction at different distances from the origin).

这样定义你的函数:

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

并称之为:

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

然后你可以像这样计算vo:

Then you can calculate vo like this:

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

这篇关于光线追踪三角形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆