5
$\begingroup$

I've been trying to implement the Moller-Trumbore ray-triangle intersection algorithm in my raytracing code. The code is supposed to read in a mesh and light sources, fire off rays from the light source, and return the triangle from the mesh which each ray intersects. Here is my implementation of the algorithm:

//Moller-Trumbore intersection algorithm
void getFaceIntersect(modelStruct m, ray r, hitFaceStruct& hitFaces)
{
    // Constant thoughout loop
    point origin = r.p0;
    point direction = r.u;
    hitFaces.isHit = false;

    for (int i = 0; i < m.faces; i++)
    {
        // Get face vertices
        point v1 = m.vertList[m.faceList[i].v1];
        point v2 = m.vertList[m.faceList[i].v2];
        point v3 = m.vertList[m.faceList[i].v3];

        // Get two edgess
        point edge1 = v2 - v1;
        point edge2 = v3 - v1;

        // Get p
        point p = direction.cross(direction, edge2);
        // Use p to find determinant
        double det = p.dot(edge1, p);

        // If the determinant is about 0, the ray lies in the plane of the triangle
        if (abs(det) < 0.00000000001)
        {
            continue;
        }

        double inverseDet = 1 / det;

        point v1ToOrigin = (origin - v1);

        double u = v1ToOrigin.dot(v1ToOrigin, p) * inverseDet;

        // If u is not between 0 and 1, no hit
        if (u < 0 || u > 1)
        {
            continue;
        }

        // Used for calculating v
        point q = v1ToOrigin.cross(v1ToOrigin, edge1);
        double v = direction.dot(direction, q) * inverseDet;

        if (v < 0 || (u + v) > 1)
        {
            continue;
        }

        double t = q.dot(edge2, q) * inverseDet;

        // gets closest face
        if (t < abs(hitFaces.s)) 
        {
            hitFaceStruct goodStruct = hitFaceStruct();
            goodStruct.face = i;
            goodStruct.hitPoint = p;
            goodStruct.isHit = true;
            goodStruct.s = t;
            hitFaces = goodStruct;
            break;
        }
    }
}

The relevant code for hitFaceStruct and modelStruct is as follows:

typedef struct _hitFaceStruct
{
    int face; //the index of the sphere in question in the list of faces
    float s; //the distance from the ray that hit it
    bool isHit;
    point hitPoint;
} hitFaceStruct;

typedef struct _modelStruct {
    char *fileName;
    float scale;
    float rot_x, rot_y, rot_z;
    float x, y, z;
    float r_amb, g_amb, b_amb;
    float r_dif, g_dif, b_dif;
    float r_spec, g_spec, b_spec;
    float k_amb, k_dif, k_spec, k_reflective, k_refractive;
    float spec_exp, index_refraction;
    int verts, faces, norms = 0;    // Number of vertices, faces, normals, and spheres in the system
    point *vertList, *normList; // Vertex and Normal Lists
    faceStruct *faceList;       // Face List
} modelStruct;

Whenever I shoot a ray, the values of u or v in the algorithm code always come out to a large negative number, rather than the expected small, positive one. The direction vector of the ray is normalized before I pass it on to the intersection code, and I'm positive I'm firing rays that would normally hit the mesh. Can anyone please help me spot my error here?

$\endgroup$
  • 4
    $\begingroup$ did you check the numbers with a simple triangle? 1,0,0; 0,1,0; 0,0,1 and ray from origin to 1,1,1 $\endgroup$ – ratchet freak Nov 20 '15 at 8:54
3
$\begingroup$

The syntax for your dot- and cross-product are a bit strange. The methods are members of a vector, but still take two arguments. Are they static methods? Or are you really sure they do what you would expect?

Otherwise the only real difference in your implementation and the one you linked that I can see is your test against the parameter t.

The implementation you linked tests for

if(t > EPSILON)

your code tests for

if(t < abs(hitFaces.s))

I don't see in your code how you set the value for hitFaces.s since you fire this ray against a model and don't know jet if it has hit anything. My understanding would be, that you first test if t is large enough to signal a hit ( > EPSILON ) and then in a second step sort for the smallest t (closest to the ray origin).

In my head you can't get a value for hitFaces.s without calculating this intersection test as you wrote it, and the intersection test needs the hitFaces.s to determine if an intersection was made. But I could be in the wrong here.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.