1
votes

I am currently writing a pathtracer. Now i want to implement ray - triangle intersection. So my triangle consists of three Points (v0,v1,v2). I looked at other posts on this topic (Raytracing - Ray/Triangle Intersection). Sadly it is not working correctly so i want to check if the problem is on the intersection side. Here are my two triangle functions:

public float intersect(Ray ray){
    Vector3D e1 = v1.sub(v0);
    Vector3D e2 = v2.sub(v0);
    Vector3D e1e2 = e1.cross(e2).normalize();

    Vector3D p = ray.direction.cross(e2);

    float a = e1.dot(p);
    if(a < 0.0)
        return -1.0f;

    float f = 1.0f / a;
    Vector3D s = ray.origin.sub(v0);
    float u = f*(s.dot(p));
    if(u < 0.0 || u > 1.0)
        return -1.0f; //no hit

    Vector3D q = s.cross(e1);
    float v = f * (ray.direction.dot(q));
    if(v < 0.0 || v > 1.0)
        return -1.0f; //no hit

    float t = f * (e2.dot(q)); //distance
    return t;
}

public Vector3D normal(Vector3D nVec){
    Vector3D e1 = v1.sub(v0);
    Vector3D e2 = v2.sub(v0);
    Vector3D e1e2 = e1.cross(e2).normalize();
    return e1e2;
}

So is this code correct?

2

2 Answers

1
votes

I honestly find your code rather hard to read because you don't use very descriptive names. I am going to give you what I did in pseudocode:

//1.Find intersection point of the ray and the infinite Plane created by triangle,
//or find if the ray is parralel to the plane (no intersection Point)
//2.Find out if the intersection point is within the triangle itself

Triangle: Vector A, Vector B, Vector C
ray: Vector rayOrig, Vector rayDir
Intersection: boolean hasHit = false, Vector hitPoint, float t

Vector normal = (B-A)CrossProduct(C-A) //I think you had basically the same with e1e2
float d = (normal)DotProduct(A)
float nd = (normal)DotProduct(rayDir)
if(nd!=0)
{    //The ray hits the triangles plane
    Intersection.t=(d- (normal).DotProduct(rayOrig))/nd
    Intersection.hitPoint=rayOrig+(rayDir*Intersection.t)
    if (pointInTriangle(Intersection.hitPoint, A, B, C))
    {
         Intersection.hasHit = true
    }
}
return Intersection

Notice that after getting the intersection point with the plane the function point in triangle is called, which should return a boolean. I got my method for that from: http://www.blackpawn.com/texts/pointinpoly/ using the second barycentric coordiantes, it looks like you are doing something similar in this part

if(u < 0.0 || u > 1.0)
    return -1.0f; //no hit

Vector3D q = s.cross(e1);
float v = f * (ray.direction.dot(q));
if(v < 0.0 || v > 1.0)
    return -1.0f; //no hit

It doesnt look like you are checking for ray plane intersection at all though, are you doing that in a different function? If that is the case, I dont think you actually need the rays direction for a triangle test.

1
votes

What you have implemented is the famous Möller-Trumbore intersection algorithm. The code is correct. If your code doesn't detect some this, it could be because it checks for backface culling. You can remove that test by changing the first if-test to if (a == 0.0f).

Also, on the fourth line, Vector3D e1e2 = e1.cross(e2).normalize();, you are calculating the triangle's plane's normal vector which is unnecessary.