1
votes

i want to implement the Moller & Trumbore algorithm, explained by

http://geomalgorithms.com/a06-_intersect-2.html

into my openframeworks project.

This is how my function looks

bool ofApp::intersectRayTriangle(Ray ray, Triangle triangle, ofVec3f* intersect) {

// u, v are triangle vectors - n is plane normal
ofVec3f u, v, n;

// ray vectors
ofVec3f w0, w;

// params to calc ray-plane intersect
float r, a, b;

u = triangle.v1 - triangle.v0;
u.normalize();

v = triangle.v2 - triangle.v0;  
v.normalize();

n = u.cross(v);
n.normalize();

if(n == ofVec3f(0.0f, 0.0f, 0.0f)) // triangle is degenerate
    return false;

w0 = ray.origin - triangle.v0;

a = -dot(n, w0);
b = dot(n, ray.direction);

if(fabs(b) < SMALL_NUM)
{
    if(a == 0.0f) 
        return false; // ray lies in triangle plane
    else       
        return false; // ray disjoint from plane
}

r = a / b;
if(r < 0.0f) 
    return false; // ray goes away from triangle

// intersect is the intersection point with the ray and the plane
*intersect = ray.origin + r * ray.direction;

// UNTIL HERE ITS ONLY PLANE INTERSECTION
//return true;

// Is plane intersection point inside the triangle?
float uu, uv, vv, wu, wv, D;

uu = dot(u,u);
uv = dot(u,v);
vv = dot(v,v);
w = *intersect - triangle.v0;
w.normalize();
wu = dot(w,u);
wv = dot(w,v);
D = uv * uv - uu * vv;

// get and test parametric coords
float s, t;
s = (uv * wv - vv * wu) / D;
if (s < 0.0f || s > 1.0f)         // I is outside T
    return false;
t = (uv * wu - uu * wv) / D;
if (t < 0.0f || (s + t) > 1.0f)  // I is outside T
    return false;

return true;                       // I is in T}

The first parts checks if the ray intersects the plane given by the triangle. The second part checks if the intersection points is inside the triangle to validate the triangle intersection.

My problem is, that the intersection point with the plane, which i get like

// intersect is the intersection point with the ray and the plane
*intersect = ray.origin + r * ray.direction;

is already wrong, while testing different plane intersecting rays bring me the right results with plane intersection if i return true right after...

I think about a normalize (or not normalize) error all the time, but im not sure about it.

The triangle has the coordinates:

triangle.v0 = ofVec3f(100.0, 50.0, 0.0);
triangle.v1 = ofVec3f(50.0, 150.0, 0.0);
triangle.v2 = ofVec3f(150.0, 150.0, 0.0);

and a ray, which should intersect

rayHit.origin = ofVec3f (100, 100, -100);
rayHit.direction = ofVec3f (1, 1, 1);

and a ray, which should NOT intersect

rayNoHit.origin = ofVec3f (200, 100, -100);
rayNoHit.direction = ofVec3f (1, 1, 1);

while a ray which not even goes through the plane validates me the functionality of intersecting the plane

rayNoPlaneHit.origin = ofVec3f(300, 100, -100);
rayNoPlaneHit.direction = ofVec3f(1, 1, 0);

I saw many different questions here about raycasting a triangle or plane, but i really think i got it already, only missing a little thing, which cost me hours already.

I would be so happy if somebody can help me. Thanks and best regards

2
Probably a sign error. The algorithm implements directed intersection so that only a ray hitting the triangle from the front will be registered; is that what you want? Also, the first ray will end up at (200,200,0), so it doesn't intersect the triangle.cfh
Not familiar with the algorithm, but don't you have to normalize w0?starmole

2 Answers

0
votes

There are two mistakes I can see: first, you specified the triangle in clockwise order, so its normal will point in negative z direction; the same direction that your ray points, so the hit will not register since the code checks for direction.

Second, your rayHit intersects the z plane at (200, 200, 0), so your assumption that it intersects the triangle is wrong.

0
votes

Thank you cfh for the correct hint that my rayHit intersects the z plane at (200,200,0). I did that wrong and rayHit has now the right direction rayHit.direction = ofVec3f (0, 0, 1);

Therefore i can validate the functionality of intersecting the triangle plane now!

But my algorithm still returns the result that my (also corrected)

rayNoHit.origin = ofVec3f (200, 100, -100);
rayNoHit.direction = ofVec3f (0, 0, 1);

also is inside the triangle and i still have the problem that i can't validate that the point is inside the triangle the right way. Do i have a error in the barycentric coordinates solution or do i miss something else in the lower part of the algorithm?