0
\$\begingroup\$

I've implemented the Möller-Trumbore algorithm but I hit some false positive:

Ray: vec3(2.100000, -1.000000, 3.314214), vec3(0.685786, -1.000000, 1.900000)
Collide with: vec3(1.000000, 1.000000, -0.999999), vec3(0.999999, 1.000000, 1.000001), vec3(1.000000, -1.000000, 1.000000))
uvt=vec3(0.435307, 0.198000, -1.603999)

If I draw the collision, I see clearly that the ray does not intersect with the triangle.

From this site: http://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/moller-trumbore-ray-triangle-intersection I wrote this code:

bool Node::rayIntersectTriangleDebug(const glm::vec3 orig, glm::vec3 dir
                       , const glm::vec3 vert0, const glm::vec3 vert1, const glm::vec3 vert2
                       , glm::vec3 &result)
  {
    //dir = glm::normalize(dir);

    const glm::vec3 edge1 = vert1 - vert0;
    const glm::vec3 edge2 = vert2 - vert0;
    const glm::vec3 pvec = glm::cross(dir, edge2);
    const float det = glm::dot(edge1, pvec);

    const float Epsilon = std::numeric_limits<float>::epsilon();

    if (det > -Epsilon && det < Epsilon)
      return false;

    const float invDet = 1.0f / det;


    const glm::vec3 tvec = orig - vert0;

    result.x = glm::dot(tvec, pvec) * invDet;
    if (result.x < 0.0f || result.x > 1.0f)
      return false;

    const glm::vec3 qvec = glm::cross(tvec, edge1);

    result.y = glm::dot(dir, qvec) * invDet;
    if (result.y < 0.0f || result.x + result.y > 1.0f)
      return false;

    result.z = glm::dot(edge2, qvec) * invDet;

    const float abs = std::abs(result.z);
    const float dist = std::abs(glm::distance(orig, dir));

    const glm::vec3 intersection = vert0 + result.x * edge2 + result.y * edge1;

    if (abs < dist)
      {
         return true;
      }
     return false;
  }

Also I'm not sure if I have to normalize my direction vector.

EDIT

I've red here that

I'm not sure if it should be normalized or not, but tests I've conducted over a normalized version yelded valid results

I've tried to normalize my direction with the following code without success:

const glm::vec3 dir = glm::normalize(officialDirection - orig);
\$\endgroup\$
0
\$\begingroup\$

I though that the vector t could be positive if the ray faced the triangle or negative if the ray was in the back of the triangle but this is not true. It's positive if you are hitting the triangle and negative if not.

Here is the working implementation:

  bool Node::rayIntersectTriangleDebug(const glm::vec3 orig, const glm::vec3 dir
                       , const glm::vec3 vert0, const glm::vec3 vert1, const glm::vec3 vert2
                       , glm::vec3 &result)
  {
    const glm::vec3 edge1 = vert1 - vert0;
    const glm::vec3 edge2 = vert2 - vert0;
    const glm::vec3 pvec = glm::cross(dir, edge2);
    const float det = glm::dot(edge1, pvec);

    static const float Epsilon = std::numeric_limits<float>::epsilon();

    if (det > -Epsilon && det < Epsilon)
      return false;

    const float invDet = 1.0f / det;


    const glm::vec3 tvec = orig - vert0;

    result.x = glm::dot(tvec, pvec) * invDet;
    if (result.x < 0.0f || result.x > 1.0f)
      return false;

    const glm::vec3 qvec = glm::cross(tvec, edge1);

    result.y = glm::dot(dir, qvec) * invDet;
    if (result.y < 0.0f || result.x + result.y > 1.0f)
      return false;

    result.z = glm::dot(edge2, qvec) * invDet;

    const float abs = std::abs(result.z);
    const float dist = std::abs(glm::distance(orig, dir));
    const glm::vec3 intersection = vert0 + result.x * edge2 + result.y * edge1;


    if (result.z < Epsilon)
      return false;

    /* Convert the barycentric coordinate to wold Cartesian ones: */
    //const glm::vec3 intersection = vert0 + result.x * edge2 + result.y * edge1;


    return true;
  }

This implementation works and does not need to have a normalized direction. I convert barycentric coordinate to wold position with this formula:

const glm::vec3 intersection = vert0 + result.x * edge2 + result.y * edge1;
\$\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.