MathUtils.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #include "MathUtils.h"
  2. #include "Sphere.h"
  3. USING_NS_BF;
  4. bool Beefy::RayIntersectsTriangle(const Vector3& rayOrigin, const Vector3& rayVector, const Vector3& vtx0, const Vector3& vtx1, const Vector3& vtx2, Vector3* outIntersectionPoint, float* outDistance)
  5. {
  6. const float EPSILON = 0.0000001f;
  7. Vector3 edge1, edge2, h, s, q;
  8. float a, f, u, v;
  9. edge1 = vtx1 - vtx0;
  10. edge2 = vtx2 - vtx0;
  11. h = Vector3::CrossProduct(rayVector, edge2);//rayVector.crossProduct(edge2);
  12. a = Vector3::Dot(edge1, h); //edge1.dotProduct(h);
  13. if (a > -EPSILON && a < EPSILON)
  14. return false; // This ray is parallel to this triangle.
  15. f = 1.0f / a;
  16. s = rayOrigin - vtx0;
  17. u = f * Vector3::Dot(s, h); //s.dotProduct(h);
  18. if (u < 0.0 || u > 1.0)
  19. return false;
  20. q = Vector3::CrossProduct(s, edge1); //s.crossProduct(edge1);
  21. v = f * Vector3::Dot(rayVector, q); //rayVector.dotProduct(q);
  22. if (v < 0.0 || u + v > 1.0)
  23. return false;
  24. // At this stage we can compute t to find out where the intersection point is on the line.
  25. float distance = f * Vector3::Dot(edge2, q); //edge2.dotProduct(q);
  26. if (distance > EPSILON) // ray intersection
  27. {
  28. if (outIntersectionPoint != NULL)
  29. *outIntersectionPoint = rayOrigin + rayVector * distance;
  30. if (outDistance != NULL)
  31. *outDistance = distance;
  32. return true;
  33. }
  34. else // This means that there is a line intersection but not a ray intersection.
  35. return false;
  36. }
  37. bool Beefy::RayIntersectsCircle(const Vector3& rayOrigin, const Vector3& rayVector, const Sphere& sphere, Vector3* outIntersectionPoint, Vector3* outNormal, float* outDistance)
  38. {
  39. Vector3 e = sphere.mCenter - rayOrigin;
  40. float rSq = sphere.mRadius * sphere.mRadius;
  41. float eSq = e.GetMagnitudeSquare();
  42. float a = Vector3::Dot(e, rayVector); // ray.direction is assumed to be normalized
  43. float bSq = /*sqrtf(*/eSq - (a * a)/*)*/;
  44. float f = sqrtf(fabsf((rSq)- /*(b * b)*/bSq));
  45. // Assume normal intersection!
  46. float t = a - f;
  47. // No collision has happened
  48. if (rSq - (eSq - a * a) < 0.0f)
  49. {
  50. return false;
  51. }
  52. // Ray starts inside the sphere
  53. else if (eSq < rSq)
  54. {
  55. // Just reverse direction
  56. t = a + f;
  57. }
  58. if (outDistance != NULL)
  59. *outDistance = t;
  60. if ((outIntersectionPoint != NULL) || (outNormal != NULL))
  61. {
  62. Vector3 intersect = rayOrigin + rayVector * t;
  63. if (outIntersectionPoint != NULL)
  64. *outIntersectionPoint = intersect;
  65. if (outNormal != NULL)
  66. *outNormal = Vector3::Normalize(intersect - sphere.mCenter);
  67. }
  68. return true;
  69. }
  70. bool Beefy::RayIntersectsAABB(const Vector3& rayOrigin, const Vector3& rayVector, const AABB& aabb, Vector3* outIntersectionPoint, Vector3* outNormal, float* outDistance)
  71. {
  72. const Vector3& min = aabb.mMin;
  73. const Vector3& max = aabb.mMax;
  74. // Any component of direction could be 0!
  75. // Address this by using a small number, close to
  76. // 0 in case any of directions components are 0
  77. float t1 = (min.mX - rayOrigin.mX) / ((fabs(rayVector.mX) < 0.00001f) ? 0.00001f : rayVector.mX);
  78. float t2 = (max.mX - rayOrigin.mX) / ((fabs(rayVector.mX) < 0.00001f) ? 0.00001f : rayVector.mX);
  79. float t3 = (min.mY - rayOrigin.mY) / ((fabs(rayVector.mY) < 0.00001f) ? 0.00001f : rayVector.mY);
  80. float t4 = (max.mY - rayOrigin.mY) / ((fabs(rayVector.mY) < 0.00001f) ? 0.00001f : rayVector.mY);
  81. float t5 = (min.mZ - rayOrigin.mZ) / ((fabs(rayVector.mZ) < 0.00001f) ? 0.00001f : rayVector.mZ);
  82. float t6 = (max.mZ - rayOrigin.mZ) / ((fabs(rayVector.mZ) < 0.00001f) ? 0.00001f : rayVector.mZ);
  83. float tmin = fmaxf(fmaxf(fminf(t1, t2), fminf(t3, t4)), fminf(t5, t6));
  84. float tmax = fminf(fminf(fmaxf(t1, t2), fmaxf(t3, t4)), fmaxf(t5, t6));
  85. // if tmax < 0, ray is intersecting AABB
  86. // but entire AABB is being it's origin
  87. if (tmax < 0) {
  88. return false;
  89. }
  90. // if tmin > tmax, ray doesn't intersect AABB
  91. if (tmin > tmax) {
  92. return false;
  93. }
  94. float t_result = tmin;
  95. // If tmin is < 0, tmax is closer
  96. if (tmin < 0.0f) {
  97. t_result = tmax;
  98. }
  99. if ((outIntersectionPoint != NULL) || (outDistance != NULL))
  100. {
  101. Vector3 hitPoint = rayOrigin + rayVector * t_result;
  102. if (outIntersectionPoint != NULL)
  103. *outIntersectionPoint = hitPoint;
  104. if (outDistance != NULL)
  105. *outDistance = (rayOrigin - hitPoint).GetMagnitude();
  106. }
  107. if (outNormal != NULL)
  108. {
  109. static Vector3 normals[] = {
  110. Vector3(-1, 0, 0),
  111. Vector3(1, 0, 0),
  112. Vector3(0, -1, 0),
  113. Vector3(0, 1, 0),
  114. Vector3(0, 0, -1),
  115. Vector3(0, 0, 1)
  116. };
  117. float t[] = { t1, t2, t3, t4, t5, t6 };
  118. for (int i = 0; i < 6; ++i)
  119. {
  120. if (t_result == t[i])
  121. *outNormal = normals[i];
  122. }
  123. }
  124. return true;
  125. }