SoftBodyCosseratRodConstraintTest.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2025 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <TestFramework.h>
  5. #include <Tests/SoftBody/SoftBodyCosseratRodConstraintTest.h>
  6. #include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
  7. #include <Jolt/Physics/SoftBody/SoftBodyMotionProperties.h>
  8. #include <Utils/SoftBodyCreator.h>
  9. #include <Layers.h>
  10. #include <Renderer/DebugRendererImp.h>
  11. JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyCosseratRodConstraintTest)
  12. {
  13. JPH_ADD_BASE_CLASS(SoftBodyCosseratRodConstraintTest, Test)
  14. }
  15. void SoftBodyCosseratRodConstraintTest::Initialize()
  16. {
  17. CreateFloor();
  18. // Create a hanging helix
  19. {
  20. constexpr float cRadius = 0.5f;
  21. constexpr int cNumVertices = 128;
  22. constexpr float cHeight = 5.0f;
  23. constexpr float cNumCycles = 10;
  24. Ref<SoftBodySharedSettings> helix_settings = new SoftBodySharedSettings;
  25. for (int i = 0; i < cNumVertices; ++i)
  26. {
  27. float fraction = float(i) / (cNumVertices - 1);
  28. SoftBodySharedSettings::Vertex v;
  29. float alpha = cNumCycles * 2.0f * JPH_PI * fraction;
  30. v.mPosition = Float3(cRadius * Sin(alpha), 0.5f * (1.0f - fraction * cHeight), cRadius * Cos(alpha));
  31. v.mInvMass = i == 0? 0.0f : 1.0e-2f;
  32. helix_settings->mVertices.push_back(v);
  33. if (i > 0)
  34. helix_settings->mRodStretchShearConstraints.push_back(SoftBodySharedSettings::RodStretchShear(i - 1, i));
  35. if (i > 1)
  36. helix_settings->mRodBendTwistConstraints.push_back(SoftBodySharedSettings::RodBendTwist(i - 2, i - 1));
  37. }
  38. helix_settings->CalculateRodProperties();
  39. helix_settings->Optimize();
  40. SoftBodyCreationSettings helix(helix_settings, RVec3(0, 10, 0), Quat::sIdentity(), Layers::MOVING);
  41. mSoftBodies.push_back(mBodyInterface->CreateAndAddSoftBody(helix, EActivation::Activate));
  42. }
  43. // Create a tree with a static root
  44. {
  45. // Root particle
  46. Ref<SoftBodySharedSettings> tree_settings = new SoftBodySharedSettings;
  47. SoftBodySharedSettings::Vertex v;
  48. v.mPosition = Float3(0, 0, 0);
  49. v.mInvMass = 0.0f;
  50. tree_settings->mVertices.push_back(v);
  51. // Create branches
  52. struct Branch
  53. {
  54. uint32 mPreviousVertex;
  55. uint32 mPreviousRod;
  56. Vec3 mDirection;
  57. uint32 mDepth;
  58. };
  59. Array<Branch> branches;
  60. branches.push_back({ 0, uint32(-1), Vec3::sAxisY(), 0 });
  61. while (!branches.empty())
  62. {
  63. // Take the next branch
  64. Branch branch = branches.front();
  65. branches.erase(branches.begin());
  66. // Create vertex
  67. SoftBodySharedSettings::Vertex &previous_vertex = tree_settings->mVertices[branch.mPreviousVertex];
  68. (Vec3(previous_vertex.mPosition) + branch.mDirection).StoreFloat3(&v.mPosition);
  69. v.mInvMass = branch.mDepth > 0? 2.0f * previous_vertex.mInvMass : 1.0e-3f;
  70. uint32 new_vertex = uint32(tree_settings->mVertices.size());
  71. tree_settings->mVertices.push_back(v);
  72. // Create rod
  73. uint32 new_rod = uint32(tree_settings->mRodStretchShearConstraints.size());
  74. tree_settings->mRodStretchShearConstraints.push_back(SoftBodySharedSettings::RodStretchShear(branch.mPreviousVertex, new_vertex));
  75. if (branch.mPreviousRod != uint32(-1))
  76. tree_settings->mRodBendTwistConstraints.push_back(SoftBodySharedSettings::RodBendTwist(branch.mPreviousRod, new_rod));
  77. // Create sub branches
  78. if (branch.mDepth < 10)
  79. for (uint32 i = 0; i < 2; ++i)
  80. {
  81. // Determine new child direction
  82. float angle = DegreesToRadians(-15.0f + i * 30.0f);
  83. Vec3 new_direction = Quat::sRotation(branch.mDepth & 1? Vec3::sAxisZ() : Vec3::sAxisX(), angle) * branch.mDirection;
  84. // Create new branch
  85. branches.push_back({ new_vertex, new_rod, new_direction, branch.mDepth + 1 });
  86. }
  87. }
  88. tree_settings->CalculateRodProperties();
  89. tree_settings->Optimize();
  90. SoftBodyCreationSettings tree(tree_settings, RVec3(10, 0, 0), Quat::sIdentity(), Layers::MOVING);
  91. mSoftBodies.push_back(mBodyInterface->CreateAndAddSoftBody(tree, EActivation::Activate));
  92. }
  93. }
  94. void SoftBodyCosseratRodConstraintTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
  95. {
  96. // Draw the soft body rods
  97. for (BodyID id : mSoftBodies)
  98. {
  99. BodyLockRead lock(mPhysicsSystem->GetBodyLockInterface(), id);
  100. if (lock.Succeeded())
  101. {
  102. const Body &body = lock.GetBody();
  103. const SoftBodyMotionProperties *mp = static_cast<const SoftBodyMotionProperties *>(body.GetMotionProperties());
  104. RMat44 com = body.GetCenterOfMassTransform();
  105. for (const SoftBodySharedSettings::RodStretchShear &r : mp->GetSettings()->mRodStretchShearConstraints)
  106. {
  107. RVec3 x0 = com * mp->GetVertex(r.mVertex[0]).mPosition;
  108. RVec3 x1 = com * mp->GetVertex(r.mVertex[1]).mPosition;
  109. mDebugRenderer->DrawLine(x0, x1, Color::sWhite);
  110. }
  111. }
  112. }
  113. }