RayTriangle8.h 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. #include <Jolt/Math/Vec8.h>
  6. JPH_NAMESPACE_BEGIN
  7. /// Intersect ray with 8 triangles in SOA format, returns 8 vector of closest points or FLT_MAX if no hit
  8. JPH_INLINE Vec8 RayTriangle8(Vec3Arg inOrigin, Vec3Arg inDirection, Vec8Arg inV0X, Vec8Arg inV0Y, Vec8Arg inV0Z, Vec8Arg inV1X, Vec8Arg inV1Y, Vec8Arg inV1Z, Vec8Arg inV2X, Vec8Arg inV2Y, Vec8Arg inV2Z)
  9. {
  10. // Epsilon
  11. Vec8 epsilon = Vec8::sReplicate(1.0e-12f);
  12. // Zero & one
  13. Vec8 zero = Vec8::sZero();
  14. Vec8 one = Vec8::sReplicate(1.0f);
  15. // Find vectors for two edges sharing inV0
  16. Vec8 e1x = inV1X - inV0X;
  17. Vec8 e1y = inV1Y - inV0Y;
  18. Vec8 e1z = inV1Z - inV0Z;
  19. Vec8 e2x = inV2X - inV0X;
  20. Vec8 e2y = inV2Y - inV0Y;
  21. Vec8 e2z = inV2Z - inV0Z;
  22. // Get direction vector components
  23. Vec8 dx = Vec8::sSplatX(Vec4(inDirection));
  24. Vec8 dy = Vec8::sSplatY(Vec4(inDirection));
  25. Vec8 dz = Vec8::sSplatZ(Vec4(inDirection));
  26. // Begin calculating determinant - also used to calculate u parameter
  27. Vec8 px = dy * e2z - dz * e2y;
  28. Vec8 py = dz * e2x - dx * e2z;
  29. Vec8 pz = dx * e2y - dy * e2x;
  30. // if determinant is near zero, ray lies in plane of triangle
  31. Vec8 det = e1x * px + e1y * py + e1z * pz;
  32. // Check which determinants are near zero
  33. UVec8 det_near_zero = Vec8::sLess(det.Abs(), epsilon);
  34. // Set components of the determinant to 1 that are near zero to avoid dividing by zero
  35. det = Vec8::sSelect(det, Vec8::sReplicate(1.0f), det_near_zero);
  36. // Calculate distance from inV0 to ray origin
  37. Vec8 sx = Vec8::sSplatX(Vec4(inOrigin)) - inV0X;
  38. Vec8 sy = Vec8::sSplatY(Vec4(inOrigin)) - inV0Y;
  39. Vec8 sz = Vec8::sSplatZ(Vec4(inOrigin)) - inV0Z;
  40. // Calculate u parameter and flip sign if determinant was negative
  41. Vec8 u = (sx * px + sy * py + sz * pz) / det;
  42. // Prepare to test v parameter
  43. Vec8 qx = sy * e1z - sz * e1y;
  44. Vec8 qy = sz * e1x - sx * e1z;
  45. Vec8 qz = sx * e1y - sy * e1x;
  46. // Calculate v parameter and flip sign if determinant was negative
  47. Vec8 v = (dx * qx + dy * qy + dz * qz) / det;
  48. // Get intersection point and flip sign if determinant was negative
  49. Vec8 t = (e2x * qx + e2y * qy + e2z * qz) / det;
  50. // Check if there is an intersection
  51. UVec8 no_intersection =
  52. UVec8::sOr
  53. (
  54. UVec8::sOr
  55. (
  56. UVec8::sOr
  57. (
  58. det_near_zero,
  59. Vec8::sLess(u, zero)
  60. ),
  61. UVec8::sOr
  62. (
  63. Vec8::sLess(v, zero),
  64. Vec8::sGreater(u + v, one)
  65. )
  66. ),
  67. Vec8::sLess(t, zero)
  68. );
  69. // Select intersection point or FLT_MAX based on if there is an intersection or not
  70. return Vec8::sSelect(t, Vec8::sReplicate(FLT_MAX), no_intersection);
  71. }
  72. JPH_NAMESPACE_END