Ray-tracing triangles

时间:2016-11-12 05:53:19

标签: java algorithm 3d intersection raytracing

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. First determine if the ray even intersects the plane that the triangle is on.
  2. Clip all points so they are on the same plane as the triangle (so to the xy plane, as an example).
  3. Determine if the potential intersection point falls inside or out of the triangle, based on the number of polygon edges you cross when sending out a ray in an arbitrary direction along the new plane.

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

Where getPlaceIntersectionVector() is:

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:
Plane Intersection

And this:
Ray intersection

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)

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.

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.

2 个答案:

答案 0 :(得分:1)

问题在于这一行:

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

平面由法线和从平面到原点的距离定义。向量与原点的距离是向量的长度,因此您计算的只是平面法线的长度(如果已经标准化,则总是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);

答案 1 :(得分:1)

略有不同的方法:

让我们的三角形顶点为V0, V1, V2
边缘矢量

A = V1-V0
B = V2 - V0

Ray有参数方程式(如你所写)

P = R0 + t * Rd

从另一侧,交叉点在三角形平面中具有参数坐标u,v

P = V0 + u * A + v * B

因此,您可以为x,y,z坐标编写三个线性方程组,并为t, u, v求解。如果行列式ius非零(光线与平面不平行),并且t >=0u, v, u+v位于范围0..1中,则P位于三角形内。

R0.X + t * Rd.X = V0.X + u * A.X + v * B.X
R0.Y + t * Rd.Y = V0.Y + u * A.Y + v * B.Y
R0.Z + t * Rd.Z = V0.Z + u * A.Z + v * B.Z