IntrOrientedBox2Cone2.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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/IntrRay2OrientedBox2.h>
  9. #include <Mathematics/Cone.h>
  10. // The queries consider the box and cone to be solids.
  11. //
  12. // Define V = cone.ray.origin, D = cone.ray.direction, and cs = cone.cosAngle.
  13. // Define C = box.center, U0 = box.axis[0], U1 = box.axis[1],
  14. // e0 = box.extent[0], and e1 = box.extent[1]. A box point is
  15. // P = C + x*U0 + y*U1 where |x| <= e0 and |y| <= e1. Define the function
  16. // F(P) = Dot(D, (P-V)/Length(P-V)) = F(x,y)
  17. // = Dot(D, (x*U0 + y*U1 + (C-V))/|x*U0 + y*U1 + (C-V)|
  18. // = (a0*x + a1*y + a2)/(x^2 + y^2 + 2*b0*x + 2*b1*y + b2)^{1/2}
  19. // The function has an essential singularity when P = V. The box intersects
  20. // the cone (with positive-area overlap) when at least one of the four box
  21. // corners is strictly inside the cone. It is necessary that the numerator
  22. // of F(P) be positive at such a corner. The (interior of the) solid cone
  23. // is defined by the quadratic inequality
  24. // (Dot(D,P-V))^2 > |P-V|^2*(cone.cosAngle)^2
  25. // This inequality is inexpensive to compute. In summary, overlap occurs
  26. // when there is a box corner P for which
  27. // F(P) > 0 and (Dot(D,P-V))^2 > |P-V|^2*(cone.cosAngle)^2
  28. namespace WwiseGTE
  29. {
  30. template <typename Real>
  31. class TIQuery<Real, OrientedBox<2, Real>, Cone<2, Real>>
  32. {
  33. public:
  34. struct Result
  35. {
  36. // The value of 'intersect' is true when there is a box point that
  37. // is strictly inside the cone. If the box just touches the cone
  38. // from the outside, an intersection is not reported, which
  39. // supports the common operation of culling objects outside a
  40. // cone.
  41. bool intersect;
  42. };
  43. Result operator()(OrientedBox<2, Real> const& box, Cone<2, Real>& cone)
  44. {
  45. Result result;
  46. TIQuery<Real, Ray<2, Real>, OrientedBox<2, Real>> rbQuery;
  47. auto rbResult = rbQuery(cone.ray, box);
  48. if (rbResult.intersect)
  49. {
  50. // The cone intersects the box.
  51. result.intersect = true;
  52. return result;
  53. }
  54. // Define V = cone.ray.origin, D = cone.ray.direction, and
  55. // cs = cone.cosAngle. Define C = box.center, U0 = box.axis[0],
  56. // U1 = box.axis[1], e0 = box.extent[0], and e1 = box.extent[1].
  57. // A box point is P = C + x*U0 + y*U1 where |x| <= e0 and
  58. // |y| <= e1. Define the function
  59. // F(x,y) = Dot(D, (P-V)/Length(P-V))
  60. // = Dot(D, (x*U0 + y*U1 + (C-V))/|x*U0 + y*U1 + (C-V)|
  61. // = (a0*x + a1*y + a2)/(x^2 + y^2 + 2*b0*x + 2*b1*y + b2)^{1/2}
  62. // The function has an essential singularity when P = V.
  63. Vector<2, Real> diff = box.center - cone.ray.origin;
  64. Real a0 = Dot(cone.ray.direction, box.axis[0]);
  65. Real a1 = Dot(cone.ray.direction, box.axis[1]);
  66. Real a2 = Dot(cone.ray.direction, diff);
  67. Real b0 = Dot(box.axis[0], diff);
  68. Real b1 = Dot(box.axis[1], diff);
  69. Real b2 = Dot(diff, diff);
  70. Real csSqr = cone.cosAngle * cone.cosAngle;
  71. for (int i1 = 0; i1 < 2; ++i1)
  72. {
  73. Real sign1 = i1 * (Real)2 - (Real)1;
  74. Real y = sign1 * box.extent[1];
  75. for (int i0 = 0; i0 < 2; ++i0)
  76. {
  77. Real sign0 = i0 * (Real)2 - (Real)1;
  78. Real x = sign0 * box.extent[0];
  79. Real fNumerator = a0 * x + a1 * y + a2;
  80. if (fNumerator > (Real)0)
  81. {
  82. Real dSqr = x * x + y * y + (b0 * x + b1 * y) * (Real)2 + b2;
  83. Real nSqr = fNumerator * fNumerator;
  84. if (nSqr > dSqr * csSqr)
  85. {
  86. result.intersect = true;
  87. return result;
  88. }
  89. }
  90. }
  91. }
  92. result.intersect = false;
  93. return result;
  94. }
  95. };
  96. }