EPATest.cpp 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #include <TestFramework.h>
  4. #include <Tests/ConvexCollision/EPATest.h>
  5. #include <Jolt/Geometry/Sphere.h>
  6. #include <Jolt/Geometry/AABox.h>
  7. #include <Jolt/Geometry/ConvexSupport.h>
  8. #include <Jolt/Geometry/EPAPenetrationDepth.h>
  9. #include <Renderer/DebugRendererImp.h>
  10. JPH_IMPLEMENT_RTTI_VIRTUAL(EPATest)
  11. {
  12. JPH_ADD_BASE_CLASS(EPATest, Test)
  13. }
  14. void EPATest::PrePhysicsUpdate(const PreUpdateParams &inParams)
  15. {
  16. AABox box(Vec3(1, 1, -2), Vec3(2, 2, 2));
  17. Sphere sphere(Vec3(4, 4, 0), sqrt(8.0f) + 0.01f);
  18. Mat44 matrix = Mat44::sRotationTranslation(Quat::sRotation(Vec3(1, 1, 1).Normalized(), 0.25f * JPH_PI), Vec3(1, 2, 3));
  19. bool intersecting = CollideBoxSphere(matrix, box, sphere);
  20. JPH_ASSERT(intersecting);
  21. (void)intersecting; // For when asserts are off
  22. }
  23. bool EPATest::CollideBoxSphere(Mat44Arg inMatrix, const AABox &inBox, const Sphere &inSphere) const
  24. {
  25. // Draw the box and shere
  26. mDebugRenderer->DrawBox(inMatrix, inBox, Color::sGrey);
  27. mDebugRenderer->DrawSphere(inMatrix * inSphere.GetCenter(), inSphere.GetRadius(), Color::sGrey);
  28. // Transform the box and sphere according to inMatrix
  29. TransformedConvexObject<AABox> transformed_box(inMatrix, inBox);
  30. TransformedConvexObject<Sphere> transformed_sphere(inMatrix, inSphere);
  31. // Run the EPA algorithm
  32. EPAPenetrationDepth epa;
  33. Vec3 v1 = Vec3::sAxisX(), pa1, pb1;
  34. bool intersect1 = epa.GetPenetrationDepth(transformed_box, transformed_box, 0.0f, transformed_sphere, transformed_sphere, 0.0f, 1.0e-2f, FLT_EPSILON, v1, pa1, pb1);
  35. // Draw iterative solution
  36. if (intersect1)
  37. {
  38. mDebugRenderer->DrawMarker(pa1, Color::sRed, 1.0f);
  39. mDebugRenderer->DrawMarker(pb1, Color::sGreen, 1.0f);
  40. mDebugRenderer->DrawArrow(pb1 + Vec3(0, 1, 0), pb1 + Vec3(0, 1, 0) + v1, Color::sYellow, 0.1f);
  41. }
  42. // Calculate analytical solution
  43. Vec3 pa2 = inBox.GetClosestPoint(inSphere.GetCenter());
  44. Vec3 v2 = inSphere.GetCenter() - pa2;
  45. bool intersect2 = v2.LengthSq() <= Square(inSphere.GetRadius());
  46. JPH_ASSERT(intersect1 == intersect2);
  47. if (intersect1 && intersect2)
  48. {
  49. Vec3 pb2 = inSphere.GetCenter() - inSphere.GetRadius() * v2.NormalizedOr(Vec3::sZero());
  50. // Transform analytical solution
  51. v2 = inMatrix.Multiply3x3(v2);
  52. pa2 = inMatrix * pa2;
  53. pb2 = inMatrix * pb2;
  54. // Draw analytical solution
  55. mDebugRenderer->DrawMarker(pa2, Color::sOrange, 1.0f);
  56. mDebugRenderer->DrawMarker(pb2, Color::sYellow, 1.0f);
  57. // Check angle between v1 and v2
  58. float dot = v1.Dot(v2);
  59. float len = v1.Length() * v2.Length();
  60. float angle = RadiansToDegrees(ACos(dot / len));
  61. JPH_ASSERT(angle < 0.1f);
  62. Trace("Angle = %.9g", (double)angle);
  63. // Check delta between contact on A
  64. Vec3 dpa = pa2 - pa1;
  65. JPH_ASSERT(dpa.IsNearZero(Square(8.0e-4f)));
  66. Trace("Delta A = %.9g", (double)dpa.Length());
  67. // Check delta between contact on B
  68. Vec3 dpb = pb2 - pb1;
  69. JPH_ASSERT(dpb.IsNearZero(Square(8.0e-4f)));
  70. Trace("Delta B = %.9g", (double)dpb.Length());
  71. }
  72. return intersect1;
  73. }