BsRay.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #include "BsRay.h"
  2. #include "BsPlane.h"
  3. #include "BsSphere.h"
  4. #include "BsAABox.h"
  5. namespace BansheeEngine
  6. {
  7. std::pair<bool, float> Ray::intersects(const Plane& p) const
  8. {
  9. return p.intersects(*this);
  10. }
  11. std::pair<bool, float> Ray::intersects(const Sphere& s) const
  12. {
  13. return s.intersects(*this);
  14. }
  15. std::pair<bool, float> Ray::intersects(const AABox& box) const
  16. {
  17. return box.intersects(*this);
  18. }
  19. std::pair<bool, float> Ray::intersects(const Vector3& a,
  20. const Vector3& b, const Vector3& c, const Vector3& normal,
  21. bool positiveSide, bool negativeSide) const
  22. {
  23. // Calculate intersection with plane.
  24. float t;
  25. {
  26. float denom = normal.dot(getDirection());
  27. // Check intersect side
  28. if (denom > + std::numeric_limits<float>::epsilon())
  29. {
  30. if (!negativeSide)
  31. return std::pair<bool, float>(false, 0.0f);
  32. }
  33. else if (denom < - std::numeric_limits<float>::epsilon())
  34. {
  35. if (!positiveSide)
  36. return std::pair<bool, float>(false, 0.0f);
  37. }
  38. else
  39. {
  40. // Parallel or triangle area is close to zero when
  41. // the plane normal not normalized.
  42. return std::pair<bool, float>(false, 0.0f);
  43. }
  44. t = normal.dot(a - getOrigin()) / denom;
  45. if (t < 0)
  46. {
  47. // Intersection is behind origin
  48. return std::pair<bool, float>(false, 0.0f);
  49. }
  50. }
  51. // Calculate the largest area projection plane in X, Y or Z.
  52. UINT32 i0, i1;
  53. {
  54. float n0 = Math::abs(normal[0]);
  55. float n1 = Math::abs(normal[1]);
  56. float n2 = Math::abs(normal[2]);
  57. i0 = 1; i1 = 2;
  58. if (n1 > n2)
  59. {
  60. if (n1 > n0) i0 = 0;
  61. }
  62. else
  63. {
  64. if (n2 > n0) i1 = 0;
  65. }
  66. }
  67. // Check the intersection point is inside the triangle.
  68. {
  69. float u1 = b[i0] - a[i0];
  70. float v1 = b[i1] - a[i1];
  71. float u2 = c[i0] - a[i0];
  72. float v2 = c[i1] - a[i1];
  73. float u0 = t * getDirection()[i0] + getOrigin()[i0] - a[i0];
  74. float v0 = t * getDirection()[i1] + getOrigin()[i1] - a[i1];
  75. float alpha = u0 * v2 - u2 * v0;
  76. float beta = u1 * v0 - u0 * v1;
  77. float area = u1 * v2 - u2 * v1;
  78. // Epsilon to avoid float precision errors.
  79. const float EPSILON = 1e-6f;
  80. float tolerance = - EPSILON * area;
  81. if (area > 0)
  82. {
  83. if (alpha < tolerance || beta < tolerance || alpha+beta > area-tolerance)
  84. return std::pair<bool, float>(false, 0.0f);
  85. }
  86. else
  87. {
  88. if (alpha > tolerance || beta > tolerance || alpha+beta < area-tolerance)
  89. return std::pair<bool, float>(false, 0.0f);
  90. }
  91. }
  92. return std::pair<bool, float>(true, t);
  93. }
  94. }