bool intersect_ray_cylinder()

in packages/miew/src/gfx/shaders/Uber.frag [190:237]


  bool intersect_ray_cylinder(in vec3 origin, in vec3 ray, out vec3 point, out float frontFaced) {

    // intersect XZ-projected ray with circle
    float a = dot(ray.xz, ray.xz);
    float b = dot(ray.xz, origin.xz);
    float c = dot(origin.xz, origin.xz) - 1.0;
    float det = b * b - a * c;
    if (det < 0.0) return false;
    float t1 = (-b - sqrt(det)) / a;
    float t2 = (-b + sqrt(det)) / a;

    // calculate both intersection points
    vec3 p1 = origin + ray * t1;
    vec3 p2 = origin + ray * t2;

    float halfHeight = 0.5;

    // choose nearest point
    #ifdef ORTHOGRAPHIC_CAMERA
      // orthografic camera is used for dirLight sources. So in it for all cylinders the point with smaller 't' is visible
      // if it is not outside of cylinnder (t1 is always smaller than t2).
      if (p1.y >= -halfHeight && p1.y <= halfHeight) {
        point = p1;
        frontFaced = 1.0;
        return true;
      }
      if (p2.y >= -halfHeight && p2.y <= halfHeight) {
        point = p2;
        frontFaced = -1.0;
        return true;
      }
    #else
      // for perspective camera first intersection can be in front of near plane. If not intersection is p1 else - p2
      // t* = 0.0 corresponds to point of intersection near plane by the ray from camera to curPixel
      if (t1 >= 0.0 && p1.y >= -halfHeight && p1.y <= halfHeight) {
        point = p1;
        frontFaced = 1.0;
        return true;
      }
      if (t2 >= 0.0 && p2.y >= -halfHeight && p2.y <= halfHeight) {
        point = p2;
        frontFaced = -1.0;
        return true;
      }
    #endif

    return false;
  }