xelatihy / yocto-gl

Yocto/GL: Tiny C++ Libraries for Data-Driven Physically-based Graphics
https://xelatihy.github.io/yocto-gl
2.78k stars 203 forks source link

intersect_sphere always returns uv coordinates from the "back" of the sphere? #1431

Open tom7 opened 1 year ago

tom7 commented 1 year ago

I used intersect_sphere from yocto_geometry.h (and yocto_geometryt.h) in my project. I discovered that it only returns uv coordinates from the "back" of the sphere. I think is because there are two possible intersections for any ray, but the code does something strange (to me; I am not that good at 3D geometry, which is why I used the library; thanks!):

First it tries one intersection:

  // compute ray parameter
  auto t = (-b - sqrt(dis)) / (2 * a);

  // exit if not within bounds
  if (t < ray.tmin || t > ray.tmax) return {};

Then it tries the other intersection:

  // try other ray parameter
  t = (-b + sqrt(dis)) / (2 * a);

  // exit if not within bounds
  if (t < ray.tmin || t > ray.tmax) return {};

and then it computes the UV coordinates, but only for this second intersection:

  // compute local point for uvs
  auto plocal = ((ray.o + ray.d * t) - p) / r;
  auto u      = atan2(plocal.y, plocal.x) / (2 * pif);
  if (u < 0) u += 1;
  auto v = acos(clamp(plocal.z, -1.0f, 1.0f)) / pif;

  // intersection occurred: set params and exit
  return {{u, v}, t, true};

I fixed this for my own code by having two successful return paths (each computing the uv for that t) instead of two return {} paths, which works for me. I wasn't confident enough in my change to propose it (for one thing, the code above seems to require that both intersections are in the ray's interval, which I don't understand) but thought I'd mention it in case you also see this as a bug!

xelatihy commented 1 year ago

I'll look into this. Thanks.