SoftBodyContactListenerTest.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2024 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <TestFramework.h>
  5. #include <Tests/SoftBody/SoftBodyContactListenerTest.h>
  6. #include <Jolt/Physics/Body/BodyCreationSettings.h>
  7. #include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
  8. #include <Jolt/Physics/SoftBody/SoftBodyManifold.h>
  9. #include <Jolt/Physics/Collision/Shape/SphereShape.h>
  10. #include <Utils/SoftBodyCreator.h>
  11. #include <Renderer/DebugRendererImp.h>
  12. #include <Layers.h>
  13. JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyContactListenerTest)
  14. {
  15. JPH_ADD_BASE_CLASS(SoftBodyContactListenerTest, Test)
  16. }
  17. void SoftBodyContactListenerTest::Initialize()
  18. {
  19. // Install contact listener for soft bodies
  20. mPhysicsSystem->SetSoftBodyContactListener(this);
  21. // Floor
  22. CreateFloor();
  23. // Start the 1st cycle
  24. StartCycle();
  25. }
  26. void SoftBodyContactListenerTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
  27. {
  28. mTime += inParams.mDeltaTime;
  29. if (mTime > 2.5f)
  30. {
  31. // Next cycle
  32. mCycle = (mCycle + 1) % 7;
  33. mTime = 0.0f;
  34. // Remove the old scene
  35. mBodyInterface->RemoveBody(mOtherBodyID);
  36. mBodyInterface->DestroyBody(mOtherBodyID);
  37. mBodyInterface->RemoveBody(mSoftBodyID);
  38. mBodyInterface->DestroyBody(mSoftBodyID);
  39. // Start the new
  40. StartCycle();
  41. }
  42. // Draw current state
  43. const char *cycle_names[] = { "Accept contact", "Sphere 10x mass", "Cloth 10x mass", "Sphere infinite mass", "Cloth infinite mass", "Sensor contact", "Reject contact" };
  44. mDebugRenderer->DrawText3D(mBodyInterface->GetPosition(mOtherBodyID), cycle_names[mCycle], Color::sWhite, 1.0f);
  45. }
  46. void SoftBodyContactListenerTest::StartCycle()
  47. {
  48. // Create the cloth
  49. Ref<SoftBodySharedSettings> cloth_settings = SoftBodyCreator::CreateClothWithFixatedCorners(15, 15, 0.75f);
  50. // Create cloth that's fixated at the corners
  51. SoftBodyCreationSettings cloth(cloth_settings, RVec3(0, 5, 0), Quat::sRotation(Vec3::sAxisY(), 0.25f * JPH_PI), Layers::MOVING);
  52. cloth.mUpdatePosition = false; // Don't update the position of the cloth as it is fixed to the world
  53. cloth.mMakeRotationIdentity = false; // Test explicitly checks if soft bodies with a rotation collide with shapes properly
  54. mSoftBodyID = mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
  55. // Create sphere
  56. BodyCreationSettings bcs(new SphereShape(1.0f), RVec3(0, 7, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
  57. bcs.mOverrideMassProperties = EOverrideMassProperties::CalculateInertia;
  58. bcs.mMassPropertiesOverride.mMass = 100.0f;
  59. mOtherBodyID = mBodyInterface->CreateAndAddBody(bcs, EActivation::Activate);
  60. }
  61. SoftBodyValidateResult SoftBodyContactListenerTest::OnSoftBodyContactValidate(const Body &inSoftBody, const Body &inOtherBody, SoftBodyContactSettings &ioSettings)
  62. {
  63. switch (mCycle)
  64. {
  65. case 0:
  66. // Normal
  67. return SoftBodyValidateResult::AcceptContact;
  68. case 1:
  69. // Makes the sphere 10x as heavy
  70. ioSettings.mInvMassScale2 = 0.1f;
  71. ioSettings.mInvInertiaScale2 = 0.1f;
  72. return SoftBodyValidateResult::AcceptContact;
  73. case 2:
  74. // Makes the cloth 10x as heavy
  75. ioSettings.mInvMassScale1 = 0.1f;
  76. return SoftBodyValidateResult::AcceptContact;
  77. case 3:
  78. // Makes the sphere have infinite mass
  79. ioSettings.mInvMassScale2 = 0.0f;
  80. ioSettings.mInvInertiaScale2 = 0.0f;
  81. return SoftBodyValidateResult::AcceptContact;
  82. case 4:
  83. // Makes the cloth have infinite mass
  84. ioSettings.mInvMassScale1 = 0.0f;
  85. return SoftBodyValidateResult::AcceptContact;
  86. case 5:
  87. // Sensor contact
  88. ioSettings.mIsSensor = true;
  89. return SoftBodyValidateResult::AcceptContact;
  90. default:
  91. // No contacts
  92. return SoftBodyValidateResult::RejectContact;
  93. }
  94. }
  95. void SoftBodyContactListenerTest::OnSoftBodyContactAdded(const Body &inSoftBody, const SoftBodyManifold &inManifold)
  96. {
  97. // Draw contacts
  98. RMat44 com = inSoftBody.GetCenterOfMassTransform();
  99. for (const SoftBodyVertex &vertex : inManifold.GetVertices())
  100. if (inManifold.HasContact(vertex))
  101. {
  102. RVec3 position = com * inManifold.GetLocalContactPoint(vertex);
  103. Vec3 normal = inManifold.GetContactNormal(vertex);
  104. mDebugRenderer->DrawMarker(position, Color::sRed, 0.1f);
  105. mDebugRenderer->DrawArrow(position, position + normal, Color::sGreen, 0.1f);
  106. }
  107. }