lighttransport / nanort

NanoRT, single header only modern ray tracing kernel.
MIT License
1.07k stars 89 forks source link

Questions about differences between paper + NanoRT for ray-triangle intersection #54

Closed Tyler799 closed 4 years ago

Tyler799 commented 4 years ago

I noticed that in the original paper, the following is done:

 /* Calculate scaled z-coordinates of vertices and use them to calculate hit
   * distance. */
  const float Az = Sz * A[kz];
  const float Bz = Sz * B[kz];
  const float Cz = Sz * C[kz];
  const float T = U * Az + V * Bz + W * Cz;

#ifdef BACKFACE_CULLING
  if (T < 0.0f || T > hit.t * det)
    return false;
#else
  int det_sign = sign_mask(det);
  if ((xorf(T, det_sign) < 0.0f) ||
      (xorf(T, det_sign) > (hit.t * xorf(det, det_sign))))
    return false;
#endif

  /* normalize U, V, W and T */
  hit.u = U * rcpDet;
  hit.v = V * rcpDet;
  hit.w = W * rcpDet;
  hit.t = T * rcpDet;

But in NanoRT, the following is done:

    const T Az = ray_coeff_.Sz * A[ray_coeff_.kz];
    const T Bz = ray_coeff_.Sz * B[ray_coeff_.kz];
    const T Cz = ray_coeff_.Sz * C[ray_coeff_.kz];
    const T D = U * Az + V * Bz + W * Cz;

    const T rcpDet = static_cast<T>(1.0) / det;
    T tt = D * rcpDet;

    if (tt > (*t_inout)) {
      return false;
    }

    if (tt < t_min_) {
      return false;
    }

    (*t_inout) = tt;
    // Use Möller-Trumbore style barycentric coordinates
    // U + V + W = 1.0 and interp(p) = U * p0 + V * p1 + W * p2
    // We want interp(p) = (1 - u - v) * p0 + u * v1 + v * p2;
    // => u = V, v = W.
    u_ = V * rcpDet;
    v_ = W * rcpDet;

    return true;

I am attempting to implement the algorithm from the paper myself, but am having some trouble understanding a few things.

1: Is multiplying by the inverse of the determinant somehow a way to convert from barycentric to Cartesian?

2: In the paper they have these "U, V, W" at the end. Is the idea that at the end of the algorithm, they leave the intersection point in barycentric form, rather than in Cartesian? If that's the case, what is happening at the end of NanoRT? What do u and v represent? And why is W not calculated?

3: If I want to know if I have an edge hit on a triangle, how do I tell?

syoyo commented 4 years ago

1: Is multiplying by the inverse of the determinant somehow a way to convert from barycentric to Cartesian?

No

2: In the paper they have these "U, V, W" at the end. Is the idea that at the end of the algorithm, they leave the intersection point in barycentric form, rather than in Cartesian? If that's the case, what is happening at the end of NanoRT? What do u and v represent? And why is W not calculated?

3: If I want to know if I have an edge hit on a triangle, how do I tell?

You can use your own intersector and intersection struct by template. See curves_primitive for example: https://github.com/lighttransport/nanort/tree/master/examples/curves_primitive