OPC_RayTriOverlap.h 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. #define LOCAL_EPSILON 0.000001f
  2. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  3. /**
  4. * Computes a ray-triangle intersection test.
  5. * Original code from Tomas Möller's "Fast Minimum Storage Ray-Triangle Intersection".
  6. * It's been optimized a bit with integer code, and modified to return a non-intersection if distance from
  7. * ray origin to triangle is negative.
  8. *
  9. * \param vert0 [in] triangle vertex
  10. * \param vert1 [in] triangle vertex
  11. * \param vert2 [in] triangle vertex
  12. * \return true on overlap. mStabbedFace is filled with relevant info.
  13. */
  14. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  15. inline_ BOOL RayCollider::RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2)
  16. {
  17. // Stats
  18. mNbRayPrimTests++;
  19. // Find vectors for two edges sharing vert0
  20. Point edge1 = vert1 - vert0;
  21. Point edge2 = vert2 - vert0;
  22. // Begin calculating determinant - also used to calculate U parameter
  23. Point pvec = mDir^edge2;
  24. // If determinant is near zero, ray lies in plane of triangle
  25. float det = edge1|pvec;
  26. if(mCulling)
  27. {
  28. if(det<LOCAL_EPSILON) return FALSE;
  29. // From here, det is > 0. So we can use integer cmp.
  30. // Calculate distance from vert0 to ray origin
  31. Point tvec = mOrigin - vert0;
  32. // Calculate U parameter and test bounds
  33. mStabbedFace.mU = tvec|pvec;
  34. // if(IR(u)&0x80000000 || u>det) return FALSE;
  35. if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IR(det)) return FALSE;
  36. // Prepare to test V parameter
  37. Point qvec = tvec^edge1;
  38. // Calculate V parameter and test bounds
  39. mStabbedFace.mV = mDir|qvec;
  40. if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>det) return FALSE;
  41. // Calculate t, scale parameters, ray intersects triangle
  42. mStabbedFace.mDistance = edge2|qvec;
  43. // Det > 0 so we can early exit here
  44. // Intersection point is valid if distance is positive (else it can just be a face behind the orig point)
  45. if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE;
  46. // Else go on
  47. float OneOverDet = 1.0f / det;
  48. mStabbedFace.mDistance *= OneOverDet;
  49. mStabbedFace.mU *= OneOverDet;
  50. mStabbedFace.mV *= OneOverDet;
  51. }
  52. else
  53. {
  54. // the non-culling branch
  55. if(det>-LOCAL_EPSILON && det<LOCAL_EPSILON) return FALSE;
  56. float OneOverDet = 1.0f / det;
  57. // Calculate distance from vert0 to ray origin
  58. Point tvec = mOrigin - vert0;
  59. // Calculate U parameter and test bounds
  60. mStabbedFace.mU = (tvec|pvec) * OneOverDet;
  61. // if(IR(u)&0x80000000 || u>1.0f) return FALSE;
  62. if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IEEE_1_0) return FALSE;
  63. // prepare to test V parameter
  64. Point qvec = tvec^edge1;
  65. // Calculate V parameter and test bounds
  66. mStabbedFace.mV = (mDir|qvec) * OneOverDet;
  67. if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>1.0f) return FALSE;
  68. // Calculate t, ray intersects triangle
  69. mStabbedFace.mDistance = (edge2|qvec) * OneOverDet;
  70. // Intersection point is valid if distance is positive (else it can just be a face behind the orig point)
  71. if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE;
  72. }
  73. return TRUE;
  74. }