IntrRay3Cone3.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/Ray.h>
  9. #include <Mathematics/IntrLine3Cone3.h>
  10. // The queries consider the cone to be single sided and solid. The
  11. // cone height range is [hmin,hmax]. The cone can be infinite where
  12. // hmin = 0 and hmax = +infinity, infinite truncated where hmin > 0
  13. // and hmax = +infinity, finite where hmin = 0 and hmax < +infinity,
  14. // or a cone frustum where hmin > 0 and hmax < +infinity. The
  15. // algorithm details are found in
  16. // https://www.geometrictools.com/Documentation/IntersectionLineCone.pdf
  17. namespace WwiseGTE
  18. {
  19. template <typename Real>
  20. class FIQuery<Real, Ray3<Real>, Cone3<Real>>
  21. :
  22. public FIQuery<Real, Line3<Real>, Cone3<Real>>
  23. {
  24. public:
  25. struct Result
  26. :
  27. public FIQuery<Real, Line3<Real>, Cone3<Real>>::Result
  28. {
  29. // No additional information to compute.
  30. };
  31. Result operator()(Ray3<Real> const& ray, Cone3<Real> const& cone)
  32. {
  33. // Execute the line-cone query.
  34. Result result;
  35. this->DoQuery(ray.origin, ray.direction, cone, result);
  36. // Adjust the t-interval depending on whether the line-cone
  37. // t-interval overlaps the ray interval [0,+infinity). The block
  38. // numbers are a continuation of those in IntrLine3Cone3.h.
  39. if (result.type != Result::isEmpty)
  40. {
  41. using QFN1 = typename FIQuery<Real, Line3<Real>, Cone3<Real>>::QFN1;
  42. QFN1 zero(0, 0, result.t[0].d);
  43. if (result.type == Result::isPoint)
  44. {
  45. if (result.t[0] < zero)
  46. {
  47. // Block 12.
  48. this->SetEmpty(result);
  49. }
  50. // else: Block 13.
  51. }
  52. else if (result.type == Result::isSegment)
  53. {
  54. if (result.t[1] > zero)
  55. {
  56. // Block 14.
  57. this->SetSegment(std::max(result.t[0], zero), result.t[1], result);
  58. }
  59. else if (result.t[1] < zero)
  60. {
  61. // Block 15.
  62. this->SetEmpty(result);
  63. }
  64. else // result.t[1] == zero
  65. {
  66. // Block 16.
  67. this->SetPoint(zero, result);
  68. }
  69. }
  70. else if (result.type == Result::isRayPositive)
  71. {
  72. // Block 17.
  73. this->SetRayPositive(std::max(result.t[0], zero), result);
  74. }
  75. else // result.type == Result::isRayNegative
  76. {
  77. if (result.t[1] > zero)
  78. {
  79. // Block 18.
  80. this->SetSegment(zero, result.t[1], result);
  81. }
  82. else if (result.t[1] < zero)
  83. {
  84. // Block 19.
  85. this->SetEmpty(result);
  86. }
  87. else // result.t[1] == zero
  88. {
  89. // Block 20.
  90. this->SetPoint(zero, result);
  91. }
  92. }
  93. }
  94. result.ComputePoints(ray.origin, ray.direction);
  95. result.intersect = (result.type != Result::isEmpty);
  96. return result;
  97. }
  98. };
  99. }