2
votes

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

2 Answers

1
votes

The problem is this line:

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

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).

So define your function something like this:

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

and call it something like this:

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

Then you can calculate vo like this:

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

Slightly different approach:

Let's triangle vertices are V0, V1, V2
Edge vectors are

A = V1-V0
B = V2 - V0

Ray has parametric equation (as you wrote)

P = R0 + t * Rd

From the other side, intersection point has parametric coordinates u, v in the triangle plane

P = V0 + u * A + v * B

So you can write system of three linear equation for x, y, z coordinates and solve it for t, u, v. If determinant ius non-zero (ray is not parallel to the plane), and t >=0, and u, v, u+v lie in range 0..1, then P is inside triangle.

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