4

I am using the Möller-Trumbore method as part of my (still very basic) collision detection system.

The information I'm craving about is the distance from the ray origin and intersection point. The intersection point would be fine too obviously.

I probably wrongly assumed t in the code below is actually the distance from the ray origin to the intersection point. If it actually is, then I don't know what's wrong with my code.

I have got a simulation with a mesh and "bullets", sometimes firing a collision acurately, and sometimes not (bullets passing thru mesh, or firing a colision before it actually should hit).

bool rayTriangleIntersect(const XMFLOAT3 &orig, const XMFLOAT3 &dir, const XMFLOAT3 &v0, const XMFLOAT3 &v1, const XMFLOAT3 &v2, float &t, float &u, float &v) {
// http://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/moller-trumbore-ray-triangle-intersection

    float kEpsilon = 0.000001f;
    XMFLOAT3 v0v1 = v1 - v0;
    XMFLOAT3 v0v2 = v2 - v0;
    XMFLOAT3 pvec = XMFLOAT3Cross(dir, v0v2);

    float det = XMFLOAT3Dot(v0v1, pvec);

    if (det < kEpsilon) return false;

    float invDet = 1.0f / det;

    XMFLOAT3 tvec = orig - v0;
    u = XMFLOAT3Dot(tvec, pvec) * invDet;
    if (u < 0 || u > 1) return false;

    XMFLOAT3 qvec = XMFLOAT3Cross(tvec, v0v1);
    v = XMFLOAT3Dot(dir, qvec) * invDet;
    if (v < 0 || u + v > 1) return false;

    t = XMFLOAT3Dot(v0v2, qvec) * invDet;

    return true;
}

Is t really the distance im looking for ? If not how do I get it, or the intersection point. I've heard of baricentric coordinates in a triangle related to u and v - is it the way to go ? If yes I'd be thankful for an example or link related to the Möller-Trumbore method.

Thanks!

PinkTurtle
  • 247
  • 4
  • 22

2 Answers2

2

One issue with your implementation is that you only check if det is smaller kEpsilon, but there is no guarantee that det is positive. You want to check

if(det<kEpsilon && det>-kEpsilon)

So that might explain the false positives. The way this algorithm works is by basically figuring out "when" the ray will hit the triangles plane and then checking if the position of the ray at that time is inside the triangle by transforming into barycentric coordinates.

You should be able to calculate the intersection point as:

intersection = v0+u*v0v2+v*v0v1;

That being said t should be the distance you are looking for anyway, so you might have an implementation problem.

There seems to be an excellent explanation here: http://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/moller-trumbore-ray-triangle-intersection

Nils Ole Timm
  • 1,775
  • 1
  • 11
  • 12
  • I thought det is positive when the ray is facing the visible (not culled) face of a triangle ? That is why I stripped checking det's sign. – PinkTurtle Jan 22 '16 at 10:36
  • It is, or should be depending on the orientation of your triangles. The sign definitely determines which side it's on. – Nils Ole Timm Jan 22 '16 at 11:22
  • Something is wrong in my implementation - I didn't figure out what yet. To detect a collision I'm asserting that the distance from a vertex last position to vertex current position must be bigger than t, with the ray given by both positions hitting the triangle obviously. Digging :) – PinkTurtle Jan 22 '16 at 11:27
  • An easy way to test this would be to draw the ray you are testing as well as the result from your intersection test. – Nils Ole Timm Jan 22 '16 at 11:32
  • Yes good point! The ray is easy to figure out as it's the path of my bullet - I'll see if I can display the hit location. – PinkTurtle Jan 22 '16 at 11:41
  • Well I don't know what is happening my collisions are completely inacurate. Displaying them gives me hitpoints popping pretty much everywhere into triangles that are not at all in line with my ray direction aka bullet linear route. How can M-T return true I don't know. My pseudo code being : for a 1D point/bullet moving in a straight direction, start detecting a collision if point inside model AABB, then check if point inside any model sub-mesh AABB then check if point inside any mesh subspace AABB. For each tri inside subspace AABB, do Möller-Trumbore. What's wrong with that ? :( – PinkTurtle Jan 22 '16 at 16:03
  • Pseudo code for deciding a collision actually occurs being : M-T must return true and current position minus last position is > than last position to intersection point (aka t). – PinkTurtle Jan 22 '16 at 16:04
  • Well, you should probably build a test case with just one triangle. See when it tells you there's a collision and when it doesn't. And if you find a case where things clearly go wrong step through the code and see when the values mess up. I don't think I can give better advice than that without looking at way more code. Sorry. – Nils Ole Timm Jan 22 '16 at 17:29
  • 1
    Yo I switched from XMFLOAT data types with homemade cross and dot products to XMVECTOR and MS implemented methods. Now things look all right. Not sure where I failed but thanks for the help so far! I must have screwed my 3D math ;p – PinkTurtle Jan 22 '16 at 21:15
  • Glad to hear it's working now – Nils Ole Timm Jan 23 '16 at 01:43
  • Yes issue wasn't much with MT code actually. Didn't take time to dig what actually was causing it all to glitch. Something with handling XMFLOAT types VS XMVECTORs. – PinkTurtle Jan 23 '16 at 01:46
1

A standard parametric ray equation is r(t) = p + td. The origin point is p and d is the ray direction. So, that algorithm gives you t and you know p and d already. Therefore you can compute ray (or vector) r(t), and then take its magnitude |r(t)| to obtain the distance to triangle (intersection).

PS. You may need to normalize your direction vector d first. That is, ensure its of unit length. (The link you provided isn't clear if that's necessary though.)

zx6r
  • 11
  • 1