Search code examples
javascriptgeometryraytracing

Triangle intersection in raytracer not working


I am trying to make my own raytracer in Javascript. So far the spheres work very well. I now want to expand the capabilities to include triangles, and from there I can go to squares, cubes and beyond. The code I have for finding intersections with triangles is as follows

function triangleIntersection(t, r) {
var norm = triangleNormal(t);
var dist = triangleDistance(t);
var a = Vector.dotProduct(r.vector, norm);

if (a === 0) {
    return -1;
} else {
    var b = Vector.dotProduct(norm, Vector.add(r.point, Vector.negative(Vector.multiply(norm, dist))));
    var d = -1 * b / a;

    var qx = Vector.scale(r.vector, d).x + r.point.x;
    var qy = Vector.scale(r.vector, d).y + r.point.y;
    var qz = Vector.scale(r.vector, d).z + r.point.z;

    var q = new Vector(qx, qy, qz);

    var ca = Vector.subtract(t.points[2], t.points[0]);
    var qa = Vector.subtract(q, t.points[0]);
    var t1 = Vector.dotProduct(Vector.crossProduct(ca, qa), norm);

    var bc = Vector.subtract(t.points[1], t.points[2]);
    var qc = Vector.subtract(q, t.points[2]);
    var t2 = Vector.dotProduct(Vector.crossProduct(bc, qc), norm);

    var ab = Vector.subtract(t.points[0], t.points[1]);
    var qb = Vector.subtract(q, t.points[1]);
    var t3 = Vector.dotProduct(Vector.crossProduct(ab, qb), norm);

    if ((t1 >= 0) && (t2 >= 0) && (t3 >= 0)) {
        return 1 * b / a;
    } else {
        return -1;
    }
}

}

Triangle objects have a point array (points[]) and item 0 is point A, item 1 is point B and item 2 is point C. The parameter t is one of these triangles. The parameter r is a ray object, with properties point which is the origin, and vector, which is the direction.

I also have these functions for finding normal and distance of a triangle.

function triangleNormal(s) {
var ca = Vector.subtract(s.points[2], s.points[0]);
var ba = Vector.subtract(s.points[1], s.points[0]);
var norm = Vector.unitVector(Vector.crossProduct(ca, ba));

return norm;
}

function triangleDistance(t) {
    return Vector.dotProduct(triangleNormal(t, 0), t.points[0]);
}

When I render my scene the triangle I use in my scene is red colored. No matter how far I move my camera back the triangle fills the whole scene red. I do not know why this happens.


Solution

  • An important error in your plane intersection code is this comparison operation:

    a === 0

    There are two things wrong with it:

    1. For ray tracing you want the ray to hit planes in front of its source, not behind it, so you need a < 0.

    2. Even if you did want the ray to hit planes behind it, you must never do equality operations between floating point values, because floating point calculations are not exact. (You must do something like abs(a) < 1e-6f or some small value)