BsRay.cpp 2.9 KB

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