EstimateCollisionResponseTest.cpp 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2023 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include "UnitTestFramework.h"
  5. #include <Jolt/Physics/Collision/EstimateCollisionResponse.h>
  6. #include <Jolt/Physics/Collision/Shape/BoxShape.h>
  7. #include "PhysicsTestContext.h"
  8. #include "Layers.h"
  9. TEST_SUITE("EstimateCollisionResponseTests")
  10. {
  11. // Test CastShape ordering according to penetration depth
  12. TEST_CASE("TestEstimateCollisionResponse")
  13. {
  14. PhysicsTestContext c;
  15. c.ZeroGravity();
  16. const Vec3 cBox1HalfExtents(0.1f, 1, 2);
  17. const Vec3 cBox2HalfExtents(0.2f, 3, 4);
  18. // Test different motion types, restitution, positions and angular velocities
  19. for (EMotionType mt : { EMotionType::Static, EMotionType::Kinematic, EMotionType::Dynamic })
  20. for (float restitution : { 0.0f, 0.3f, 1.0f })
  21. for (float friction : { 0.0f, 0.3f, 1.0f })
  22. for (float y : { 0.0f, 0.5f, cBox2HalfExtents.GetY() })
  23. for (float z : { 0.0f, 0.5f, cBox2HalfExtents.GetZ() })
  24. for (float w : { 0.0f, -1.0f, 1.0f })
  25. {
  26. // Install a listener that predicts the collision response
  27. class MyListener : public ContactListener
  28. {
  29. public:
  30. virtual void OnContactAdded(const Body &inBody1, const Body &inBody2, const ContactManifold &inManifold, ContactSettings &ioSettings) override
  31. {
  32. EstimateCollisionResponse(inBody1, inBody2, inManifold, mResult, ioSettings.mCombinedFriction, ioSettings.mCombinedRestitution);
  33. }
  34. CollisionEstimationResult mResult;
  35. };
  36. MyListener listener;
  37. c.GetSystem()->SetContactListener(&listener);
  38. const RVec3 cBaseOffset(1, 2, 3);
  39. const Real cEpsilon = 0.0001_r;
  40. Body &box1 = c.CreateBox(cBaseOffset, Quat::sIdentity(), EMotionType::Dynamic, EMotionQuality::Discrete, Layers::MOVING, cBox1HalfExtents);
  41. box1.SetFriction(friction);
  42. box1.SetRestitution(restitution);
  43. box1.SetLinearVelocity(Vec3(1, 1, 0));
  44. box1.SetAngularVelocity(Vec3(0, w, 0));
  45. Body &box2 = c.CreateBox(cBaseOffset + RVec3(cBox1HalfExtents.GetX() + cBox2HalfExtents.GetX() - cEpsilon, y, z), Quat::sIdentity(), mt, EMotionQuality::Discrete, mt == EMotionType::Static? Layers::NON_MOVING : Layers::MOVING, cBox2HalfExtents);
  46. box2.SetFriction(friction);
  47. box2.SetRestitution(restitution);
  48. if (mt != EMotionType::Static)
  49. box2.SetLinearVelocity(Vec3(-1, 0, 0));
  50. // Step the simulation
  51. c.SimulateSingleStep();
  52. // Check that the predicted velocities are correct
  53. CHECK_APPROX_EQUAL(listener.mResult.mLinearVelocity1, box1.GetLinearVelocity());
  54. CHECK_APPROX_EQUAL(listener.mResult.mAngularVelocity1, box1.GetAngularVelocity());
  55. CHECK_APPROX_EQUAL(listener.mResult.mLinearVelocity2, box2.GetLinearVelocity());
  56. CHECK_APPROX_EQUAL(listener.mResult.mAngularVelocity2, box2.GetAngularVelocity());
  57. // Remove the bodies in reverse order
  58. BodyInterface &bi = c.GetBodyInterface();
  59. bi.RemoveBody(box2.GetID());
  60. bi.RemoveBody(box1.GetID());
  61. bi.DestroyBody(box2.GetID());
  62. bi.DestroyBody(box1.GetID());
  63. }
  64. }
  65. }