BsRay.cpp 3.1 KB

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