CmRay.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include "CmRay.h"
  2. #include "CmPlane.h"
  3. #include "CmSphere.h"
  4. #include "CmAABox.h"
  5. namespace CamelotFramework
  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. //
  24. // Calculate intersection with plane.
  25. //
  26. float t;
  27. {
  28. float denom = normal.dot(getDirection());
  29. // Check intersect side
  30. if (denom > + std::numeric_limits<float>::epsilon())
  31. {
  32. if (!negativeSide)
  33. return std::pair<bool, float>(false, 0.0f);
  34. }
  35. else if (denom < - std::numeric_limits<float>::epsilon())
  36. {
  37. if (!positiveSide)
  38. return std::pair<bool, float>(false, 0.0f);
  39. }
  40. else
  41. {
  42. // Parallel or triangle area is close to zero when
  43. // the plane normal not normalised.
  44. return std::pair<bool, float>(false, 0.0f);
  45. }
  46. t = normal.dot(a - getOrigin()) / denom;
  47. if (t < 0)
  48. {
  49. // Intersection is behind origin
  50. return std::pair<bool, float>(false, 0.0f);
  51. }
  52. }
  53. //
  54. // Calculate the largest area projection plane in X, Y or Z.
  55. //
  56. size_t i0, i1;
  57. {
  58. float n0 = Math::abs(normal[0]);
  59. float n1 = Math::abs(normal[1]);
  60. float n2 = Math::abs(normal[2]);
  61. i0 = 1; i1 = 2;
  62. if (n1 > n2)
  63. {
  64. if (n1 > n0) i0 = 0;
  65. }
  66. else
  67. {
  68. if (n2 > n0) i1 = 0;
  69. }
  70. }
  71. //
  72. // Check the intersection point is inside the triangle.
  73. //
  74. {
  75. float u1 = b[i0] - a[i0];
  76. float v1 = b[i1] - a[i1];
  77. float u2 = c[i0] - a[i0];
  78. float v2 = c[i1] - a[i1];
  79. float u0 = t * getDirection()[i0] + getOrigin()[i0] - a[i0];
  80. float v0 = t * getDirection()[i1] + getOrigin()[i1] - a[i1];
  81. float alpha = u0 * v2 - u2 * v0;
  82. float beta = u1 * v0 - u0 * v1;
  83. float area = u1 * v2 - u2 * v1;
  84. // epsilon to avoid float precision error
  85. const float EPSILON = 1e-6f;
  86. float tolerance = - EPSILON * area;
  87. if (area > 0)
  88. {
  89. if (alpha < tolerance || beta < tolerance || alpha+beta > area-tolerance)
  90. return std::pair<bool, float>(false, 0.0f);
  91. }
  92. else
  93. {
  94. if (alpha > tolerance || beta > tolerance || alpha+beta < area-tolerance)
  95. return std::pair<bool, float>(false, 0.0f);
  96. }
  97. }
  98. return std::pair<bool, float>(true, t);
  99. }
  100. }