rayEllipsoidIntersectionInterval.glsl 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /**
  2. * DOC_TBA
  3. *
  4. * @name czm_rayEllipsoidIntersectionInterval
  5. * @glslFunction
  6. */
  7. czm_raySegment czm_rayEllipsoidIntersectionInterval(czm_ray ray, vec3 ellipsoid_center, vec3 ellipsoid_inverseRadii)
  8. {
  9. // ray and ellipsoid center in eye coordinates. radii in model coordinates.
  10. vec3 q = ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ray.origin, 1.0)).xyz;
  11. vec3 w = ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ray.direction, 0.0)).xyz;
  12. q = q - ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ellipsoid_center, 1.0)).xyz;
  13. float q2 = dot(q, q);
  14. float qw = dot(q, w);
  15. if (q2 > 1.0) // Outside ellipsoid.
  16. {
  17. if (qw >= 0.0) // Looking outward or tangent (0 intersections).
  18. {
  19. return czm_emptyRaySegment;
  20. }
  21. else // qw < 0.0.
  22. {
  23. float qw2 = qw * qw;
  24. float difference = q2 - 1.0; // Positively valued.
  25. float w2 = dot(w, w);
  26. float product = w2 * difference;
  27. if (qw2 < product) // Imaginary roots (0 intersections).
  28. {
  29. return czm_emptyRaySegment;
  30. }
  31. else if (qw2 > product) // Distinct roots (2 intersections).
  32. {
  33. float discriminant = qw * qw - product;
  34. float temp = -qw + sqrt(discriminant); // Avoid cancellation.
  35. float root0 = temp / w2;
  36. float root1 = difference / temp;
  37. if (root0 < root1)
  38. {
  39. czm_raySegment i = czm_raySegment(root0, root1);
  40. return i;
  41. }
  42. else
  43. {
  44. czm_raySegment i = czm_raySegment(root1, root0);
  45. return i;
  46. }
  47. }
  48. else // qw2 == product. Repeated roots (2 intersections).
  49. {
  50. float root = sqrt(difference / w2);
  51. czm_raySegment i = czm_raySegment(root, root);
  52. return i;
  53. }
  54. }
  55. }
  56. else if (q2 < 1.0) // Inside ellipsoid (2 intersections).
  57. {
  58. float difference = q2 - 1.0; // Negatively valued.
  59. float w2 = dot(w, w);
  60. float product = w2 * difference; // Negatively valued.
  61. float discriminant = qw * qw - product;
  62. float temp = -qw + sqrt(discriminant); // Positively valued.
  63. czm_raySegment i = czm_raySegment(0.0, temp / w2);
  64. return i;
  65. }
  66. else // q2 == 1.0. On ellipsoid.
  67. {
  68. if (qw < 0.0) // Looking inward.
  69. {
  70. float w2 = dot(w, w);
  71. czm_raySegment i = czm_raySegment(0.0, -qw / w2);
  72. return i;
  73. }
  74. else // qw >= 0.0. Looking outward or tangent.
  75. {
  76. return czm_emptyRaySegment;
  77. }
  78. }
  79. }