BsRay.cpp 2.8 KB

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